Clang and undefined symbols when building a librar

2019-02-10 03:03发布

问题:

I'm working on a C++ framework, and there's a few issues when I compile it on OSX with Clang.

First of, I'm using some other libraries, such as openssl, and clang complains that some symbols aren't solved when I build the library. They shouldn't be: these libraries will be linked with the final binary, it shouldn't happen on an intermediary.

Then, there's also a few methods and variables that are supposed to be implemented in the "client" binary... with GCC, no problems, but Clang also complains that these symbols can't be solved during compilation.

How come ? What should I do ?

Here's my CMakeLists.txt in case that can be useful:

cmake_minimum_required(VERSION 2.8)

project(crails_project)

set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wno-deprecated-declarations -pedantic -DASYNC_SERVER -DSERVER_DEBUG -DUSE_MONGODB_SESSION_STORE")

find_package(cppnetlib REQUIRED)

include_directories(include /usr/local/include ${CPPNETLIB_INCLUDE_DIRS} .)

file(GLOB crails_core
     src/*.cpp)

file(GLOB crails_sql
     src/sql/*.cpp)

file(GLOB crails_mongodb
     src/mongodb/*.cpp)

add_library(crails-core    SHARED ${crails_core})
add_library(crails-sql     SHARED ${crails_sql})
add_library(crails-mongodb SHARED ${crails_mongodb})

This is the command that crashes:

/usr/bin/c++  -std=c++0x -Wall -Wno-deprecated-declarations -pedantic -DASYNC_SERVER -DSERVER_DEBUG -DUSE_MONGODB_SESSION_STORE -dynamiclib -Wl,-headerpad_max_install_names   -o libcrails-core.dylib -install_name /Users/michael/Personal/crails/build/libcrails-core.dylib CMakeFiles/crails-core.dir/src/assets.cpp.o CMakeFiles/crails-core.dir/src/cgi2params.cpp.o CMakeFiles/crails-core.dir/src/cipher.cpp.o [...]

And here are the two kinds of error I get:

Undefined symbols for architecture x86_64:

  "_BIO_ctrl", referenced from:
      Cipher::encode_base64(unsigned char*, unsigned int) const in cipher.cpp.o

And the second one:

  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for boost::detail::thread_data_base", referenced from:
      boost::detail::thread_data_base::thread_data_base() in server.cpp.o

回答1:

Solved it ! Clang needs to receive the option -undefined dynamic_lookup to ignore missing symbols when compiling a library.

Add this to the CMakeFile.txt to produce the expected effect:

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
  set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS} -undefined dynamic_lookup")
endif()


回答2:

I don't recommend to enable global dynamic lookup:

-undefined dynamic_lookup which will mark all undefined symbols as having to be looked up at runtime.

Much more safe way to resolve it for specific symbols:

-Wl,-U,symbol_name, which only does so for the given symbol (note: you have to prepend an underscore to the symbol name)

You could also use weak dynamic linking:

extern int SayHello() __attribute__((weak));


回答3:

According to one of the commenters you have to use -lcrypto to prevent the first error.

The second error seems to be due to an ABI incompatibility of clang and gcc. Rebuild boost with clang++ and libc++. See SO posts Is clang++ ABI same as g++?, Why can't clang with libc++ in c++0x mode link this boost::program_options example? and How to compile/link Boost with clang++/libc++?.

In case you run into linker troubles with other libraries you should also try to rebuild those with clang++.

Edit:

In order to instruct the OS X linker to allow unresolved symbols you should add -undefined dynamic_lookup to the linker options. See also SO post Error when making dynamic lib from .o



标签: c++ cmake clang