【C/C++/CMake】ubuntu系统下安装引用第三方库libyaml找不到yaml.h


一、环境说明

本项目使用Windows11+WSL功能,在编译器visual studio2022下建立CMake项目,并编译运行至Ubuntu-20.04上。
在这里插入图片描述
问题复现:在项目中引入yaml.h时一直划红线找不到该库:
在这里插入图片描述

二、安装libyaml库

官方地址:https://pyyaml.org/wiki/LibYAML
下载路径:http://pyyaml.org/download/libyaml/yaml-0.2.5.tar.gz

按照官方readme安装yaml,默认安装路径在/usr/local下:

$ bash ./configure
$ make
# sudo make install

三、.cpp文件中引入libyaml库

为排除问题,我首先新建了个test.cpp,使用最原始的办法gcc来编译。

#include <stdio.h>
#include <yaml.h>

int main(){
	int majar = -1;
    int minor = -1;
    int patch = -1;
    yaml_get_version(&major, &minor, &patch);
    printf("%d.%d.%d\n", major, minor, patch);
	return 0;
}
gcc test.cpp -o test

以上编译结果会报错找不到函数: undefined reference to `yaml_get_version’;
原因是没有链接yaml库,使用下述代码即编译成功。

gcc test.cpp -o test -lyaml

其中,-o test 表示指定输出文件名为test;-lyaml表示链接yaml库。

./test

运行test文件,能够正常输出yaml版本号,至此我认为yaml库的安装没有问题

四、CMake链接libyaml库

通过gcc编译的过程,我认识到CMake也必须链接yaml库,在一步步排查问题前我也使用过include_directories、link_directories、link_libraries等链接库的方法,但还是链接不上,最后千辛万苦求助GPT找到:find_package命令。(GPT的详细回答见下一章节)
因此,我的CMakeLists.txt最终的相关代码为:

find_package(yaml REQUIRED)
add_executable (test "test.cpp")
include_directories(/usr/local/include/yaml.h)
target_link_libraries(test /usr/local/lib/libyaml.a)

find_packageinclude_directoriestarget_link_libraries缺一不可,target_link_libraries也在链接时使用,指明链接库的名字。

其中 “/usr/local/include/yaml.h” 和 “/usr/local/lib/libyaml.a” 为Ubuntu上yaml的安装路径。

(本节在2023/4/26更新:参考文章https://blog.csdn.net/qq_19280295/article/details/127910260

五、GPT Q&A

1、find_package命令语法如下:

find_package(<package_name> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [[COMPONENTS] [component1] [component2] ...])

其中,<package_name>表示需要查找的库名。version表示要求的库版本,EXACT表示需要精确匹配版本,QUIET表示不输出查找过程中的信息,MODULE表示使用CMake模块查找库,REQUIRED表示该库是必须的,COMPONENTS表示要查找的库的组件名。
例如:

find_package(yaml REQUIRED)

该命令会在系统中查找名为yaml的库,REQUIRED表示该库是必须的。

2、find_package做了什么
在find_package查找库之后,CMake会自动设置一些变量,例如YAML_INCLUDE_DIR、YAML_LIBRARIES和YAML_FOUND等,这些变量可以在后续的命令中使用。例如,YAML_INCLUDE_DIR变量表示yaml库的头文件路径,YAML_LIBRARIES变量表示yaml库的链接选项。

3、find_library和find_path与之区别
find_library和find_path命令用于查找指定的库和头文件,而find_package命令则用于查找指定库的包。它们之间的区别在于,find_package命令会自动设置一些变量,例如包含路径、库文件路径、链接选项等,而find_library和find_path命令只是返回库文件路径和头文件路径,需要手动设置变量。此外,find_package命令还可以检查库的版本,查找库的组件等。
因此,一般情况下,我们建议使用find_package命令来查找和使用第三方库。但是,如果您只需要查找某个库的路径,而不需要设置其他变量,那么使用find_library命令可能更加简单和方便。

六、小结

虽然到最后还是没有完全搞明白include_directories、link_directories、link_libraries、find_package、find_library、find_path等命令之间的区别和用法,但是这个问题总算是暂时解决了,希望有大神可以讲解一下,或者给个思路如何系统学习这方面的知识。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐