C++学习笔记—find原理—以ceres为例子的实操
1. 更新 locate 数据库(必做!)
- 操作: 打开终端,运行
sudo updatedb
- 原因: 确保 locate 的数据库包含你刚刚安装的新库的文件信息,否则后续步骤可能找不到任何内容
2. 初步定位:查找核心配置文件 (Config.cmake)
- 操作: 运行以下命令
1 | locate -i 'config.cmake' | grep -i 'ceres' |
结果为:
1 | /home/xfy/3d/ceres/ceres-solver/build/third_party/abseil-cpp/abslConfig.cmake |
可以看到最后两行就是要找的,一个是系统级安装目录,一个是用户安装目录的。
3. 确定 find_package 名称
由CeresConfig.cmake可以知道这里的名称大小写是Ceres,所以应该是find_package(Ceres REQUIRED)
4. 如何使用
这个文档的注释中没有像OpenCV那样写出如何使用,此时就需要自己来寻找。
首先查找*Config.cmake 文件中是否有创建目标的代码:
add_library(库名 IMPORTED)
add_library(库名::组件名 IMPORTED)
这里查找看到:
1 | if (NOT TARGET ceres) |
创建了目标Ceres::ceres
。
既然创建了目标,那说明是cmake的新使用方法就行:
1 | target_link_libraries(my_app Ceres::ceres) |
通用方法判断库是否提供导入目标
从这个 Ceres 的例子中,我们可以总结出一些通用方法来判断任何库是否提供导入目标:
- 查看库的配置文件:
- 寻找
include(${XXX_DIR}/XXXTargets.cmake)
这样的语句 - 寻找
add_library(XXX::XXX IMPORTED)
这样的语句 - 寻找
set_target_properties(XXX::XXX ...)
这样的语句
- 寻找
- 查看库变量的设置:
- 如果看到
set(XXX_LIBRARIES XXX::XXX)
,表明库提供了导入目标
- 如果看到
如果是传统方式的话:
1 | # 传统方式 - 需要同时设置包含目录和链接库 |
5. 补充小知识:findpackage的查找顺序
- 首先检查 Ceres_DIR 变量
- 如果设置了 Ceres_DIR,CMake 会直接查找该目录下的 CeresConfig.cmake
- 如果找到了有效的配置文件,查找过程立即结束
- 然后才会搜索 CMAKE_PREFIX_PATH
- 接着是 CMAKE_FRAMEWORK_PATH 和 CMAKE_APPBUNDLE_PATH(主要用于 macOS)
- 最后是标准系统安装位置
- /usr/local/lib/cmake/Ceres/
- /usr/lib/cmake/Ceres/
如果想要指定版本,有两种方式:
使用 CMAKE_PREFIX_PATH(推荐)
这是最通用、最干净的方式,尤其是当处理多个第三方库时:
1
2
3# 在命令行设置
cmake -DCMAKE_PREFIX_PATH=/home/xfy/3d/ceres/ceres-solver/build ..或在 CMakeLists.txt 中:
1
2
3
4# 在 find_package 之前设置
list(APPEND CMAKE_PREFIX_PATH "/home/xfy/3d/ceres/ceres-solver/build")
find_package(Ceres REQUIRED)优点:
- 可以一次性指定多个库的搜索路径
- 不需要为每个库单独设置变量
- 是 CMake 推荐的方式
使用特定库的 _DIR 变量
对于单个库,直接设置其专用变量也很有效:
1
2
3# 命令行方式
cmake -DCeres_DIR=/home/xfy/3d/ceres/ceres-solver/build/lib/cmake/Ceres ..或在 CMakeLists.txt 中:
1
2
3set(Ceres_DIR "/home/xfy/3d/ceres/ceres-solver/build/lib/cmake/Ceres")
find_package(Ceres REQUIRED)注意:Ceres_DIR 应该指向包含 CeresConfig.cmake 的确切目录,而不仅仅是构建目录。其中Ceres就是find_package名称