构建库时的Clang和undefined符号

时间:2014-08-21 08:19:47

标签: c++ cmake clang

我正在研究一个C ++框架,当我在使用Clang的OSX上编译它时会出现一些问题。

首先,我正在使用其他一些库,例如openssl,而clang抱怨我在构建库时没有解决某些符号。它们不应该是:这些库将与最终的二进制文件链接,它不应该发生在中介上。

然后,还有一些方法和变量应该在“客户端”二进制文件中实现...使用GCC,没有问题,但Clang也抱怨这些符号在编译期间无法解决。

为什么?我该怎么办?

这是我的CMakeLists.txt,以防有用:

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})

这是崩溃的命令:

/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 [...]

以下是我得到的两种错误:

架构x86_64的未定义符号:

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

第二个:

  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

3 个答案:

答案 0 :(得分:12)

我不建议启用全局动态查找:

-undefined dynamic_lookup 这会将所有未定义的符号标记为必须在运行时查找。

为特定符号解决此问题的更安全方法:

-Wl,-U,symbol_name,仅对给定的符号执行此操作(注意:您必须在符号名称前加下划线)

您还可以使用弱动态链接:

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

答案 1 :(得分:11)

解决了! Clang需要接收选项-undefined dynamic_lookup以在编译库时忽略缺失的符号。

将其添加到CMakeFile.txt以产生预期效果:

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 :(得分:1)

根据评论者之一,您必须使用-lcrypto来防止第一个错误。

第二个错误似乎是由于clang和gcc的ABI不兼容。使用clang ++和libc ++重建boost。请参阅SO帖子Is clang++ ABI same as g++?Why can't clang with libc++ in c++0x mode link this boost::program_options example?How to compile/link Boost with clang++/libc++?

如果您遇到其他库的链接器问题,您还应该尝试使用clang ++重建那些。

编辑:

为了指示OS X链接器允许未解析的符号,您应该将-undefined dynamic_lookup添加到链接器选项。另请参阅SO帖子Error when making dynamic lib from .o