little helper tool wrapping invocation of presets

I found myself still using simple Makefiles on top of CMake presets, for things like:

  • having default generators for each platform without making a different preset for each platform
  • setting the number of jobs to the number of cores on the machine
  • invoking a configure preset automatically if its binary dir doesn’t exist when the user invokes a build preset
  • invoking a build preset with a certain target specified, so I don’t have to write another preset to do that
  • simple clean operations

Make provided all the functionality I need on Unix, but it’s not very portable to Windows, and it was more code to maintain than I would’ve liked.

So I decided to write a little tool that is specially tuned for these kinds of use cases:

bake is a simple command line utility that invokes cmake presets. The syntax is bake <kind>[<name>], where kind is config, build, or test, and name is the name of a non-hidden preset of the corresponding kind in the working directory’s CMakePresets.json.

It works with absolutely no configuration at all – you can just use the bake <kind>[<name>] syntax and it should give you sensible defaults. But if you wish, it also accepts a barebones configuration file called a Bakefile:

  • It’s a series of sections containing options

  • Lines starting with # and empty lines are ignored

  • Lines starting with * or - are options in a section

  • All other lines start a new section

Valid sections are:

  • Generators: specify CMake generators to be used on Mac, Windows, and Linux
  • Aliases: specify a set of one-word aliases for other actions, for example all: build[all] means you can type bake all instead of bake build[all]. For aliases of build presets, you can also use an arrow -> to specify a certain target, for example onlyOne: build[all] -> target1 means bake onlyOne will expand to cmake --build --preset all --target target1.
  • Clean: a set of files or directories, relative to the Bakefile directory, that will be removed when bake clean is invoked. bake clean also traverses all subdirectories recursively, and for any subdir containing a Bakefile, evaluates those clean commands as well.
  • Wipe: similar to clean, but intended for wiping persistent caches, like fetched sources of dependencies.
  • Logs: If specified, names a directory relative to the Bakefile directory where bake will write logs of all cmake config and test runs. This logs directory is automatically removed by bake clean.

All sections are optional, and you can use bake without writing a Bakefile by sticking with the bake <kind>[<name>] syntax.

Example Bakefile:

Generators:
* Mac: Xcode
* Windows: Visual Studio 16 2019
* Linux: Ninja

Aliases:
* config: config[default]
* all: build[all]
* ios: build[ios]
* plugins: build[all] -> ALL_PLUGINS
* apps: build[all] -> ALL_APPS
* tests: test[all]

Clean:
* Builds/

Wipe:
* Cache/

Logs: 
* logs

The entire goal here is to be lightweight, self documenting, and cross platform.

I hope someone finds this useful – any suggestions and feedback are welcome, and the code is completely free to use in any capacity!