CMakeLists学习一、find_package查找包

前言

很久之前就想写关于CMakeLists相关的学习记录,但当时的重点在数学基础内容上,这一块就搁置了,现在重新记录一下。

首先就是cmake中查找第三方包指令find_package()的原理

引例

图像相关的工程中,最常用的第三方包OpenCV需要通过CMakeLists来配置,常见写法如下:

find_package(OpenCV 4 REQUIRED)

include_directories(${OpenCV_INCLUDE_DIRS})

add_executable(main src/main.cpp)
target_link_libraries(main ${OpenCV_LIBRARIES})

上面的配置中,find_package从目录中寻找OpenCV,找到后将头文件目录设置为${OpenCV_INCLUDE_DIRS},库文件设为${OpenCV_LIBRARIES},然后在工程中包含OpenCV头文件目录,生成可执行文件,最后链接OpenCV库。

环境变量

首先需要知道本机的环境变量,可以使用export命令显示所有环境变量:

export

也可以使用echo命令显示某个环境变量,比如PATH:

echo $PATH

find_package查询路径

cmake设置第三方包的头文件目录和库文件位置,是通过查询.cmake文件实现的,有两种命名形式,Find<Package>.cmake或者<Package>Config.cmake

.cmake文件一般在第三方包编译和安装时会自动安装到$CMAKE_PREFIX_PATH/lib/cmake/等文件夹中,比如/usr/lib/cmake//usr/local/lib/cmake等等。

find_package()的工作就是在特定路径下查找第三方包.cmake文件。这些路径包括设定查询路径默认查询路径

设定查询路径

设定查询路径通过cmake中的CMAKE_MODULE_PATH关键字设置寻找.cmake的位置:

list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")

上面的指令把工程根目录下的cmake文件夹添加为.cmake文件搜索路径,是优先搜索的路径。

另外,还可以直接设置某个包的.cmake位置:

set(OpenCV_DIR /path_to_opencv)
find_package(OpenCV)

上面的指令使find_package()寻找OpenCV时,最优先查找/path_to_opencv路径下的.cmake文件。

默认路径

如果没有设定查询路径,或者在设定查询路径没有找到合适的.cmake时,cmake继续在默认查询路径中寻找.cmake文件,这些默认查询路径有:

PATH
CMAKE_PREFIX_PATH
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH

如果PATH路径为/bin/sbin文件夹,则从上一级目录查找。

以默认路径为根目录,cmake将检查根目录下的/lib/cmake,/lib/<arch>/cmake,/share/cmake下寻找.cmake文件,根据.cmake生成对应的头文件目录和库文件路径。

链接库问题

find_package()后,include_directories()基本上不会出问题,常见问题在链接库。

还是以OpenCV为例:

find_package(OpenCV 4 REQUIRED)

include_directories(${OpenCV_INCLUDE_DIRS})

add_executable(main src/main.cpp)
target_link_libraries(main ${OpenCV_LIBRARIES})

执行cmake成功,make编译时没有找到opencv的库是很常见的报错。明明在cmake中target_link_libraries()指定了链接库,那么为什么还是会报ld错误呢?

这是因为,部分第三方包的.cmake文件提供给cmake的${<Package>_LIBRARIES}只是一个包名,比如OpenCV的就是

libopencv_calib3d
libopencv_core
...

等一大串库文件的名字,而不是路径,编译器不知道库文件的路径在哪,找不到库,自然就会报ld链接错误了。

解决方法就是给出链接库的路径,这里就涉及到一个ld问题。为了以后查询方便,ld将放在ubuntu指令学习中。

还有一个更简单但也更麻烦的链接方法:直接把需要链接的库放在Makefile的根目录下,编译器就能直接看到库文件了。

find_package()命令

最后回到find_package命令上,它的常用形式为:

find_package(<PackageName> [version] [EXACT] [QUIET] [REQUIRED])

version: 版本合适(大版本号相同)
EXACT: 版本必须一致
QUIET: 没找到包也不会报错
REQUIRED: 必须找到该包,否则停止

  • 24
    点赞
  • 102
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值