与cmake链接错误 [英] Linking error with cmake

查看:175
本文介绍了与cmake链接错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解为什么在编译使用CMake生成的项目时出现链接错误.

I'm trying to understand why I get a linking error while compiling a project generated with CMake.

CMakeFiles.txt为项目的每个文件夹构建一个静态库,然后通过以下方式将所有这些链接在一起:

The CMakeFiles.txt builds a static library for each folder of the project and then link all of them together in the following way:

# 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,如

then in each subfolder I have a simple CMakeLists.txt like

file(GLOB FOO_SOURCE *.cpp)
add_library(LIB_FOO ${FOO_SOURCE})

现在这可以正常工作并且可以编译所有内容,但是在链接时我得到了一个未定义的引用,因此我尝试调查所有内容是否在最后可用,看起来像这样.实际错误如下:

Now this works and compiles everything fine but I get an undefined reference while linking, so I tried to investigate if everything was available at the end and it looks like so. The actual error is the following:

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的一部分,因此我检查了文件是否存在并包含符号:

Now, MapGenerator.cpp is part of LIB_MAP, so I checked if the file exists and contains the symbols:

:~$ nm libLIB_MAP.a | grep generate
....
00000000000044dc T _ZN12MapGenerator8generateEb15WorldGenOptions

:~$ nm CMakeFiles/LIB_MAP.dir/MapGenerator.cpp.o | grep generate
....
00000000000044dc T _ZN12MapGenerator8generateEb15WorldGenOptions

因此该符号存在,这时我检查了ld是否正确链接了该符号:

So the symbol is present, at this point I checked if it was correctly linked by ld:

:~$ make VERBOSE=1
/usr/bin/g++  ... libLIB_MAP.a libLIB_WORLD.a ...

因此它实际上与其他找不到符号的库一起存在于链接阶段.

So it is actually present in linking phase together with the other library that is not able to find the symbol.

我缺少一些琐碎的东西吗?我对CMake还是很陌生,所以我没主意.

Is there something trivial I'm missing? I'm quite new to CMake so I'm out of ideas.

推荐答案

这是库依赖关系的问题,该问题在CMake中没有正确建模.

This is a problem of a library dependency that was not modeled correctly in CMake.

您的LIB_WORLD引用了LIB_MAP中的方法.在您的CMake脚本中没有对这种依赖性进行建模.由于这两个都是静态库,因此它们仍然可以自行构建. (请记住,静态库本质上是一堆打包在一起的目标文件,但它们从未通过链接器传递.)

Your LIB_WORLD references methods from LIB_MAP. This dependency is not modeled in your CMake scripts. As both of those are static libraries, they will still build fine on their own. (Remember that static libraries are essentially a bunch of object files packed together, but they never pass through the linker.)

但是,一旦将它们链接到可执行文件或共享库,就会出现问题.即使您的可执行文件同时链接了LIB_WORLDLIB_MAP,它也会以错误的顺序 进行链接.因此,当链接器尝试解决LIB_WORLD的丢失符号时,它尚不了解LIB_MAP导出的符号,因此您会遇到错误消息.

However, as soon as you link them to an executable or a shared library, you will get the problem. Even though your executable links against both LIB_WORLD and LIB_MAP, it does so in the wrong order. So when the linker is trying to resolve the missing symbols for LIB_WORLD, it does not know yet about the symbols exported by LIB_MAP, hence the error message you experienced.

正确的解决方法是引入对LIB_WORLD的依赖关系:

The proper fix is to introduce the dependency on LIB_WORLD:

add_library(LIB_WORLD [...])
target_link_libraries(LIB_WORLD LIB_MAP)

现在,每当您针对LIB_WORLD进行链接时,您也将始终针对LIB_MAP进行链接,并且 CMake将确保顺序正确. (特别是,如果您的可执行文件未直接使用LIB_MAP中的方法,则可能希望将其从target_link_libraries中完全删除.)

Now whenever you link something against LIB_WORLD you will always also link against LIB_MAP and CMake will take care that the order is right. (In particular, if your executable does not make direct use of methods from LIB_MAP you might want to remove it from its target_link_libraries altogether.)

另一个好处是,它现在允许您将LIB_WORLD构建为共享库,该库以前会因链接器错误而失败.

As an additional benefit, it now allows you to build LIB_WORLD as a shared library, which would have failed with a linker error before.

这篇关于与cmake链接错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆