前言:
CMake给我们提供了find_package()命令用来查找依赖包,理想情况下,一句find_package()命令就能把一整个依赖包的头文件包含路径、库路径、库名字、版本号等情况都获取到,后续只管用就好了。但实际使用过程可能会出现这样那样的问题,因此需要我们对find_package这个强大的命令有个大概的理解。
在进行find_package()探索之前,先熟悉一下我们使用源码安装第三方库的流程。
源码安装流程
以OpenCV 3.4.20 为例,源码安装的流程为:
mkdir build
cd build
cmake ..
make -j8
sudo make install
其中将cmake .. 更换成以下指令,然后 make install 就可以指定第三方库的安装位置。
cmake -DCMAKE_INSTALL_PREFIX=安装路径 ..
在build文件夹中make之后,生成的库文件都在build文件夹内,通过make install 命令又安装到了系统根目录下。因此在安装完库后,如果不删除源码,系统中将会有两个地方存着库的文件(根目录和build文件)。
下面来看一下,指定安装位置和不指定安装位置,库都安装在了哪里。
一般安装库文件后关于库的相关内容会存放在4个子文件夹中,bin、include、lib、share。
<package_name>Config.cmake 文件的安装目录:
- 在指定安装目录的情况下,<package_name>Config.cmake一般会存放在share文件夹下。
- 默认不指定安装目录的情况下, <package_name>Config.cmake可能会被安装在
/usr/local/lib/cmake
或/usr/lib/cmake
目录下,具体取决于系统的配置和权限设置。- 使用命令行安装的情况下, <package_name>Config.cmake一般会被安装在
/usr/lib/x86_64-linux-gnu/cmake目录下
find_package命令搜包过程
find_package是为了得到这三个变量的值:<PackageName>_DIR
、<PackageName>_INCLUDE_DIRS
和<PackageName>_LIBS,这三个变量的值可以通过搜索Find<PackageName>.cmake或<PackageName>Config.cmake
或<lower-case-package-name>-config.cmake得到。
find_package
命令有两种工作模式,这两种工作模式的不同决定了其搜包路径的不同:
1. Module模式
find_package命令基础工作模式(Basic Signature),也是默认工作模式。
Module模式下是要查找到名为Find<PackageName>.cmake
的配置文件。
搜包路径依次为:
CMAKE_MODULE_PATH
CMAKE_ROOT
先在CMAKE_MODULE_PATH变量对应的路径中查找。如果路径为空,或者路径中查找失败,则在CMake安装目录(即CMAKE_ROOT变量)下的Modules目录下(通常为/usr/share/cmake-3.16/Modules
,3.16是我的CMake版本)查找。
其中CMAKE_MODULE_PATH默认为空,可以利用set
命令赋值。
2. Config模式
find_package命令高级工作模式(Full Signature)。 只有在find_package()中指定CONFIG、NO_MODULE等关键字,或者Module模式查找失败后才会进入到Config模式。
Config模式下是要查找名为<PackageName>Config.cmake
或<lower-case-package-name>-config.cmake
的模块文件。
搜包路径依次为:
1、<PackageName>_DIR
这个变量路径默认为空。
这个路径是非根目录路径,需要指定到<PackageName>Config.cmake
或<lower-case-package-name>-config.cmake
文件所在目录才能找到。
2、CMAKE_PREFIX_PATH、CMAKE_FRAMEWORK_PATH、CMAKE_APPBUNDLE_PATH的CMake变量或环境变量路径根目录,默认都为空。
注意如果你电脑中安装了ROS并配置好之后,你在终端执行echo $CMAKE_PREFIX_PATH会发现ROS会将CMAKE_PREFIX_PATH这个变量设置为ROS中的库的路径,意思是会首先查找ROS安装的库,如果恰好你在ROS中安装了OpenCV库,就会发现首先找到的是ROS中的OpenCV,而不是你自己安装到系统中的OpenCV。
3、PATH
环境变量路径
其实这个路径才是Config模式大部分情况下能够查找到安装到系统中各种库的原因。
这个路径的查找规则为:
遍历PATH
环境变量中的各路径,如果该路径如果以bin或sbin结尾,则自动回退到上一级目录得到根目录。
$ echo $PATH
/home/jq/.local/bin:/home/jq/bin:/opt/ros/noetic/bin:/home/jq/.local/bin:/home/jq/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/jq/.fishros/bin/
查找指定包建议
如果你明确知道想要查找的库<PackageName>Config.cmake
或<lower-case-package-name>-config.cmake
文件所在路径,为了能够准确定位到这个包,可以直接设置变量<PackageName>_DIR
为具体路径,如:
set(OpenCV_DIR "/usr/local/include/opencv-3.4.20/share/OpenCV")
参考:
“轻松搞定CMake”系列之find_package用法详解_/opt/ros/melodic/share/gazebo_dev/cmake/gazebo_dev-CSDN博客