CMake:使静态库有效,但动态无效
Posted
技术标签:
【中文标题】CMake:使静态库有效,但动态无效【英文标题】:CMake: Make a static library works but dynamic doesn't 【发布时间】:2019-03-01 01:47:02 【问题描述】:我正在尝试使用 CMake 制作一个共享库,但如果我静态制作它,它会运行良好,但动态不会:
CMAKE_MINIMUM_REQUIRED(VERSION 3.6)
PROJECT(TestDemo)
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_COMPILER clang++)
# Headers
INCLUDE_DIRECTORIES(src)
INCLUDE_DIRECTORIES(src/xxx)
INCLUDE_DIRECTORIES(3rdparty/zstd)
INCLUDE_DIRECTORIES(/usr/local/include)
# CORE LIB
FILE(GLOB CORE_SRC src/xxx/*.cpp
src/xxx/io/*.cpp
src/xxx/util/*.cpp
src/xxx/thread/*.cpp)
LIST(REMOVE_ITEM CORE_SRC $CMAKE_CURRENT_SOURCE_DIR/src/xxx/io/BzipStream.cpp
$CMAKE_CURRENT_SOURCE_DIR/src/xxx/io/GzipStream.cpp)
# This works
ADD_LIBRARY(xxx-core STATIC $CORE_SRC)
# This doesn't
#ADD_LIBRARY(xxx-core SHARED $CORE_SRC)
错误信息是:
[100%] Linking CXX shared library libxxxdb-core.dylib
Undefined symbols for architecture x86_64:
"_mpool_get_global", referenced from:
xxx::mpoolxx<xxx::alloc_to_mpool_bridge<xxx::mpoolxx<long>, 1>::MemBlock>::get_vtab() in trb_cxx.cpp.o
"_sfixed_mpool_destroy", referenced from:
xxx::fixed_mpool_wrapper<24>::~fixed_mpool_wrapper() in trb_cxx.cpp.o
"_sfixed_mpool_init", referenced from:
xxx::fixed_mpool_wrapper<24>::fixed_mpool_wrapper() in trb_cxx.cpp.o
"_trb_destroy", referenced from:
xxx::trbstrmap_imp<int, unsigned char, &(xxx_trb_compare_less_tag), xxx::mpoolxx<long>, 0, 16>::~trbstrmap_imp() in trb_cxx.cpp.o
xxx::trbtab<int const, std::__1::pair<int const, int>, 0, &(xxx_trb_compare_less_tag), xxx::fixed_mpoolxx<long>, 0, 16>::~trbtab() in trb_cxx.cpp.o
"_trb_erase", referenced from:
xxx::trbtab<int const, std::__1::pair<int const, int>, 0, &(xxx_trb_compare_less_tag), xxx::fixed_mpoolxx<long>, 0, 16>::erase(int const&) in trb_cxx.cpp.o
xxx::trbtab<int const, std::__1::pair<int const, int>, 0, &(xxx_trb_compare_less_tag), xxx::fixed_mpoolxx<long>, 0, 16>::erase(xxx::trb_iterator<std::__1::pair<int const, int>, 16, 0>) in trb_cxx.cpp.o
"_trb_iter_first", referenced from:
xxx::trbtab<int const, std::__1::pair<int const, int>, 0, &(xxx_trb_compare_less_tag), xxx::fixed_mpoolxx<long>, 0, 16>::begin() const in trb_cxx.cpp.o
"_trb_iter_next", referenced from:
xxx::trb_iterator<std::__1::pair<int const, int>, 16, 0>::operator++() in trb_cxx.cpp.o
"_trb_probe", referenced from:
xxx::trbtab<int const, std::__1::pair<int const, int>, 0, &(xxx_trb_compare_less_tag), xxx::fixed_mpoolxx<long>, 0, 16>::insert(std::__1::pair<int const, int> const&) in trb_cxx.cpp.o
xxx::trbmap<int, int, &(xxx_trb_compare_less_tag), xxx::fixed_mpoolxx<long>, 0, 16>::operator[](int const&) in trb_cxx.cpp.o
"_trb_probe_node", referenced from:
xxx::trbstrmap_imp<int, unsigned char, &(xxx_trb_compare_less_tag), xxx::mpoolxx<long>, 0, 16>::probe_raw(char const*, unsigned long, char const*) in trb_cxx.cpp.o
"_trb_vtab_init", referenced from:
xxx::trbxx_vtab_init_by_cxx_type(trb_vtab*, field_type_t, int (*)(trb_vtab const*, trb_tree const*, void const*, void const*), int (*)(trb_vtab const*, trb_tree const*, void const*, void const*)) in trb_cxx.cpp.o
xxx::trbxx_vtab_init(trb_vtab*, field_type_t, int (*)(trb_vtab const*, trb_tree const*, void const*, void const*)) in trb_cxx.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
【问题讨论】:
静态库几乎是目标文件的集合,它没有真正链接,创建它时不会出现链接器错误。根据平台,共享库可能需要在链接时解析所有外部符号。这就是 Windows 中的情况。创建 Windows dll 时,您需要链接提供您在错误消息中看到的所有这些符号的库。不确定它在 Mac 上是如何工作的,但可能是一样的。 【参考方案1】:在创建静态库时不会发生链接,因为静态库
不是由链接器生成的:它只是创建的目标文件的存档
与存档者ar
。所以不能
创建静态库时出现任何未定义的引用或其他链接错误,
就像你创建一个 .tar
或 .zip
目标文件存档一样。
见static-libraries,
一个共享库,就像一个程序,是由链接器和 Mac OS/Darwin 生成的 链接器(与 GNU/Linux 链接器不同)默认情况下不允许未定义符号 共享库中的引用。
你有两个选择:
您可以指定xxx-core
依赖的所有库与其链接,
target_link_libraries
或者,您可以使用链接选项覆盖链接器的默认行为
-undefined=dynamic_lookup
,表示
共享库中未定义的引用将由加载器在运行时解析。
在您的 CMakeLists.txt 中,使用 set_target_properties
在你定义了xxx-core
目标之后:
ADD_LIBRARY(xxx-core SHARED $CORE_SRC)
SET_TARGET_PROPERTIES(xxx-core LINK_FLAGS Wl,-undefined=dynamic_lookup)
【讨论】:
以上是关于CMake:使静态库有效,但动态无效的主要内容,如果未能解决你的问题,请参考以下文章
如何使 cmake 将 D 参数传递给 ar 以可重现地构建静态库
从父 cmake 动态/静态库构建 cmake 静态库的最佳方法