必须配置CMAKE_FIND_ROOT_PATH及其三模式变量:设CMAKE_FIND_ROOT_PATH为目标sysroot路径,CMAKE_FIND_ROOT_PATH_MODE_LIBRARY和INCLUDE为ONLY,PROGRAM为NEVER,PACKAGE为ONLY,才能确保find_package等命令严格限定在目标平台路径搜索。

find_package 在交叉编译时默认会去宿主机(比如 x86_64 Ubuntu)的 /usr/lib、/usr/include 甚至 pkg-config 缓存里找库,这会导致链接到错误的 x86 头文件或 .so,最终编译通过但运行崩溃,或者 find_package(OpenCV) 直接失败 —— 根本不是 OpenCV 版本问题,而是路径没切过去。
必须让 find_package 只在目标平台目录里搜,且完全忽略宿主机路径。靠 PATHS 参数硬指定是治标不治本,容易被后续 find_path/find_library 的隐式行为绕过。
toolchain 文件里必须设置 CMAKE_FIND_ROOT_PATH 和三模式变量
这是最可靠、CMake 原生支持的方式,所有 find_* 系列命令都会受控:
• CMAKE_FIND_ROOT_PATH 必须设为目标 sysroot 路径(如 /usr/arm-linux-gnueabihf)或工具链 + 第三方库根目录(如 /opt/arm-toolchain /opt/opencv-arm),多个路径用空格分隔,按顺序搜索
• CMAKE_FIND_ROOT_PATH_MODE_LIBRARY 设为 ONLY:只在 CMAKE_FIND_ROOT_PATH 下找 .a/.so
• CMAKE_FIND_ROOT_PATH_MODE_INCLUDE 设为 ONLY:头文件也只认这些路径下的 include/
• CMAKE_FIND_ROOT_PATH_MODE_PROGRAM 设为 NEVER:避免误用宿主机的 pkg-config 或 protoc 等工具
• CMAKE_FIND_ROOT_PATH_MODE_PACKAGE 也设为 ONLY:确保 find_package 加载的 *Config.cmake(如 OpenCVConfig.cmake)只从目标路径读取
find_package(... PATHS ... NO_DEFAULT_PATH) 不推荐单独使用
• 单独加 PATHS /opt/opencv-arm 只影响本次调用,无法约束它内部依赖的 find_library 行为
• NO_DEFAULT_PATH 会禁用 CMAKE_FIND_ROOT_PATH,反而让 CMake 回退到宿主机路径(因为 NO_DEFAULT_PATH 优先级高于 root path)
• 如果你真要用 PATHS,必须配合 NO_CMAKE_PATH 和 NO_CMAKE_ENVIRONMENT_PATH 才能压住默认路径,但极易漏写、难维护
• 实际项目中,90% 的 find_package 失败都源于这里用了 PATHS 却没关死其他路径源
第三方库(如 OpenCV)必须提供目标平台的 *Config.cmake
• 宿主机上 apt install libopencv-dev 装的是 x86_64 的 OpenCVConfig.cmake,交叉编译时绝对不能用
• 正确做法:用交叉工具链重新编译 OpenCV,并指定 -DCMAKE_INSTALL_PREFIX=/opt/opencv-arm,安装后确保该路径下有 lib/cmake/opencv4/OpenCVConfig.cmake
• 若库没提供 Config 模式(比如老版本 OpenCV),就得用 find_package(OpenCV REQUIRED) + set(OpenCV_DIR /opt/opencv-arm/lib/cmake/opencv4) 显式指向,否则 CMake 会 fallback 到 FindOpenCV.cmake,而后者不尊重 CMAKE_FIND_ROOT_PATH
• 注意:OpenCV_DIR 是缓存变量,必须在 find_package 前 set(... CACHE PATH ...) 或通过 -DOpenCV_DIR=... 传入
CMAKE_FIND_ROOT_PATH 指向了工具链目录,却忘了把第三方库(比如你自己编译的 OpenCV)也加进去;或者 CMAKE_FIND_ROOT_PATH_MODE_LIBRARY 写成了 BOTH,结果 CMake 先在宿主机找到一个同名但 ABI 不兼容的 libz.so,链接过去就段错误。


















