【发布时间】:2015-07-24 01:50:42
【问题描述】:
我试图了解为什么在编译使用 CMake 生成的项目时出现链接错误。
CMakeFiles.txt 为项目的每个文件夹构建一个静态库,然后通过以下方式将它们链接在一起:
# root CMakeLists.txt
add_subdirectory(subfolder1)
add_subdirectory(subfolder2)
add_subdirectory(...)
add_executable(target ${SOURCES})
set(LIBRARIES
LIB_FOO
LIB_BAR
...
)
target_link_libraries(target
${LIBRARIES}
)
然后在每个子文件夹中我都有一个简单的 CMakeLists.txt 之类的
file(GLOB FOO_SOURCE *.cpp)
add_library(LIB_FOO ${FOO_SOURCE})
现在这可以正常工作并编译一切正常,但在链接时我得到一个未定义的引用,所以我试图调查最后是否一切都可用,看起来像这样。实际错误如下:
libLIB_WORLD.a(World.cpp.o): In function `World::generate(WorldGenOptions)':
World.cpp:(.text+0x803): undefined reference to `MapGenerator::MapGenerator(BlockMap*)'
World.cpp:(.text+0x837): undefined reference to `MapGenerator::generate(bool, WorldGenOptions)'
现在,MapGenerator.cpp 是LIB_MAP 的一部分,所以我检查了文件是否存在并包含符号:
:~$ nm libLIB_MAP.a | grep generate
....
00000000000044dc T _ZN12MapGenerator8generateEb15WorldGenOptions
:~$ nm CMakeFiles/LIB_MAP.dir/MapGenerator.cpp.o | grep generate
....
00000000000044dc T _ZN12MapGenerator8generateEb15WorldGenOptions
所以符号是存在的,此时我检查了它是否被 ld 正确链接:
:~$ make VERBOSE=1
/usr/bin/g++ ... libLIB_MAP.a libLIB_WORLD.a ...
因此它实际上与无法找到该符号的其他库一起存在于链接阶段。
我缺少什么微不足道的东西吗?我对 CMake 很陌生,所以我没有想法。
【问题讨论】:
-
您可能需要检查为链接器提供的库的顺序
-
@Steephen:顺序是问题末尾
VERBOSE=1写的那个,LIB_MAP链接在LIB_WORLD之前 -
@Steephen:交换 LIB_MAP 和 LIB_WORLD 的顺序似乎已经解决了这个问题。所以世界(需要地图)在另一个之前链接。
-
@Steephen 我只是减少了调用,因为它链接了 40-50 个库 + 15 个共享库,我想专注于这个问题。
-
CMake 通常会take care of the correct order of libraries passed to the linker,但我仍然建议使用
--start-group--end-grouplinker options for the GNU toolchain。它增加了链接时间,但是在某个地方有这么多库甚至可能是循环依赖。
标签: c++ linker cmake static-libraries