结论:报“is not able to compile a simple test program”错误并非编译器损坏,而是cmake在windows上默认尝试运行目标平台可执行文件导致失败;因其无法执行而误判编译器失效。

直接说结论:报 is not able to compile a simple test program 错误,**不是编译器坏了,而是 CMake 在 Windows 上默认尝试运行目标平台的可执行文件**——它根本跑不起来,于是误判编译器失效。
为什么 CMake 会在 Windows 上卡在 test program 阶段?
CMake 的配置流程里有一环是生成并运行一个极简的 main() 程序来验证工具链。这个行为在 Linux/macOS 交叉编译时通常被跳过(因为 CMake 能识别出 target ≠ host),但在 Windows 上,尤其用较老版本 CMake(
而你交叉编译出来的二进制(比如 aarch64-linux-gnu-gcc 产出的 ELF 文件)根本没法在 Windows 上执行,system() 调用失败,CMake 就认定“编译器不能工作”。
- 这不是路径写错、编译器没装好,而是机制性误判
- 错误日志里通常能看到类似
testCCompiler.cmake:29 (try_compile)的调用栈 -
CMakeError.log里会显示链接成功但执行返回非零码(Windows 没法 load ELF)
必须设置的三个关键变量(Windows 下尤其重要)
光靠 CMAKE_TOOLCHAIN_FILE 不够,Windows 下需要显式告诉 CMake:“别试运行,我只编译”。这靠以下三变量组合实现:
-
CMAKE_SYSTEM_NAME必须设为Linux(或其他目标系统名,如Generic),不能留空或设成Windows -
CMAKE_SYSTEM_PROCESSOR明确设为目标架构,例如aarch64、arm、armv7 -
CMAKE_TRY_COMPILE_TARGET_TYPE设为STATIC_LIBRARY—— 这是最关键的一句,它让 CMake 放弃生成和运行可执行文件,改用静态库方式验证编译器可用性
示例(写在 toolchain 文件末尾):
set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
常见陷阱:路径、空格与编码
即使逻辑正确,Windows 下的细节也容易翻车:
- 工具链路径含空格或中文?
CMAKE_C_COMPILER值必须用双引号包裹,且路径分隔符统一用正斜杠/(反斜杠\在 CMake 字符串里会被转义) - 工具链文件保存为 UTF-8 无 BOM 格式 —— Windows 记事本默认带 BOM,CMake 读取会报语法错误
-
CMAKE_SYSROOT和CMAKE_FIND_ROOT_PATH不要混用:CMAKE_SYSROOT是头文件和库的根目录(如/opt/sysroot),CMAKE_FIND_ROOT_PATH是 CMake 查找依赖时额外拼接的前缀,两者指向同一位置时容易重复包含 - 检查
CMakeCache.txt里CMAKE_C_COMPILER的值是否和你预期一致 —— 有时环境变量CC会覆盖 toolchain 文件里的设置,导致实际用错编译器
验证是否真修复了?看 CMakeCache.txt 里的标志位
配置完成后,打开 CMakeCache.txt,搜索以下几行:
-
CMAKE_C_COMPILER_WORKS:BOOL=TRUE—— 如果还是FALSE,说明 test program 阶段仍失败 -
CMAKE_SYSTEM_NAME:STRING=Linux和CMAKE_SYSTEM_PROCESSOR:STRING=aarch64必须和你设的一致 -
CMAKE_TRY_COMPILE_TARGET_TYPE:STRING=STATIC_LIBRARY必须存在且值正确
如果这些都对,但依然报错,重点检查 CMakeError.log 里最后一段 —— 它会暴露真实失败点:是找不到 features.h(CMAKE_SYSROOT 指向错误),还是链接器报 skipping incompatible(CMAKE_LINKER 没设或设错),这些都不是 test program 问题,得另起炉灶查。











