Cmake 无法使用“link_directories"找到库

2021-12-26 00:00:00 makefile cmake c++

我是 Ubuntu,我正在学习 cmake 和 make,只是尝试了一个简单的例子.我有两个目录:srcbuild.在 src 中,我有两个文件:main.cppCMakeLists.txt,其中(仅)包含以下文本:

add_executable(test main.cpp)链接目录(/usr/lib/x86_64-linux-gnu)target_link_libraries(测试protobuf)

/usr/lib/x86_64-linux-gnu 中,有一个名为 libprotobuf.so 的共享库,我想链接它.我的 main.cpp 通过包含相关头文件 #include <google/protobuf/message.h> 使用此库中的函数.

现在,在我的 build 目录中,我运行 cmake ../src,然后运行 ??make.但是,我随后收到链接器错误,告诉我对 protobuf 库中的某些函数存在未定义的引用.如果我搜索 build 中的所有文件和子目录,则没有提到与 protobuf 相关的任何内容.

但是,如果我删除 CMakeLists.txt 文件中的 link_directories 行,而是在指定可执行文件时写入库的完整路径,即 target_link_libraries(test/usr/lib/x86_64-linux-gnu/libprotobuf.so),它编译和链接正常.

为什么 link_directories 不允许 cmake 找到这个库?

解决方案

不要在 CMake 中像这样使用 link_directories.

这是一个常见的初学者错误,因为许多其他构建环境都是这样工作的,但在 CMake 中它只是自找麻烦.甚至手册页也特别反对它:

<块引用>

请注意,此命令 [link_directories] 很少需要.图书馆位置返回by find_package()find_library() 是绝对路径.通过这些直接到 target_link_libraries() 的绝对库文件路径命令.CMake 将确保链接器找到它们.

因此,总是将绝对路径传递给 target_link_libraries 并使用 find_library 解析链接目录:

find_library(PROTOBUF_LIBRARY protobuf HINTS/usr/lib/x86_64-linux-gnu)目标链接库(测试 PUBLIC ${PROTOBUF_LIBRARY})

这有一个巨大的好处,如果找不到预期的库,您可能会在 CMake 配置时得到诊断,而不是在编译时出现随机链接器错误.此外,如果目标机器具有非标准目录布局,这允许用户通过 GUI 指定库位置.

因此,如果它不能立即工作,请务必检查 find_library 调用的结果并查阅联机帮助页以找出它没有按预期找到您的库的原因.

I Ubuntu, I am learning about cmake and make, and just trying a simple example. I have two directories: src and build. In src, I have two files: main.cpp, and CMakeLists.txt, which has (only) the following text:

add_executable(test main.cpp)
link_directories(/usr/lib/x86_64-linux-gnu)
target_link_libraries(test protobuf)

In /usr/lib/x86_64-linux-gnu, there is a shared library called libprotobuf.so, which I want to link against. My main.cpp uses functions in this library, by including the releveant header file, #include <google/protobuf/message.h>.

Now, in my build directory, I run cmake ../src, and then make. However, I then get linker errors telling me that there are undefined references to some of the functions in the protobuf library. If I do a search through all the files and subdirectories in build, there is not mention of anything related to protobuf.

However, if I remove the link_directories line in my CMakeLists.txt file, and instead write the full path to the library when specifying the executable, i.e. target_link_libraries(test /usr/lib/x86_64-linux-gnu/libprotobuf.so), it compiles and links fine.

Why is link_directories not allowing cmake to find this library?

解决方案

Do not use link_directories like this in CMake.

This is a common beginner's mistake, as many other build environments work like this, but in CMake it's just asking for trouble. Even the manpage specifically advises against it:

Note that this command [link_directories] is rarely necessary. Library locations returned by find_package() and find_library() are absolute paths. Pass these absolute library file paths directly to the target_link_libraries() command. CMake will ensure the linker finds them.

So instead, always pass absolute paths to target_link_libraries and use find_library to resolve the link directory:

find_library(PROTOBUF_LIBRARY protobuf HINTS /usr/lib/x86_64-linux-gnu)
target_link_libraries(test PUBLIC ${PROTOBUF_LIBRARY})

This has the huge benefit that you will probably get a diagnostic at CMake configure time if the expected library cannot be found, instead of a random linker error at compile time. Also, this allows the user to specify a library location via the GUI if the target machine has a non-standard directory layout.

So if it doesn't work right away, be sure to check the result of the find_library call and consult the manpage to track down why it doesn't find your library as intended.

相关文章