In the last article about CMake I’ve explained how to use CMake for embedded software development and how to use, for example, an external toolchain.
This time, I’m going to write about how can you automate CMake for your own needs.
The CMake Presets is a very powerful — and readable — tool for CMake.
Creating a minimal CMake Preset from a simple CMake example
I’m using the same application code I’ve used before. In short, it has a main.c and a library named test_lib with a respective test_lib.c and test_lib.h.
The root CMakeLists.txt is written as following:
The executable target is named test.
The test_lib library CMakeLists.txt is written as following:
A CMake preset can be simply added by creating the file CMakePresets.json in the root directory of the project.
A minimalCMakePresets.json might look like this:
There is a default configure preset and a default build preset. Essentially, this is minimum required to take advantage from the CMake preset feature.
I’ve decided to define the target inside the preset, but it can also be done as usual.
Test your CMake Preset
To run a configure preset, run on the shell:
This will create the Makefiles inside the /build directory, defined by the field binaryDir.
To run a build preset, do the same as above but add the keyword --build before the --preset:
This will automatically build the binary and store it in /build.
Different presets for different build types
The most popular build types are debug and release.
To have a preset with a pre-defined build type, change CMAKE_BUILD_TYPE inside the cacheVariables configure preset variable to match your desired build type. The configuration inside the build preset should also match the build type.
The preset above will configure and build with the build type Debug.
Furthermore, to support the release build type, you only need to include two more presets:
The preset file above includes two configure presets and two build presets, each one for a different build type.
Info
Note that the field configurePreset was also changed and it should match a existing configure preset.
You can try configuring and building for the two build types by running:
Or for release:
Include a workflow
The next step of your CMake preset file is to include a workflow preset. A workflow is basically a bunch of steps you want CMake to execute. Since you already configured and built, you might want to group that into ONE only command — that’s where the workflow shines.
A workflow preset might look like this:
Try runing the workflow by typing:
It will configure and build for you. Crazy good! 😁
Sprinkle CMake with a simple Command Line Interface
If you are like me, you can’t be satisfied with the previous result. Even though the commands work as expected, the commands are still too long and most of it could be easily abstracted.
With the help of Python and its libraries, it is possible to create a CLI with the following methods:
init: generates the Makefiles according to a preset
build: builds the code according to a preset
workflow: executes the workflow steps according to a preset
run: executes the binary
reset: deletes the /build directory
Create a file (do not include the extension .py) in the root project directory. I’ve named it example.
My example file contains:
I’ve also added the example path into the $PATH with:
And finally, to run any command inside the example, all you have to do is:
If you want to execute your workflow preset, you simply run:
Info
The build type is Debug as default.
In case it is a release build:
That’s all folks! Not only you ended up with a 2 words command to compile your code, but the entire code necessary to reach this result is also easy to understand and to go through. The JSON preset is readable and quite flexible: only a few preset options are necesary to make it work.