如何在 cmake 中正确链接库?
Posted
技术标签:
【中文标题】如何在 cmake 中正确链接库?【英文标题】:How to link library correctly in cmake? 【发布时间】:2020-07-07 16:25:34 【问题描述】:我最近在使用 yaml-cpp 库。我按照“yaml-cpp-config.cmake.in”中的配置文件,内容是
# - Config file for the yaml-cpp package
# It defines the following variables
# YAML_CPP_INCLUDE_DIR - include directory
# YAML_CPP_LIBRARIES - libraries to link against
# Compute paths
get_filename_component(YAML_CPP_CMAKE_DIR "$CMAKE_CURRENT_LIST_FILE" PATH)
set(YAML_CPP_INCLUDE_DIR "@CONFIG_INCLUDE_DIRS@")
# Our library dependencies (contains definitions for IMPORTED targets)
include("$YAML_CPP_CMAKE_DIR/yaml-cpp-targets.cmake")
# These are IMPORTED targets created by yaml-cpp-targets.cmake
set(YAML_CPP_LIBRARIES "@EXPORT_TARGETS@")
根据第 8 行和第 14 行(或评论部分),我编辑了我的 CMakeLists.txt 和 test.cpp 之类的
cmake_minimum_required(VERSION 3.5)
project(yaml_test)
find_package(yaml-cpp)
include_directories($YAML_CPP_INCLUDE_DIRS)
add_executable(yaml_test src/test.cpp)
target_link_libraries(yaml_test $YAML_CPP_LIBRARIES)
#include <yaml-cpp/yaml.h>
int main()
YAML::Node node = YAML::LoadFile("test.yaml");
return 0;
我得到了
CMakeFiles/yaml_test.dir/src/test.cpp.o: In function `main':
test.cpp:(.text+0xf9): undefined reference to `YAML::LoadFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2: error: ld returned 1 exit status
CMakeFiles/yaml_test.dir/build.make:94: recipe for target 'yaml_test' failed
make[2]: *** [yaml_test] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/yaml_test.dir/all' failed
make[1]: *** [CMakeFiles/yaml_test.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
我从undefined reference to YAML::LoadFile找到了解决方案
将我的 CMakeLists.txt 更改为
cmake_minimum_required(VERSION 3.5)
project(yaml_test)
find_package(yaml-cpp)
include_directories($YAMLCPP_INCLUDE_DIRS)
add_executable(yaml_test src/test.cpp)
target_link_libraries(yaml_test $YAMLCPP_LIBRARIES)
我可以成功构建我的代码。
我的问题是如何直接从 yaml-cpp 包的 CMakeLists.txt 或配置文件中分辨出正确的“include_directories”和“target_link_libraries”?
有人可以帮助我吗?谢谢!
【问题讨论】:
当使用YAMLCPP
变量时,您似乎引用了that answer。但是这个答案不使用find_package(yaml-cpp)
。相反,它使用宏pkg_check_modules
来获取有关yaml-cpp
包的信息,并且YAMLCPP
只是简单地传递给该宏(也就是说,您可以传递任何其他前缀,并且该前缀将用于输出变量)。但是您的第二个 sn-p 仍然使用 find_package(yaml-cpp)
,这与该答案相矛盾并且完全错误。
【参考方案1】:
我的问题是如何直接从 yaml-cpp 包的 CMakeLists.txt 或配置文件中分辨出正确的“include_directories”和“target_link_libraries”?
请务必查看配置文件,该文件由 CMake 实际使用。
例如。 yaml-cpp-config.cmake.in
只是未来yaml-cpp-config.cmake
的一个模板,但您的系统可能有相同包的其他配置文件。
CMake 将配置文件的确切路径存储在 <PackageName>_CONFIG
变量中,因此如果不确定,您可以打印此变量的值:
...
find_package(yaml-cpp)
message(STATUS "Used config file: $yaml-cpp_CONFIG")
重要提示
读取配置文件时,除了顶部的文档之外,检查set
行很有用,该行将值分配给记录的变量,如*_LIBRARY
或*_LIBRARIES
。如果该值为empty,则“config”文件可能损坏,并且很可能无法使用已记录的变量。但是您可以使用 IMPORTED 目标,见下文。
请注意,大多数“配置”文件都提供了 IMPORTED 目标以供其他代码使用。
这种机制优于使用变量*_INCLUDE_DIR
和*_LIBRARIES
。如果找不到有关使用哪个确切 IMPORTED 目标的文档,请查看配置文件中 *_LIBRARIES
变量的值:该变量可能包含 IMPORTED 目标列表,您可以尝试通过 @987654335 在代码中使用它@。
更多详情请查看find_package
documentation。
【讨论】:
嗨,齐瓦列夫。谢谢你专业的回答。但我仍然有一个问题。在我听从了你的建议之后。我发现配置文件位于 /usr/local/share/cmake/yaml-cpp。共有四个cmake文件,包括“yaml-cpp-config.cmake”、“yaml-cpp-targets.cmake”、“yaml-cpp-config-version.cmake”和“yaml-cpp-targets-noconfig.cmake” .但在“yaml-cpp-config.cmake”中,与模板配置文件的内容相同。在“yaml-cpp-config-targets.cmake”中,我找不到任何相关的词如“YAML_CPP”或“YAMLCPP”。 抱歉问了这么烦人的问题,这个问题我囤了很久...... 你只需要查看yaml-cpp-config.cmake
:只有这个脚本可以包含对用户有用的变量设置。文件 yaml-cpp-targets.cmake
和 yaml-cpp-targets-noconfig.cmake
由 CMake 生成并且相当复杂,但它们只能定义 IMPORTED 目标。文件yaml-cpp-config-version.cmake
仅用于版本检查。如果文件yaml-cpp-config.cmake
描述了变量YAML_CPP_LIBRARIES
,那么这个变量应该可以工作... set(YAML_CPP_LIBRARIES "...")
行是否为变量分配了一个非空值?
是的,我在link 中找到了解决方案,而我的 yaml-cp-config.cmake 就像你说的那样。它将空值分配给 YAML_CPP_INCLUDE_DIR 和 YAML_CPP_LIBRARIES set(YAML_CPP_LIBRARIES "")
set(YAML_CPP_INCLUDE_DIR "")
但为什么它们是空值?我通过this insturction 构建了这个库。而我做错了什么?
"但是为什么它们是空值?" - 这是 yaml-cpp 项目中的错误(?)。在linked answer 中有一个指向错误报告的链接,该链接仍然处于打开状态。以上是关于如何在 cmake 中正确链接库?的主要内容,如果未能解决你的问题,请参考以下文章