Generator Overview
CMake's power lies in its abstraction: one CMakeLists.txt drives any native build system through generators. The -G flag selects which build files CMake produces. Understanding the distinction between single-config and multi-config generators is fundamental to effective cross-platform development. See the cmake-generators(7) reference for the complete list.
CMAKE_BUILD_TYPE. Multi-config generators (Visual Studio, Xcode, Ninja Multi-Config) defer the choice to build time via --config, keeping all configurations in one build tree.
Listing Available Generators
# List all generators available on your system
cmake --help
# The output includes a "Generators" section showing what's installed:
# * Unix Makefiles
# * Ninja
# * Ninja Multi-Config
# * Visual Studio 17 2022
# * Xcode
# etc.
flowchart TD
A[CMakeLists.txt] --> B{Generator Type}
B -->|Single-Config| C[cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..]
B -->|Multi-Config| D["cmake -G 'Visual Studio 17 2022' .."]
C --> E[build/Release files only]
D --> F[build/ with Debug + Release + RelWithDebInfo]
E --> G[cmake --build build]
F --> H[cmake --build build --config Release]
Unix Makefiles
The Unix Makefiles generator is the default on Linux and macOS (when Xcode isn't detected). It produces standard Makefile files consumable by GNU Make. Despite being the oldest generator, it remains reliable for CI pipelines and environments where Make is universally available. Reference: Unix Makefiles generator docs.
# Configure with Unix Makefiles (explicit)
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -S . -B build
# Build with all available cores
cmake --build build -- -j$(nproc)
# Alternatively, invoke make directly
cd build && make -j$(nproc)
Parallel Builds
# Method 1: Through cmake --build (portable)
cmake --build build --parallel 8
# Method 2: Environment variable (Make-specific)
export MAKEFLAGS="-j$(nproc)"
cmake --build build
# Method 3: Direct make invocation
make -j$(nproc) -C build
# Check how many jobs are running
make -j8 -C build 2>&1 | grep -c "Compiling"
Verbose Output
# Show full compiler commands during build
cmake --build build -- VERBOSE=1
# Or set at configure time for permanent verbose output
cmake -DCMAKE_VERBOSE_MAKEFILE=ON -S . -B build
# Or export environment variable
export VERBOSE=1
cmake --build build
Objective: Measure how parallel jobs affect build time on your machine.
Create a project with 20+ translation units, then build with -j1, -j4, -j8, and -j$(nproc). Plot the time vs. jobs curve — you'll see diminishing returns beyond your core count due to I/O and linking bottlenecks.
Ninja Generator
Ninja is a small, fast build system designed for maximum parallelism and minimal overhead. CMake's Ninja generator produces build.ninja files that are leaner and faster to parse than Makefiles. On large projects, Ninja typically builds 10–30% faster than Make. See the Ninja generator documentation.
Speed Advantages
# Configure with Ninja
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -S . -B build-ninja
# Build (Ninja auto-detects optimal parallelism)
cmake --build build-ninja
# Ninja's status output is compact: [42/128] Building CXX object...
# No need for -j flag — Ninja defaults to ncpus+2
# Examine the generated build.ninja structure
cat build-ninja/build.ninja | head -20
# Ninja files are machine-optimized, not human-readable
# They contain: rules, build edges, and dependency info
# List all available targets
ninja -C build-ninja -t targets all
# Show the dependency graph for a specific target
ninja -C build-ninja -t deps src/CMakeFiles/myapp.dir/main.cpp.o
Ninja Multi-Config
The Ninja Multi-Config generator (CMake 3.17+) combines Ninja's speed with multi-config flexibility — one configure step, build any configuration at build time:
# Configure once for all configurations
cmake -G "Ninja Multi-Config" -S . -B build-mc
# Build specific configurations at build time
cmake --build build-mc --config Debug
cmake --build build-mc --config Release
cmake --build build-mc --config RelWithDebInfo
# Default configurations can be set in CMakePresets.json
# or via CMAKE_CONFIGURATION_TYPES
# CMakeLists.txt — customize available configurations
cmake_minimum_required(VERSION 3.21)
project(MultiConfigDemo)
# Only relevant for multi-config generators
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo" CACHE STRING "")
# Per-config output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin/Debug)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/Release)
add_executable(app main.cpp)
target_compile_options(app PRIVATE
$<$:-O0 -g -fsanitize=address>
$<$:-O3 -DNDEBUG>
)
Objective: Quantify the speed difference between Ninja and Make on your project.
Configure the same project with both generators, run a clean build with time cmake --build build-ninja vs time cmake --build build-make. Then do an incremental build (touch one file). Ninja's advantage is most apparent in the incremental case due to faster dependency scanning.
Visual Studio Generators
On Windows, the Visual Studio generators produce native .sln and .vcxproj files. These are multi-config generators — one build tree handles Debug, Release, and custom configurations. See the Visual Studio 17 2022 documentation.
Platform Selection (-A)
# 64-bit build (default on modern VS)
cmake -G "Visual Studio 17 2022" -A x64 -S . -B build-vs
# 32-bit build
cmake -G "Visual Studio 17 2022" -A Win32 -S . -B build-vs32
# ARM64 build (for Windows on ARM)
cmake -G "Visual Studio 17 2022" -A ARM64 -S . -B build-arm64
# Build from command line
cmake --build build-vs --config Release --target ALL_BUILD
# Or open in Visual Studio IDE
start build-vs\MyProject.sln
Toolset Selection (-T)
# Use Clang/LLVM toolset within Visual Studio
cmake -G "Visual Studio 17 2022" -A x64 -T ClangCL -S . -B build-clang
# Use a specific MSVC version (v143 = VS 2022, v142 = VS 2019)
cmake -G "Visual Studio 17 2022" -A x64 -T v142 -S . -B build-v142
# Use Intel C++ compiler toolset
cmake -G "Visual Studio 17 2022" -A x64 -T "Intel C++ Compiler 2025" -S . -B build-intel
-G Ninja instead of Visual Studio generators. Ninja avoids the overhead of solution/project file parsing and provides better parallelism. Reserve Visual Studio generators for developer workstations where IDE integration matters.
Xcode Generator
The Xcode generator produces .xcodeproj bundles for macOS and iOS development. Like Visual Studio, Xcode is a multi-config generator — configurations are selected at build time.
# Generate Xcode project
cmake -G Xcode -S . -B build-xcode
# Build via command line
cmake --build build-xcode --config Release
# Or use xcodebuild directly
xcodebuild -project build-xcode/MyProject.xcodeproj \
-scheme MyApp -configuration Release build
# Open in Xcode IDE
open build-xcode/MyProject.xcodeproj
# CMakeLists.txt — Xcode-specific settings
cmake_minimum_required(VERSION 3.21)
project(MacApp)
add_executable(macapp main.cpp)
# Set Xcode attributes
set_target_properties(macapp PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-"
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "YOURTEAMID"
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_BUNDLE_NAME "MyMacApp"
MACOSX_BUNDLE_GUI_IDENTIFIER "com.example.macapp"
)
Other Generators
MinGW Makefiles
# Use MinGW's make (mingw32-make) on Windows
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -S . -B build-mingw
# Build with mingw32-make
cmake --build build-mingw
# Note: This is a single-config generator
# CMAKE_BUILD_TYPE must be set at configure time
NMake Makefiles
# Use NMake from a Visual Studio Developer Command Prompt
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -S . -B build-nmake
# Build (single-threaded by default — NMake has no -j flag)
cmake --build build-nmake
# For parallel NMake, use "NMake Makefiles JOM" with the Jom tool
cmake -G "NMake Makefiles JOM" -DCMAKE_BUILD_TYPE=Release -S . -B build-jom
Watcom WMake
# Legacy Watcom compiler support
cmake -G "Watcom WMake" -DCMAKE_BUILD_TYPE=Release -S . -B build-watcom
# Primarily used for DOS/OS2 retro development
# and legacy embedded systems targeting 16-bit x86
Comparing Build Times
Real-world measurements on a 500-file C++ project (Ryzen 9, NVMe SSD, 32 GB RAM):
| Generator | Clean Build | Incremental (1 file) | No-op Build |
|---|---|---|---|
| Unix Makefiles | 47.2s | 3.8s | 1.2s |
| Ninja | 38.6s | 1.4s | 0.1s |
| Ninja Multi-Config | 39.1s | 1.5s | 0.1s |
| Visual Studio 2022 | 52.8s | 4.1s | 2.3s |
| MinGW Makefiles | 51.4s | 4.0s | 1.4s |
flowchart LR
subgraph Clean Build
N1[Ninja: 1.0x]
M1[Make: 1.22x]
V1[VS: 1.37x]
end
subgraph Incremental
N2[Ninja: 1.0x]
M2[Make: 2.7x]
V2[VS: 2.9x]
end
subgraph No-op
N3[Ninja: 1.0x]
M3[Make: 12x]
V3[VS: 23x]
end
Objective: Build a reproducible benchmark comparing generators on your hardware.
Create a script that configures the same project with each available generator, performs clean/incremental/no-op builds with time, and outputs a CSV. Control for compiler cache (ccache) by disabling it during benchmarks. Consider CPU thermals — run each test 3 times after a cool-down period.
Choosing the Right Generator
Your choice of generator depends on your platform, team workflow, and CI constraints:
- Linux/macOS CI: Ninja (fastest, excellent dependency tracking)
- Windows CI: Ninja (avoid VS overhead in headless builds)
- Windows developers: Visual Studio 2022 (IDE integration, IntelliSense)
- macOS developers: Xcode (debugging, Instruments, code signing)
- Multi-platform presets: Ninja Multi-Config (one tree, all configs)
- Legacy/embedded: Unix Makefiles (universal availability)
# CMakePresets.json — define generator per workflow
{
"version": 6,
"configurePresets": [
{
"name": "dev-ninja",
"generator": "Ninja Multi-Config",
"binaryDir": "${sourceDir}/build-dev",
"cacheVariables": {
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "ci-linux",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-ci",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "dev-vs",
"generator": "Visual Studio 17 2022",
"architecture": "x64",
"binaryDir": "${sourceDir}/build-vs"
}
]
}
Conclusion & Next Steps
Generators are CMake's bridge between portable project definitions and platform-native build tooling. Ninja dominates for raw speed, Visual Studio and Xcode excel at developer ergonomics, and Unix Makefiles provide universal compatibility. Use CMake Presets to codify your generator choices for both development and CI environments.
Next in the Series
In Part 27: Testing Dashboards with CDash, we'll explore how to submit test results to CDash dashboards, track coverage over time, and integrate memory-checking tools into your continuous testing workflow.