find_package本质是搜索xxxconfig.cmake或findxxx.cmake文件;xxx_dir仅对config模式生效且须指向含config文件的目录,非库根目录;no_default_path禁用所有默认路径,需配合精确路径使用。

直接说结论:find_package 不是“指定目录去搜库”,而是“指定目录去搜 xxxConfig.cmake 或 Findxxx.cmake 文件”——搞错这个,90% 的路径问题都白调。
为什么 set(xxx_DIR ...) 有时不生效?
因为 xxx_DIR 只对配置模式(Config Mode)起作用,且必须指向包含 xxxConfig.cmake 的目录(不是库安装根目录,更不是 lib/ 或 include/ 目录)。常见错误包括:
- 把
OpenCV_DIR设成/usr/local/include/opencv4→ 错,这里没有OpenCVConfig.cmake - 设成
/usr/local/lib/cmake/opencv4→ 对,该路径下应有OpenCVConfig.cmake和OpenCVConfigVersion.cmake - 设了
OpenCV_DIR却没加NO_DEFAULT_PATH→ CMake 仍会查系统路径,可能加载了旧版本
正确写法示例(命令行传入):
cmake -DOpenCV_DIR=/path/to/opencv/build/install/lib/cmake/opencv4 ..
或在 CMakeLists.txt 中提前设置(需在 find_package(OpenCV ...) 之前):
set(OpenCV_DIR "/path/to/opencv/build/install/lib/cmake/opencv4" CACHE PATH "") find_package(OpenCV REQUIRED)
如何让 find_package 找到自己编译安装的 yaml-cpp?
yaml-cpp 安装后一般生成 yaml-cpp-config.cmake,但路径不标准(比如装在 ~/3rdparty/yaml-cpp-1.12.0 下,而 config 文件实际在 lib/cmake/yaml-cpp/ 子目录)。这时必须显式告诉 CMake 去哪找:
- 不能只设
yaml-cpp_DIR为安装根目录(~/3rdparty/yaml-cpp-1.12.0),要精确到 config 所在目录 - 推荐用
set(yaml-cpp_DIR ...)+NO_DEFAULT_PATH组合,避免和系统包冲突 - 注意名字大小写:yaml-cpp 的 config 文件名是
yaml-cpp-config.cmake,所以变量名必须是yaml-cpp_DIR(含连字符),不是YAMLCPP_DIR或YamlCpp_DIR
实操代码片段:
set(yaml-cpp_DIR "${CMAKE_CURRENT_LIST_DIR}/3rdparty/yaml-cpp-1.12.0/lib/cmake/yaml-cpp" CACHE PATH "")
find_package(yaml-cpp 1.12.0 REQUIRED NO_DEFAULT_PATH)
MODULE 模式下怎么加自定义 FindXXX.cmake?
当你用的库没提供 XXXConfig.cmake(比如老版本 Boost、自制小模块),就得走模块模式。关键不是“放对位置”,而是“让 CMake 看得到”:
-
CMAKE_MODULE_PATH是唯一入口,它默认为空,必须手动list(APPEND CMAKE_MODULE_PATH ...) - 路径必须是绝对路径;相对路径要用
${CMAKE_CURRENT_LIST_DIR}展开 -
find_package(my_test MODULE REQUIRED)中的MODULE是强制开关,不加的话 CMake 仍会先试 Config 模式,失败才 fallback - 文件名必须严格为
Findmy_test.cmake(驼峰或下划线都按你写的包名来,不自动转换)
示例结构:
project/ ├── CMakeLists.txt ├── cmake/ │ └── Findmy_test.cmake ← 必须叫这个名字 └── src/...
对应 CMakeLists.txt 片段:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
find_package(my_test MODULE REQUIRED)
NO_DEFAULT_PATH 到底要不要加?
加不加取决于你是否想彻底隔离环境。不加时,CMake 会按固定顺序查一堆路径(/usr/lib/cmake/、/opt/homebrew/lib/cmake/、CMAKE_PREFIX_PATH 等),容易加载错版本;加了之后,只查你明确给的路径(如 xxx_DIR 或 HINTS),更可控但调试时容易“找不到”:
- CI 构建或容器内部署:强烈建议加
NO_DEFAULT_PATH,避免污染 - 本地开发多版本共存:加
NO_DEFAULT_PATH+ 显式设xxx_DIR,最稳 - 只是临时试一个系统包(如 apt 安装的 OpenCV):不加,让它自动发现
- 混用时(比如主库用自定义路径,辅助工具用系统路径):改用
HINTS或PATHS,比NO_DEFAULT_PATH更细粒度
一个易忽略的点:NO_DEFAULT_PATH 会禁用所有默认路径,包括 CMAKE_PREFIX_PATH 和注册表,不是只关系统路径。











