Linker error with branch 4638 wrapper library in macOS

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Linker error with branch 4638 wrapper library in macOS

Postby mic » Wed Nov 03, 2021 11:38 pm

I have created an Xcode 12.5.1 project that basically duplicates the functionality of the cefsimple demo app in branch 4638, but without using CMake for the build. I have done this successfully with numerous earlier branches, always as a first step toward integrating the new branch with custom code.

When I do this, I am always careful to follow the various build settings from the cefsimple Xcode project in the binary distribution, as far as possible. Usually, I experience no difficulties, and the resulting app works as expected.

However, this time I am encountering a linker error I don't understand:

Code: Select all
Showing All Messages
Ld /cef-source-4638/xcode12.5.1/CEF3CustomSample/build/Release/CEF3CustomSample.app/Contents/MacOS/CEF3CustomSample normal (in target 'CEF3CustomSample' from project 'CEF3CustomSample')
    cd /cef-source-4638/xcode12.5.1/CEF3CustomSample
    /Applications/Xcode12.5.1/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -target x86_64-apple-macos10.11 -isysroot /Applications/Xcode12.5.1/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk -L/cef-source-4638/xcode12.5.1/CEF3CustomSample/build/Release -L/cef-source-4638/xcode12.5.1/CEF3CustomSample/cef/lib -F/cef-source-4638/xcode12.5.1/CEF3CustomSample/build/Release -filelist /cef-source-4638/xcode12.5.1/CEF3CustomSample/build/CEF3CustomSample.build/Release/CEF3CustomSample.build/Objects-normal/x86_64/CEF3CustomSample.LinkFileList -dead_strip -Wl,-search_paths_first -Wl,-ObjC -Wl,-pie -Wl,-dead_strip -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lpthread -lcef_dll_wrapper -framework Cocoa -framework AppKit -Xlinker -dependency_info -Xlinker /cef-source-4638/xcode12.5.1/CEF3CustomSample/build/CEF3CustomSample.build/Release/CEF3CustomSample.build/Objects-normal/x86_64/CEF3CustomSample_dependency_info.dat -o /cef-source-4638/xcode12.5.1/CEF3CustomSample/build/Release/CEF3CustomSample.app/Contents/MacOS/CEF3CustomSample

Undefined symbols for architecture x86_64:
  "base::cef_subtle::RefCountedThreadSafeBase::~RefCountedThreadSafeBase()", referenced from:
      base::internal::BindState<void (SimpleHandler::*)(bool), scoped_refptr<SimpleHandler>, bool>::Destroy(base::internal::BindStateBase const*) in simple_handler.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)


This is the affected line of code (from simple_handler.cpp):

Code: Select all
CefPostTask(TID_UI, base::BindOnce(&SimpleHandler::CloseAllBrowsers, this, force_close));


This same line of code occurs in the cefsimple demo app, but there it does not produce the linker error.

The undefined symbol "~RefCountedThreadSafeBase" is defined in the CEF wrapper library:

include/base/cef_ref_counted.h
Code: Select all
...
namespace base {
namespace cef_subtle {
...
class RefCountedThreadSafeBase {
...
 protected:
...
#if DCHECK_IS_ON()
  ~RefCountedThreadSafeBase();
#else
  ~RefCountedThreadSafeBase() = default;
#endif
...


libcef_dll/base/cef_ref_counted.cc
Code: Select all
...
namespace base {
...
namespace cef_subtle {
...
#if DCHECK_IS_ON()
RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
  DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
                      "calling Release()";
}
#endif
...


If I link with the debug version of the CEF wrapper library, the linker error does not occur.

So far, the only way I have found to address this problem is to modify the CEF include file and wrapper library as follows:

include/base/cef_ref_counted.h:
Code: Select all
...
namespace base {
namespace cef_subtle {
...
class RefCountedThreadSafeBase {
...
 protected:
...
// modified to prevent linker error
//#if DCHECK_IS_ON()
//  ~RefCountedThreadSafeBase();
//#else
//  ~RefCountedThreadSafeBase() = default;
//#endif
  ~RefCountedThreadSafeBase();
...


libcef_dll/base/cef_ref_counted.cc
Code: Select all
...
namespace base {
...
namespace cef_subtle {
...
// modified to prevent linker error
//#if DCHECK_IS_ON()
//RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
//  DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
//                      "calling Release()";
//}
//#endif
RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
#if DCHECK_IS_ON()
  DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
                      "calling Release()";
#endif
}
...


These changes ensure there is at least an empty constructor in the release build, which is apparently enough to satisfy the linker.

I cannot determine why this issue occurs only for this one single symbol, nor why it does not occur in the cefsimple Xcode project in the binary distribution, when linking with the same library file. I don't even know why it does not occur when linking with the debug version of the library.

Can anyone help me to determine what the problem might be? I would greatly appreciate any assistance with identifying the cause of this error, or how to prevent it without modifying CEF code or being forced to link with the debug version of the wrapper library.
mic
Mentor
 
Posts: 82
Joined: Fri Jan 29, 2016 12:59 pm

Re: Linker error with branch 4638 wrapper library in macOS

Postby mic » Thu Nov 04, 2021 9:56 am

Clang mangles C++ names according to the Itanium IA64 ABI specification, and this link:

https://itanium-cxx-abi.github.io/cxx-a ... -ctor-dtor

specifies that the destructor name will be followed by one of the following sequences:

::= D0 # deleting destructor
::= D1 # complete object destructor
::= D2 # base object destructor

So, I concluded that searching for "RefCountedThreadSafeBaseD" in the wrapper library symbols should reveal the available destructors:

Code: Select all
% nm Release/libcef_dll_wrapper.a | grep RefCountedThreadSafeBaseD
Release/libcef_dll_wrapper.a:cef_lock.o: no symbols
Release/libcef_dll_wrapper.a:libcef_dll_wrapper2.o: no symbols

% nm Debug/libcef_dll_wrapper.a | grep RefCountedThreadSafeBaseD     
0000000000000210 T __ZN4base10cef_subtle24RefCountedThreadSafeBaseD1Ev
00000000000000b0 T __ZN4base10cef_subtle24RefCountedThreadSafeBaseD2Ev
                 U __ZN4base10cef_subtle24RefCountedThreadSafeBaseD2Ev
                 U __ZN4base10cef_subtle24RefCountedThreadSafeBaseD2Ev
                 U __ZN4base10cef_subtle24RefCountedThreadSafeBaseD2Ev
                 U __ZN4base10cef_subtle24RefCountedThreadSafeBaseD2Ev
                 U __ZN4base10cef_subtle24RefCountedThreadSafeBaseD2Ev
Debug/libcef_dll_wrapper.a:libcef_dll_wrapper2.o: no symbols


You can see from the above that the release version of the library contains no symbols for the "RefCountedThreadSafeBase" destructor, while the debug version of the library contains several. Only the first two are defined, one of which is a complete object destructor, and one of which is a base object destructor.

So, with my limited understanding I can see why the linker error would occur only with the release version of the library, and why my workaround avoids the problem, but not why it is avoided in the cefsimple app. I can find no setting that would seem to provide this magical immunity from the missing library symbol.

Any ideas?
mic
Mentor
 
Posts: 82
Joined: Fri Jan 29, 2016 12:59 pm

Re: Linker error with branch 4638 wrapper library in macOS

Postby magreenblatt » Thu Nov 04, 2021 10:19 am

Are you building libcef_dll_wrapper as part of your non-CMake config?
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: Linker error with branch 4638 wrapper library in macOS

Postby mic » Thu Nov 04, 2021 10:47 am

No, first I use the standard Xcode projects with CEF binary distribution to create the framework and wrapper library, then I copy them to the build for the external project. I am trying to link statically with the pre-generated wrapper library. I can confirm the presence or absence of the necessary symbols in the file I am linking with, and the linker error follows these results.

Not only can I not determine why the cefsimple project does not have the same error, I can't even determine why the debug version of the wrapper library includes the missing symbols. I can't find any setting in the wrapper library project that will control this, yet the debug build will produce the symbols and the release build will not.
mic
Mentor
 
Posts: 82
Joined: Fri Jan 29, 2016 12:59 pm

Re: Linker error with branch 4638 wrapper library in macOS

Postby mic » Thu Nov 04, 2021 11:14 am

I can also verify that the missing symbols are present in the object files used to create the debug version of the wrapper library, but not in the object files used to create the release version of the library:

Code: Select all
% cd <debug objects output folder>
% nm cef_ref_counted.o | grep RefCountedThreadSafeBaseD
0000000000000210 T __ZN4base10cef_subtle24RefCountedThreadSafeBaseD1Ev
00000000000000b0 T __ZN4base10cef_subtle24RefCountedThreadSafeBaseD2Ev
% nm cef_ref_counted.o | grep RefCountedThreadSafeBase
0000000000000210 T __ZN4base10cef_subtle24RefCountedThreadSafeBaseD1Ev
00000000000000b0 T __ZN4base10cef_subtle24RefCountedThreadSafeBaseD2Ev
0000000000000050 T __ZNK4base10cef_subtle24RefCountedThreadSafeBase16HasAtLeastOneRefEv
0000000000000000 T __ZNK4base10cef_subtle24RefCountedThreadSafeBase9HasOneRefEv

% cd <release objects output folder>
% nm cef_ref_counted.o | grep RefCountedThreadSafeBaseD
% nm cef_ref_counted.o | grep RefCountedThreadSafeBase
0000000000000010 T __ZNK4base10cef_subtle24RefCountedThreadSafeBase16HasAtLeastOneRefEv
0000000000000000 T __ZNK4base10cef_subtle24RefCountedThreadSafeBase9HasOneRefEv


What I can't seem to figure out is how or why.
mic
Mentor
 
Posts: 82
Joined: Fri Jan 29, 2016 12:59 pm

Re: Linker error with branch 4638 wrapper library in macOS

Postby magreenblatt » Thu Nov 04, 2021 11:18 am

DCHECK_IS_ON() likely returns true for the Debug build only. Check how that is defined, and identify why it’s not getting the correct value in your non-CMake build.
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: Linker error with branch 4638 wrapper library in macOS

Postby mic » Thu Nov 04, 2021 12:19 pm

Thank you sir, that was the clue I needed.

The following symbol output seemed to frame my dilemma:

Code: Select all
% cd <my project output objects folder>
% nm simple_handler.o | grep RefCountedThreadSafeBase
                 U __ZN4base10cef_subtle24RefCountedThreadSafeBaseD2Ev
                 U __ZNK4base10cef_subtle24RefCountedThreadSafeBase9HasOneRefEv

% cd <cefsimple output objects folder>
% nm simple_handler.o | grep RefCountedThreadSafeBase
%


As you can see from the above, my project's "simple_handler.o" object file references two undefined symbols, while the corresponding object file in the cefsimple project does not.

Why should this be? As far as I could tell, the source files were identical, as were the Xcode build settings.

Except that the Xcode build settings were not identical, because "NDEBUG" was not defined. This CEF-specific define is not something I have ever needed to include in the past when only compiling CEF headers, so I did not do so this time.

However, this time the omission caused "DCHECK_IS_ON()" (include/base/cef_logging.h) to be defined for my project's "simple_handler" translation unit, which caused the "RefCountedThreadSafeBase" destructor to be declared in "cef_ref_counted.h" with no implementation. Since the release version of the wrapper library had been compiled with "NDEBUG" defined, "DCHECK_IS_ON()" was not defined, so it did not include any implementation for the "RefCountedThreadSafeBase" destructor, thus the symbol was missing so far as the linker was concerned.

Adding the "NDEBUG" definition to my project's compile settings fixed the problem. Thank you for helping me restore sanity to my existence.
mic
Mentor
 
Posts: 82
Joined: Fri Jan 29, 2016 12:59 pm


Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 187 guests