toolchain文件必须显式设置CMAKE_SYSTEM_NAME和CMAKE_SYSTEM_PROCESSOR,否则CMake不进入交叉编译模式,导致CMAKE_FIND_ROOT_PATH_MODE_*等关键行为失效,find_package会错误链接宿主机库而引发编译或链接失败。
不设这两个变量,CMake 就不会切换到交叉编译模式,CMAKE_FIND_ROOT_PATH_MODE_LIBRARY 等后续行为全失效。常见错误是只写 CMAKE_CXX_COMPILER,结果 find_package(Threads) 还是去宿主机找 libpthread.so,链接时直接失败。
正确做法是:在 toolchain 文件里固定写死:
CMAKE_SYSTEM_NAME 必须为 Linux(不是 ARM 或 Generic)CMAKE_SYSTEM_PROCESSOR 根据目标设为 arm(ARMv7)、armv7 或 aarch64(ARM64),大小写敏感,不能写成 ARM
arm-linux-gnueabihf- 工具链,CMAKE_SYSTEM_PROCESSOR 写 arm;如果是 aarch64-linux-gnu-,就写 aarch64
报错 undefined reference to `__aeabi_dadd' 或 fatal error: bits/libc-header-start.h: No such file or directory,基本都是这里出问题。
三个地方必须一致:
立即学习“C++免费学习笔记(深入)”;
arm-linux-gnueabihf-g++ 中的 gnueabihf
CMAKE_SYSROOT 路径下必须包含对应 ABI 的库子目录,例如 /usr/lib/arm-linux-gnueabihf/ 或 /usr/lib/aarch64-linux-gnu/
CMAKE_CXX_FLAGS 里要加 -mfloat-abi=hard(对应 gnueabihf)或 -mfloat-abi=softfp(对应 gnueabi),不能靠编译器默认Debian/Ubuntu 上装的 gcc-arm-linux-gnueabihf 默认 sysroot 在 /usr/arm-linux-gnueabihf/,路径不对就找不到头文件。
find_package(OpenSSL) 找到的是宿主机版本,说明路径隔离没生效。根本原因是 CMake 不知道该“只查目标平台”还是“也查宿主机”。
必须显式控制查找范围:
CMAKE_FIND_ROOT_PATH 设为 CMAKE_SYSROOT(例如 /usr/arm-linux-gnueabihf)CMAKE_FIND_ROOT_PATH_MODE_PROGRAM 设为 NEVER(不查宿主机可执行文件)CMAKE_FIND_ROOT_PATH_MODE_LIBRARY 和 CMAKE_FIND_ROOT_PATH_MODE_INCLUDE 都设为 ONLY
漏掉任意一个,find_library 就可能混用宿主机的 .so 和目标平台的头文件,编译通过、链接失败。
运行完 cmake -DCMAKE_TOOLCHAIN_FILE=xxx.cmake -S . -B build 后,立刻检查配置是否被读取:
cmake -LH -N build | grep -E "(CMAKE_SYSTEM|CMAKE_CXX_COMPILER|CMAKE_SYSROOT)"
输出里必须看到:
CMAKE_SYSTEM_PROCESSOR:STRING=arm(或 aarch64)CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/arm-linux-gnueabihf-g++CMAKE_SYSROOT:PATH=/usr/arm-linux-gnueabihf如果 CMAKE_SYSTEM_PROCESSOR 是空或显示 x86_64,说明 toolchain 文件压根没加载——可能是路径写错、CMake 版本低于 3.1,或者文件里有语法错误(比如少了个右括号)。