根本原因是find_package优先走config模式而非module模式,paths参数仅在module模式下生效且排最后;库若提供xxxconfig.cmake则完全忽略paths,而xxx_root优先级高于cmake_prefix_path,但要求文件名和路径结构严格匹配。

根本原因不是路径没写对,而是 CMake 没走到你指定的目录里去查 —— 它压根没按你想的方式启动查找逻辑。
为什么 find_package(XXX) 忽略你传的 PATHS 参数?
很多人以为加个 PATHS /opt/mylib 就能强制 CMake 去那里找,结果还是报 Could NOT find XXX。这是因为:
-
PATHS只在 Module 模式下生效,且仅作为“兜底路径”使用 —— 它排在所有其他搜索路径之后(比如XXX_ROOT、CMAKE_PREFIX_PATH、系统默认路径) - 如果库提供了
XXXConfig.cmake(即支持 Config 模式),CMake 会优先走 Config 模式,完全跳过PATHS - 即使没提供 Config 文件,CMake 也会先查
CMAKE_MODULE_PATH里的FindXXX.cmake,再查内置模块,最后才轮到PATHS
XXX_ROOT 和 CMAKE_PREFIX_PATH 到底谁更管用?
两者都影响 Config 模式查找,但优先级不同:
-
XXX_ROOT(如Eigen3_ROOT)是 CMake 3.12+ 引入的专用变量,优先级最高,CMake 会直接拼出${XXX_ROOT}/lib/cmake/XXX/XXXConfig.cmake去找 -
CMAKE_PREFIX_PATH是通用路径列表,CMake 会在每个路径下依次尝试lib/cmake/XXX/、share/XXX/、lib64/cmake/XXX/等子路径 - 如果同时设了
Eigen3_ROOT和CMAKE_PREFIX_PATH,前者生效;但如果设的是OpenCV_ROOT而 OpenCV 实际安装在/usr/local,而/usr/local/lib/cmake/opencv4/下只有OpenCVConfig.cmake(注意大小写),那依然失败 —— 因为名字必须严格匹配
Windows 下 find_package 找不到库的典型断点在哪?
Windows 没有统一安装规范,常见卡点很具体:
- 库装在
C:/libs/eigen3,但Eigen3Config.cmake实际在C:/libs/eigen3/share/eigen3/cmake/—— 这时只设Eigen3_ROOT为C:/libs/eigen3不够,得设Eigen3_DIR直接指向那个 cmake 目录 - Debug/Release 库混装:CMake 默认找
xxx.lib,但你只放了xxx_d.lib,它就认为“缺库” - 注册表干扰:某些旧版 Qt 或 VCPKG 安装会往注册表写路径,CMake 读到错误路径后就不往下搜了,建议临时清空或用
-D CMAKE_FIND_USE_REGISTRY=OFF关闭
自己编译的库怎么让 find_package 认出来?
别指望 find_package 自动发现你扔在项目目录下的 libmylib.so。要让它工作,必须提供标准配置文件:
- Config 模式:生成
MyLibConfig.cmake,里面用find_path(MyLib_INCLUDE_DIR ...)和find_library(MyLib_LIBRARY ...)定位头文件和库,并include(CMakePackageConfigHelpers)导出 target - Module 模式:手写
FindMyLib.cmake放进CMAKE_MODULE_PATH,里面用find_path/find_library+set(MyLib_FOUND TRUE)手动组装结果 - 最省事但不推荐:绕过
find_package,直接用target_include_directories(mytarget PRIVATE /path/to/mylib/include)和target_link_libraries(mytarget /path/to/mylib/libmylib.so)
真正容易被忽略的点是:CMake 查找行为由库本身决定 —— 它有没有提供 Config 文件、文件名是否匹配、目录结构是否符合约定,比你传什么参数更重要。先确认库的安装产物结构,再选对应模式,否则所有路径设置都是徒劳。











