我正在研究一个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
答案 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