Home / Use cases / CMake & C/C++ incremental builds
Local developmentCMake & C/C++ incremental builds
Kill the two-minute inner loop on a large CMake + Ninja C/C++ project without touching your CMakeLists.
The problem
A big C/C++ codebase generated by CMake with the Ninja generator rebuilds the same translation units over and over as you switch branches and tweak headers. Stock ninja re-runs the compiler for every stale edge, even when the exact same inputs produced an artifact minutes ago. The inner loop becomes "edit one file, wait, context-switch," and the wait is mostly recomputation.
How rninja solves it
- ▸Point rninja at the build.ninja CMake already emits — no change to CMakeLists.txt or your generator step.
- ▸Every action is content-hashed over its inputs, command line, and observed environment, so an unchanged compile is a cache hit that skips the toolchain entirely.
- ▸The tokio-driven scheduler keeps cores busy on the misses instead of stalling on single-threaded bookkeeping.
- ▸Switch branches and switch back, and the artifacts you already built come straight from the local sled store.
// CMake + rninja
$ cmake -G Ninja -B out/Release $ rninja -C out/Release # same flags as ninja [1/842] Compiling src/render/mesh.cc [842/842] Linking render_test cache hit
- ·rninja does not regenerate build.ninja; it executes the one your generator wrote. Re-run CMake exactly as before when your build files change.
- ·Non-deterministic outputs (embedded timestamps, random seeds) lower the hit rate. Fixing them pays back immediately.
Questions
[+] Do I have to change my CMake setup?
No. rninja parses the build.ninja CMake emits with standard ninja semantics. You keep cmake -G Ninja and only swap which binary runs the build.
[+] What if a compile really did change?
A changed input produces a different content hash, so it is a cache miss and rninja runs the toolchain exactly as ninja would. Caching is strictly additive — a hit only happens when inputs, command, and environment all match.
Try it on this exact workload
Install rninja, point it at your existing build.ninja, and time it side by side. See the quickstart or browse other use cases.