CLion CMake Presets: Turning a Shared File into a Team-Wide Build Contract
CLion reads CMakePresets.json directly, letting teams pin generators, toolchains, and cache variables in one shared file. Here is how to adopt it without breaking local workflows.
09 Oct 2026, 12:42 UTC

Your team shares a Git repository, yet every developer configures CMake differently. One person picks Unix Makefiles in the CMake GUI, another uses Ninja, and a third toggles a cache variable that CI never sets. The build graph drifts, and debugging becomes an exercise in comparing local CMakeCache.txt files. CLion's support for CMake presets offers a way out: treat CMakePresets.json as the contract for how the project is configured, built, and tested.
The useful takeaway is that CLion reads CMakePresets.json and CMakeUserPresets.json directly. Configure presets appear in the CMake tool window selector without extra plugin setup or manual cache seeding. That means the same file that drives your CI pipeline can drive the IDE, removing the "works on my machine" class of bugs caused by divergent local CMake GUI settings.
What CLion actually consumes
CMake introduced presets in two stages: configurePresets arrived in CMake 3.19, and buildPresets and testPresets followed in CMake 3.20. A configure preset pins the generator, toolchain, binaryDir, and cacheVariables. Build and test presets can chain to a configure preset, so CLion's Build and Run actions reuse the exact targets and arguments CI uses instead of a separate IDE-only configuration.
The companion file, CMakeUserPresets.json, is the intended place for machine-specific overrides such as local toolchain paths. Keeping the shared file clean while still letting CLion honor local deviations is exactly what the two-file split is designed for.
A minimal shared preset you can copy
Place the following in your project root as CMakePresets.json. This example uses schema version 2, introduced with CMake 3.20; raise it only if your team's minimum CMake and CLion releases support newer fields.
{
"version": 2,
"configurePresets": [
{
"name": "linux-ninja",
"displayName": "Linux Ninja Release",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/linux-ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
}
],
"buildPresets": [
{
"name": "linux-ninja-release",
"configurePreset": "linux-ninja",
"jobs": 4
}
]
}
Open the project in CLion and confirm the preset name appears in the CMake tool window selector. Select it, run Build, then inspect CMakeCache.txt inside the preset's binaryDir. You should see the generator and cache variables you declared, not values seeded by a local GUI session.
Next, create CMakeUserPresets.json in the same directory. This file is typically git-ignored. It inherits the shared preset and overrides one cache variable:
{
"version": 2,
"configurePresets": [
{
"name": "linux-ninja-local",
"inherits": "linux-ninja",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "/opt/toolchain/bin/g++"
}
}
]
}
Reload the project and verify CLion picks up the override without modifying the shared file. If the preset does not appear or behaves unexpectedly, check the CLion CMake tool window or event log for schema warnings; a rejected or unknown preset field usually surfaces there rather than failing silently.
Trade-offs you should plan for
Presets are version-sensitive. A preset file written against a newer CMake schema may be rejected or partially ignored by older CLion releases. Before enforcing a preset in CI, agree on a minimum CMake version and validate that your team's minimum IDE build understands the schema version you commit.
CLion still layers IDE-specific settings—like code analysis, indexing, and some debugger options—on top of the preset. Presets standardize the build graph, not every editor behavior. If a preset sets CMAKE_TOOLCHAIN_FILE or a generator that conflicts with CLion's detected toolchain, the IDE may show a warning and fall back to its own defaults, so inspect the event log after the first reload.
Switching presets invalidates the CMake cache and triggers a full reload, which can feel slow on large projects. Batch changes instead of toggling presets repeatedly during a debugging session.
Adopting it safely
Start with one configure preset and one build preset that mirror your primary CI job. Keep absolute local paths out of CMakePresets.json; use $env{} or ${sourceDir} macros so the file remains portable across machines. Add a CI step that runs cmake --list-presets and configures with the shared preset to catch schema drift early. When a local deviation is genuinely needed, add it to CMakeUserPresets.json rather than editing the shared contract.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.