要看到cmake生成的makefile中的真实编译命令,需在make后加v=1(即make v=1),该参数启用gnu make的详细输出模式,显示包括-i、-d、-o2等全部gcc/clang参数;对ninja构建则须用ninja -v而非v=1,因ninja不支持v变量;还可通过make v=1 2>&1 | tee build.log或ninja -v 2>&1 | tee build.log导出完整命令日志。

cmake 生成的 Makefile 里怎么看到真实编译命令?
默认情况下,make 会隐藏详细命令(只显示缩略的 [CC] 或 [CXX]),你根本看不到 gcc 或 clang 实际执行了什么参数。这不是 CMake 的问题,而是 GNU Make 的“静默模式”在起作用。
要看到完整命令,直接在 make 后加 V=1:
make V=1
这会让 Makefile 输出每一条实际调用的编译器命令,包括所有 -I、-D、-O2 等选项,方便你确认头文件路径、宏定义、优化级别是否生效。
注意:V=1 是 Make 的变量,不是 CMake 的;它只对 Makefile 构建器有效(Ninja 不认这个,得用 -v)。
用 ninja 构建时怎么打印编译命令?
如果你用 cmake -G Ninja .. 生成的是 Ninja 构建文件,make V=1 就不生效了。Ninja 默认也静默,但开关更简单:
ninja -v
-v 会逐行输出每个 clang++ 或 gcc 命令及其全部参数,比 make V=1 更干净直观。
常见误区:有人试 ninja V=1,这是无效的——Ninja 不支持 V 变量,只认 -v 或 --verbose。
想把所有编译命令导出成文本文件怎么办?
直接重定向输出即可,但要注意:必须确保构建系统能完整跑完(哪怕失败),否则中间命令可能被截断:
- 对 Makefile:运行
make V=1 2>&1 | tee build.log,既实时看又存档 - 对 Ninja:运行
ninja -v 2>&1 | tee build.log - 如果只想导出命令而不真正编译,可用
make -n V=1(dry-run),但注意:部分依赖逻辑可能不触发,include_directories或target_compile_options的展开未必完整
导出的 log 里,每一行以 [1/xx] 开头的,后面跟着的就是真实调用的编译器命令,可直接复制粘贴验证。
为什么有时候 V=1 还是看不到某些命令?
有几种典型情况:
-
add_custom_command或add_custom_target定义的命令不会受V=1影响,它们默认就全量输出,除非你显式用了CMD的静默包装 - Android Studio 的 NDK 构建走的是自己的封装流程,即使你在
build.gradle里配了arguments "-v",也要确认日志级别设为VERBOSE,否则 CMake 的内部调用仍被过滤 - 某些 IDE(如 CLion)会拦截并美化构建输出,需在设置里关掉 “hide compiler output” 类选项
最可靠的方式永远是脱离 IDE,在终端里用原生命令跑一遍——毕竟 CMake 本身不“执行”编译,它只是生成构建系统;真正吐出命令的是 Make 或 Ninja。











