Using CLion CMake Profiles from CMakePresets.json for Reproducible Builds
Learn how to let CLion import CMakePresets.json as named profiles, keeping builds reproducible across local, container and remote environments without editing CMakeLists.txt.
10 Sept 2025, 04:46 UTC

Problem: environment‑specific CMake settings clutter CMakeLists.txt
When a project needs a local debug build, a release build for CI, and a containerized build for integration tests, developers often add conditionals or cache variables directly in CMakeLists.txt. This makes the file harder to read, couples build logic to source code, and can cause the IDE and command line to see different include paths.
Thesis: let CMakePresets.json describe each environment and let CLion import those presets as named CMake profiles
By moving generator, toolchain file, cache variables and build directory into CMakePresets.json, the source stays clean. CLion reads the file on project open (or reload) and creates a CMake profile for each configure preset. Switching profiles changes the build directory and toolchain while keeping navigation, code analysis and test discovery synchronized with the active preset.
How CLion uses a preset
CLion does not parse CMakeLists.txt directly. On project load it runs cmake configure in a build directory, caches the generated project model and uses that model for the Project tool window, refactoring, run configurations and the test runner. Each configure preset in CMakePresets.json becomes a distinct CMake profile with its own binary directory. The IDE shows the active profile in the toolbar; selecting another profile triggers a reload of the CMake model for that preset.
Worked example: adding host and container presets
Add a file named CMakePresets.json at the repository root with the following content:
{
"version": 3,
"configurePresets": [
{
"name": "host-debug",
"displayName": "Host Debug",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/host-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "host-release",
"displayName": "Host Release",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/host-release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "container-relwithdebinfo",
"displayName": "Container RelWithDebInfo",
"generator": "Ninja",
"toolchainFile": "${sourceDir}/cmake/container-toolchain.cmake",
"binaryDir": "${sourceDir}/build/container-relwithdebinfo",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
}
]
}After saving the file, close and reopen the project or click the CMake profile selector in the bottom‑right status bar. The three presets should appear as selectable profiles: Host Debug, Host Release and Container RelWithDebInfo. To verify from the command line, run cmake --list-presets in the project root (read permission on the file is sufficient). The output lists the configure presets and confirms that CLion can see them.
Trade‑offs and limitations
Preset support is version‑sensitive. Older CLion releases (pre‑2023.2) or older CMake versions may ignore newer fields such as "displayName" or "toolchainFile" and fall back to manual profile creation. Remote toolchain builds require matching CMake and compiler versions between the host and the remote agent; a mismatch leads to configure failures that appear as vague IDE errors. Because CLion caches the CMake model, editing CMakeLists.txt outside the IDE can leave the Project tool window stale until you manually invoke Reload CMake Project from the Tools → CMake menu or the toolbar.
Practical verification
- Modify a target in
CMakeLists.txt(e.g., add a new source file to anadd_executable) while using the Host Debug profile. - Run
Tools → CMake → Reload CMake Project. - Check that the Project tool window updates the file list and that the run/debug configuration for the target reflects the change.
- Create a simple GoogleTest target, ensure the Test tool window discovers it under the active profile’s build directory, and run the tests to confirm they execute in the correct environment.
If the IDE shows the updated symbols and the tests run, the preset‑driven profile is working correctly.
Actionable closing
Keep CMakePresets.json under version control, document the required CMake and compiler versions for each preset, and avoid placing environment‑specific logic in CMakeLists.txt. This makes switching between local, container and remote builds a matter of selecting a profile, giving you reproducible builds and a cleaner source tree.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.