Using CMake Presets to Keep Configure Flags Consistent Across Teams
Learn how CMake Presets let teams share configure flags, reduce onboarding friction, and achieve reproducible builds without changing how developers invoke CMake.
25 Aug 2025, 01:20 UTC

The problem: divergent configure invocations
When developers and CI systems call cmake manually, small differences in the command line—different generators, build types, toolchain files, or cache variables—can slip in unnoticed. The result is that the same source tree produces different CMakeCache.txt files, leading to non‑reproducible builds, confusing failures, and extra onboarding time.
Thesis: presets make the intended configure explicit and shareable
CMake Presets (introduced in CMake 3.19, stabilized in 3.20) let you store configure and build settings in version‑controlled JSON files. By committing a CMakePresets.json you declare the canonical way to invoke CMake, while allowing CMakeUserPresets.json for local, uncommitted overrides. The presets are read automatically when you use cmake --preset or cmake --build --preset, so the command‑line habit stays the same but the underlying invocation becomes reproducible.
How the two‑file model works
CMakePresets.json is meant to be checked in. It contains:
version– the preset schema version (currently 3 or 4).configurePresets– each entry defines a configure step (generator, toolchain, build type, cache variables, environment, etc.).buildPresets– optional entries that reference a configure preset and add build‑time options like parallel jobs.
CMakeUserPresets.json lives next to it but is ignored by version control. It can inherit from or override any preset in the committed file, letting a developer tweak things like a personal toolchain without affecting the team baseline.
Presets support inherit (reuse common settings), condition (enable a preset only when an environment variable matches), and environment (set variables for the configure step). This composability keeps the file DRY while still expressing platform‑specific nuances.
Worked example: a multi‑config Ninja preset
Assume a project that wants to use the Ninja multi‑config generator, a Debug build type, and a custom toolchain file located at toolchains/linux‑gcc.cmake. The following CMakePresets.json captures that intent:
{
"version": 4,
"configurePresets": [
{
"name": "linux-debug",
"displayName": "Linux Debug (Ninja)",
"description": "Debug build with Ninja multi‑config and internal toolchain",
"generator": "Ninja Multi‑Config",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"toolchainFile": "${sourceDir}/toolchains/linux-gcc.cmake",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
},
"environment": {
"CC": "gcc",
"CXX": "g++"
}
}
],
"buildPresets": [
{
"name": "linux-debug-build",
"displayName": "Build Linux Debug preset",
"configurePreset": "linux-debug",
"jobs": 8
}
]
}
To see what presets are available, run from the project root:
cmake --list-presets
This will list both the configure preset linux-debug and the build preset linux-debug-build (names are shown exactly as defined).
To configure a build directory using the preset:
cmake --preset linux-debug
CMake will create the directory out/build/linux-debug (as defined by binaryDir) and populate its cache with the generator, toolchain, and CMAKE_BUILD_TYPE=Debug. You can verify the result by inspecting the cache:
grep -E 'CMAKE_GENERATOR|CMAKE_BUILD_TYPE|CMAKE_TOOLCHAIN_FILE' out/build/linux-debug/CMakeCache.txt
To build using the associated build preset:
cmake --build --preset linux-debug-build
CMake will invoke Ninja with -j8 (the jobs value) in the same build directory.
Trade‑offs and limitations
Presets are a convention, not a hard enforcement. If a script or IDE calls cmake directly, bypassing --preset, the settings in the JSON file are ignored. Therefore, teams should document that the prescribed way to invoke CMake is via presets and update any automation to use --preset.
IDE support varies: recent versions of CLion, Visual Studio, and VS Code’s CMake Tools extension read presets, but older IDEs may require manual configuration. Additionally, presets only standardize the *invocation* of CMake; they do not replace the need for correct toolchain files or proper find_package calls.
Finally, the preset schema is version‑sensitive. Features like condition or environment appeared in schema version 3; older CMake binaries (pre‑3.19) will ignore the file entirely. Commit a note in your README about the minimum CMake version required to use the presets.
Actionable closing
- Add a minimal
CMakePresets.jsonto your repository that defines at least one configure preset matching your CI’s desired generator, build type, and toolchain. - If you need per‑developer tweaks (e.g., a different compiler), create a
CMakeUserPresets.jsonthat inherits from the commit‑time preset and overrides only the necessary fields. - Update CI pipelines to call
cmake --preset <configure‑preset>followed bycmake --build --preset <build‑preset>(or the equivalent for your build system). - Validate the preset setup in CI by running
cmake --list-presetsand checking that the expected names appear, then configuring a build directory and spot‑checkingCMakeCache.txtfor the expected values. - Document the workflow in your contributing guide so new contributors know to use the preset commands instead of hand‑crafted
cmakeinvocations.
By centralizing configure settings in versioned JSON, you eliminate a common source of build inconsistency while preserving the familiar command‑line workflow.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.