ninja 通过极轻量执行 cmake 生成的静态依赖图实现加速:零解析开销、无隐式规则、仅比对时间戳与命令哈希,使增量构建从 make 的47秒降至8秒。

为什么 Ninja 能让 CMake 编译快起来
不是 Ninja 本身“编译快”,而是它把 CMake 生成的依赖图用极轻量的方式执行——没有隐式规则、不重复解析、启动即干。CMake 生成 build.ninja 后,Ninja 几乎零开销加载并调度任务,而 Make 每次都要重读整个 Makefile 并递归展开变量和函数。
真实瓶颈常在“调度”而非“编译”:一个 5000 文件的 C++ 项目,Make 的增量构建耗时 47 秒,其中 32 秒花在解析和判断哪些要重编;Ninja 同样操作仅用 8 秒,因为它的依赖图是静态扁平的,且只存变更时间戳和命令哈希。
cmake -G Ninja 必须带的参数和常见错
直接运行 cmake -G Ninja .. 很可能失败或退回到 Make —— Ninja 是单配置生成器,CMake 默认不会自动设 CMAKE_BUILD_TYPE,而多数项目中 add_compile_options() 或 target_compile_features() 依赖它。
CMake 4.3.2 Windows x86_64 历史版本安装包,适合旧项目兼容、构建环境回退、CMakeLists.txt 迁移验证、Visual Studio/Ninja/Makefile 生成器测试和 C/C++ 项目维护。
- 必须显式指定构建类型:
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..(Debug或RelWithDebInfo也可,但不能省) - Windows + MSVC 下,若提示
Could not find compiler set in environment variable CC,说明 Ninja 没绑定到工具链:加-T host=x64或完整指定-DCMAKE_CXX_COMPILER="cl.exe" - Mac 上用 Clang 时,若报
unknown argument: '-fcolor-diagnostics',是 Ninja 调用了旧版 CMake 生成的冗余 flag,升级 CMake 到 3.20+ 可解
ninja 命令和 make 的关键行为差异
ninja 不是 make 的替代命令行接口,它是不同哲学的执行器:没默认目标别名、不支持通配符、不自动找 Makefile。习惯 make install 的人容易卡住。
-
ninja等价于ninja all,但项目里必须有名为all的显式目标(CMake 自动生成) -
ninja install只有在 CMake 中调用了install()且配置了CMAKE_INSTALL_PREFIX才有效,否则报error: unknown target 'install' -
ninja clean只删 Ninja 自己知道的输出文件,比make clean更精准,但也更“窄”——不会删 CMakeCache.txt 或 CMakeFiles/ 目录,得手动rm -rf *清构建目录 - 想看构建过程?
ninja -v输出完整命令,ninja -d explain会告诉你“为什么这个目标被重建”(比如时间戳新、命令变了、depfile 缺失)
提速真正起效的三个实操点
装完 Ninja 就跑 ninja 很可能只快 10%~20%,那是因为没动底层瓶颈。以下三点在 OpenSceneGraph、Qt 和大型 OSG 项目中实测提升 30%~50% 增量构建速度:
- 启用
ccache:CMake 配置时加-DCMAKE_CXX_COMPILER_LAUNCHER=ccache,确保ccache在 PATH 且已初始化(ccache -M 10G) - 控制并发数:默认
ninja用cpu_count * 2线程,但链接阶段常因磁盘 I/O 或内存争抢变慢,试ninja -j$(nproc)(Linux)或ninja -j8(16 核机器)更稳 - 跳过测试和文档:CMakeLists.txt 里用
option(BUILD_TESTS "Build tests" OFF),然后配置时加-DBUILD_TESTS=OFF,避免 Ninja 把 test 目标也拉进依赖图
最易被忽略的是 Ninja 的“单配置”本质:改了 CMAKE_BUILD_TYPE 必须删构建目录重 cmake -G Ninja,不能像 Visual Studio 生成器那样切配置后直接 ninja —— 否则它还在跑旧的 build.ninja,连 warning 都不给。










