A TL;DR about CMake Presets
In my never-ending quest to master CMake, I'm coming across more and more handy tools for project setup and management. Trying to maintain a good starter template for my projects and having developed a few opinions on how I want my projects to work, I finally looked at "CMake Presets" I had already heard much about.
One of those opinions is that I want CMake to do as much as possible without relying on other tools to minimize what is needed for a project setup. If I have a setting that CMake already supports through an option, I define it, reducing what is needed for execution further.
With this in mind, I always thought I wouldn't really need CMake presets, but it turned out some settings I always configure were missing.
What will I cover in this article? It won't be every setting with every property, and in general, the official CMake documentation about presets is quite extensive. If this is what you're looking for, you can follow the link.
Even though the official docs are great, I prefer a different format when it comes to presentation and personal taste, and that's why this article exists.
Besides, some of the settings that can be configured with presets I would rather see directly in a CMake file. This will also be the general approach, what can live in a CMake file will, everything else goes to a preset.
What are CMake Presets?
With time and more knowledge about CMake, certain project settings appear again and again. For me, I found a set of settings I tend to use in every project. I always set up Ninja on Windows and Linux, Xcode on macOS, define the same build directories, or even run the same CTest commands.
Presets enable defining exactly those standard or repeated project settings for CMake and give the option to easily override them per project if needed — things like the build directory, generator, or target architecture.
I can then take this file, throw it in a CMake project, and be ready to go. Especially considering tooling support, where many IDEs like CLion detect those presets and automatically set up a project.
Create a preset
A preset is, at its core, a
CMakePresets.json in the root of the
project. It gets checked into source control and defines
project-wide settings. The minimum requirement to be a valid preset file is
version field that defines the version of the used JSON
Version 6 is not the latest, that be version 8. I picked version 6 as it is the latest CLion supported version of CMake presets.
One benefit of using version 8 is the support of the
$schema field, which defines a URL to the JSON schema to validate
the file contents against.
The URL for the JSON schema is from the official CMake documentation.
Another thing I see often used in projects is the
cmakeMinimumRequired property, though I'd rather define this
version through CMake itself, e.g., in the root CMake file of the project.
The base of most CMake presets is the
configurePresets property, which defines configurations that are applied to the
configuration phase, like defining the build directory or the
The minimum required setting is a name for the preset, but a display name is recommended to be shown when interacting with the preset through a GUI or the CMake CLI, increasing usability.
This example of a configuration preset defines a debug preset. Using
as the generator, the build directory will be
build/debug and the
CMake build type
Defining a release preset follows the same pattern.
Run configuration preset
With at least one configuration presets defined, it's time to run it. To view
all defined presets, run
Run one of those configuration presets with
Working on a project with CMake presets, there can always be the case where a
user needs or wants to define their own presets for any
reason. This can be done through the
This file has the same structure as the
override or extend any options and should always be
excluded from any source control — I usually add this
to my global
For example, defining a release build with debug information as a user preset.
A very handy feature, especially when it comes to multi-platform configurations, are conditional configurations. With this, it is possible to define when a preset is available, for example, to configure Xcode as generator only on macOS.
The condition reads as: compare two values (
left-hand string (
lhs) is the variable
hostSystemName, the right-hand string (
"Darwin" (aka. macOS).
There are many different options for conditionals; different types, multiple conditions to match any or all of; best taken from the official CMake documentation about preset conditions.
Any preset can inherit another to override or add to it. It is common to
define a base preset, hide it with the
hidden property, and
derive specific presets from it. Another typical use case is to have a local
and a derived continuous integration (CI) preset.
With this, let's first create a common, hidden base preset using Ninja as a generator.
The binary directory is predefined, using the variable
presetName to set the directory based on the derived preset. Via
inherits the base preset will be inherited by name.
Common variable setup
Even though I prefer to set as much as possible from inside a CMake file, it can come in very handy to define some cache variables through a preset. One of those is to run a project against multiple compilers, e.g., for CI.
Using inheritance, a CI preset can be derived from an already existing preset. Given the following base preset:
Setting the compiler as a cache variable for CI to create different configuration scenarios.
With a properly defined configuration step, it is just a small jump to also define a build preset. As the name implies, build presets are used for CMake's build phase and are directly related to a configuration preset, supporting many of the same properties.
A great advantage of using build presets is that they can predetermine what targets are built and when. For example, only building tests, everything for a debug build, or just the main target for a release, all while having a simple, explorable* command.
Let's take a debug configuration preset and create a build preset based on it.
All build presets go into an array under the property
To view all defined build presets, run
cmake --build --list-presets.
The build preset can then be used to build the project using the defined configure preset.
By default, this will build all the defined targets. This can
be changed via the
targets property, defining what targets
specifically to build. For example, only building the main target without
tests for a release.
CTest, presets can be used similarly to build presets. Any defined test preset can
be listed via
ctest --list-preset, and run with
ctest --preset, using the
ctest CLI instead of
Using test presets gives the option to execute all or a predefined set of tests, define test fixtures, change environments, set different output options, and more. Nevertheless, I try to define possible or sensible defaults directly in a CMake file for CTest.
Same as build presets, test presets are related to a configuration preset and
All the CTest CLI options can also be defined through this preset, as well as filtering for specific tests.
Here it goes, a full
CMakePresets.json example with debug and
release builds, giving a quick overview of the mentioned features of CMake
There is much more to CMake presets than I showed here, but as said in the beginning, I did not try to replicate the great official CMake documentation about presets and rather give a ready-to-start overview.
Until then 👋🏻