Jac*_*ack 4 c++ linker cmake static-libraries
我试图理解为什么在编译用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}
)
Run Code Online (Sandbox Code Playgroud)
然后在每个子文件夹中我都有一个简单的CMakeLists.txt之类的
file(GLOB FOO_SOURCE *.cpp)
add_library(LIB_FOO ${FOO_SOURCE})
Run Code Online (Sandbox Code Playgroud)
现在这个工作并编译好一切但我在链接时得到一个未定义的引用,所以我试着调查一下最后是否所有内容都可用,它看起来就是这样.实际错误如下:
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)'
Run Code Online (Sandbox Code Playgroud)
现在,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
Run Code Online (Sandbox Code Playgroud)
所以符号存在,此时我检查它是否被ld正确链接:
:~$ make VERBOSE=1
/usr/bin/g++ ... libLIB_MAP.a libLIB_WORLD.a ...
Run Code Online (Sandbox Code Playgroud)
所以它实际上存在于链接阶段和其他无法找到符号的库中.
有什么小事我不见了吗?我对CMake很新,所以我没有想法.
这是在CMake中未正确建模的库依赖性问题.
你的LIB_WORLD参考方法来自LIB_MAP.此依赖关系未在CMake脚本中建模.由于这两个都是静态库,它们仍然可以自行构建.(请记住,静态库本质上是一堆打包在一起的目标文件,但它们从不通过链接器.)
但是,只要将它们链接到可执行文件或共享库,就会出现问题.即使你对两个可执行文件链接LIB_WORLD和LIB_MAP时,它是在错误的顺序.因此,当链接器尝试解析缺失的符号时LIB_WORLD,它还不知道导出的符号LIB_MAP,因此您遇到的错误消息.
正确的解决方法是引入依赖LIB_WORLD:
add_library(LIB_WORLD [...])
target_link_libraries(LIB_WORLD LIB_MAP)
Run Code Online (Sandbox Code Playgroud)
现在,无论何时你链接的东西,LIB_WORLD你总是会链接LIB_MAP,CMake会注意订单是正确的.(特别是,如果您的可执行文件没有直接使用LIB_MAP您的方法,则可能希望将其从中target_link_libraries完全删除.)
作为一个额外的好处,它现在允许您构建LIB_WORLD为共享库,之前会因链接器错误而失败.
| 归档时间: |
|
| 查看次数: |
6915 次 |
| 最近记录: |