Lesson 21 · Build & ship
Generators
The generator concept explained. Ninja versus Make versus Visual Studio, single-config versus multi-config, and the commands for each.
Back in lesson 1 you learned CMake is a build system generator. Now it is time to actually choose a generator, because “which one” changes how you build.
What a generator is
When you run cmake -S . -B build, the generator decides what kind of build files end up in build/:
| Generator | Build files | Typical platform |
|---|---|---|
Ninja | build.ninja | Linux, macOS, Windows. The default choice for speed |
Unix Makefiles | Makefile | Linux, macOS. The old default |
Visual Studio 17 2022 | .sln plus .vcxproj | Windows |
Xcode | .xcodeproj | macOS |
Ninja Multi-Config | build.ninja, multi-config | any |
You saw -G Ninja in the presets lesson. -G is how you pick. If you do not, CMake picks a default based on your platform.
Single-config versus multi-config
This is the concept that confuses everyone, so here it is plainly:
- Single-config generators (Ninja, Makefiles). The build type,
Debug,Release, is chosen at configure time with-DCMAKE_BUILD_TYPE=Debug. One build directory, one build type. - Multi-config generators (Visual Studio, Ninja Multi-Config, Xcode). The build type is chosen at build time with
--config Debug. One build directory can hold all types.
# Single-config (Ninja)
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
# Multi-config (Ninja Multi-Config)
cmake -S . -B build -G "Ninja Multi-Config"
cmake --build build --config Debug
cmake --build build --config Release # same dir, both types
Why
This is why “the same command” produces different flags on different machines. On Windows with Visual Studio,
CMAKE_BUILD_TYPEis ignored. It is--configthat matters. On Linux with Ninja,--configis ignored. It isCMAKE_BUILD_TYPEthat matters. Projects that work on both use presets (lesson 20) to define each scenario once. Exactly why that lesson exists.
Why Ninja
Ninja is the default for good reasons:
- Fast. Built to parallelize aggressively and do minimal work on incremental builds.
- Portable. The same
build.ninjaworkflow on Linux, macOS and Windows. - Clean errors. Colors, clear formatting, deduplicated output.
It does what make does, better. Install it with apt install ninja-build, brew install ninja, or choco install ninja on Windows. Then -G Ninja, or put "generator": "Ninja" in your presets.
Visual Studio on Windows
On Windows with Visual Studio installed, cmake -S . -B build without flags picks it automatically. You get .sln files you can open in the IDE, and the IDE, with --config, handles Debug and Release switching. Ninja works too, but the VS generator gives the IDE integration.
What you actually need to remember
- Ninja plus presets for yourself and CI. Fast and deterministic.
CMAKE_BUILD_TYPEfor single-config,--configfor multi-config. If a tutorial mixes them up, the tutorial is wrong.cmake --build buildis generator-agnostic. It just works, whichever one you picked.
Pitfall
Switching generators on an existing build directory, for example
cmake -S . -B build -G Ninjaafter it was configured with Makefiles, produces confusing errors. Change generators, get a fresh build directory (rm -rf build). The generator is a configure-time identity, not a runtime flag.
Read the docs