1. 更新 locate 数据库(必做!)

  • 操作: 打开终端,运行 sudo updatedb
  • 原因: 确保 locate 的数据库包含你刚刚安装的新库的文件信息,否则后续步骤可能找不到任何内容

2. 初步定位:查找核心配置文件 (Config.cmake)

  • 操作: 运行以下命令
1
locate -i 'config.cmake' | grep -i 'ceres'

结果为:

1
2
3
4
5
6
7
/home/xfy/3d/ceres/ceres-solver/build/third_party/abseil-cpp/abslConfig.cmake
/home/xfy/3d/ceres/ceres-solver/cmake/CeresConfig.cmake.in
/home/xfy/3d/ceres/ceres-solver/cmake/CreateCeresConfig.cmake
/home/xfy/3d/ceres/ceres-solver/third_party/abseil-cpp/CMake/abslConfig.cmake.in
/home/xfy/3d/ceres/ceres-solver/third_party/googletest/googletest/cmake/Config.cmake.in
/usr/lib/cmake/Ceres/CeresConfig.cmake
/usr/local/lib/cmake/Ceres/CeresConfig.cmake

可以看到最后两行就是要找的,一个是系统级安装目录,一个是用户安装目录的。

3. 确定 find_package 名称

由CeresConfig.cmake可以知道这里的名称大小写是Ceres,所以应该是find_package(Ceres REQUIRED)

4. 如何使用

这个文档的注释中没有像OpenCV那样写出如何使用,此时就需要自己来寻找。

首先查找*Config.cmake 文件中是否有创建目标的代码:

  • add_library(库名 IMPORTED)
  • add_library(库名::组件名 IMPORTED)

这里查找看到:

1
2
3
4
5
6
if (NOT TARGET ceres)
# For backwards compatibility, create a local 'alias' target with the
# non-namespace-qualified Ceres target name. Note that this is not a
# true ALIAS library in CMake terms as they cannot point to imported targets.
add_library(ceres INTERFACE IMPORTED)
set_target_properties(ceres PROPERTIES INTERFACE_LINK_LIBRARIES Ceres::ceres)

创建了目标Ceres::ceres

既然创建了目标,那说明是cmake的新使用方法就行:

1
target_link_libraries(my_app Ceres::ceres)

通用方法判断库是否提供导入目标

从这个 Ceres 的例子中,我们可以总结出一些通用方法来判断任何库是否提供导入目标:

  1. 查看库的配置文件
    • 寻找 include(${XXX_DIR}/XXXTargets.cmake) 这样的语句
    • 寻找 add_library(XXX::XXX IMPORTED) 这样的语句
    • 寻找 set_target_properties(XXX::XXX ...) 这样的语句
  2. 查看库变量的设置
    • 如果看到 set(XXX_LIBRARIES XXX::XXX),表明库提供了导入目标

如果是传统方式的话:

1
2
3
4
# 传统方式 - 需要同时设置包含目录和链接库
# 例外,在ceres和opencv的cmake中都说明了不需要target_include_directories
target_include_directories(my_app PRIVATE ${OpenCV_INCLUDE_DIRS})
target_link_libraries(my_app ${OpenCV_LIBS})

5. 补充小知识:findpackage的查找顺序

  1. 首先检查 Ceres_DIR 变量
    • 如果设置了 Ceres_DIR,CMake 会直接查找该目录下的 CeresConfig.cmake
    • 如果找到了有效的配置文件,查找过程立即结束
  2. 然后才会搜索 CMAKE_PREFIX_PATH
  3. 接着是 CMAKE_FRAMEWORK_PATH 和 CMAKE_APPBUNDLE_PATH(主要用于 macOS)
  4. 最后是标准系统安装位置
    • /usr/local/lib/cmake/Ceres/
    • /usr/lib/cmake/Ceres/

如果想要指定版本,有两种方式:

  1. 使用 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 推荐的方式
  2. 使用特定库的 _DIR 变量

    对于单个库,直接设置其专用变量也很有效:

    1
    2
    3
    # 命令行方式
    cmake -DCeres_DIR=/home/xfy/3d/ceres/ceres-solver/build/lib/cmake/Ceres ..

    或在 CMakeLists.txt 中:

    1
    2
    3
    set(Ceres_DIR "/home/xfy/3d/ceres/ceres-solver/build/lib/cmake/Ceres")
    find_package(Ceres REQUIRED)

    注意:Ceres_DIR 应该指向包含 CeresConfig.cmake 的确切目录,而不仅仅是构建目录。其中Ceres就是find_package名称