Evaluate generation tools like cmake and meson as an alternative to make

My projects are getting bigger and more complex. I have always used GNU Make, but it gets hard to maintain.
For this reason I am evaluating if cmake or meson can help me in my projects.

First of all I should make a premise about the constraints we have in the build processes.
We build products based on microcontrollers running baremetal or RTOS (FreeRTOS) firmware.
The products are getting more and more complex. They use more microcontrollers, and FWs are encrypted. The FWs themselves are getting more and more complex, a few hundred files, dozens of directories, use of third-party libraries and middleware, etc…
At the moment we are using make , but makefiles become less and less maintainable as projects get more complicated.

We produce executable files in all formats: .elf for debugging, .bin , .ihex , etc. for the production department. We also produce some compendium files like .map , .lss , .sym , etc.

We adopt a semantic versioning ( scheme. The metadata field is populated with commit tag of git (command git describe --always --dirty --broken --exclude=* ).

All files that we produce must also contain the version in the name, for example:
Symlinks must be created whose names must not contain the version (for debugging purposes):
product.bin -> product_v1.2.4-rc.2+f599a72.bin

We adopt the out-of-tree build: all files (finished products and semi-finished products ) must reside in a dedicated directory. In particular we also split final images from semi-finished products. This also applies to the generated code that will never “mix” with the handwritten code.

The FW must know its version. The solution found at the moment is to have a target in the makefile that writes a header file containing all the information about the version. This file is not rewritten if the version is not changed (including metadata). This header file is included from a single .c (this is for dependency issues).

I would like to try to illustrate our flow with some schemes.

Here is the basic build flow. Starting from input files we get a plain executable.

I would like to point out that the .lst should reside together with the .o and the .d .

Then I use the previous macro to build the encrypted binary:

Once I have all my binaries encrypted I can bundle them in a single deploy package:

In any case I might want to pack the plain versions (for debugging needs):

A further requirement is that it must always be possible to specify one of the semi-finished products as target. For example it must be possible to specify the FW2 plain or the FW3 encrypted and these must be built without creating the deployment package or other binaries like FW1.

Having said this long premise I would like to understand (with you) if CMake or Meson can be used in such a context. Is it possible for CMake on Meson to generate a set of makefiles or ninja that respect the above constraints and behave similar (or identical) to our current build flow? I would like to get an idea of what might be the best choice in an embedded context such as the one I have illustrated.
As you can see there are several “doubtful” points:

  • the ability to configure custom commands to run at build time to generate code.
  • the ability to express the correct dependencies also for the generated source files
  • The ability to configure the feature that at build time the target names can be dynamic (solvable also with an ‘install’ phase).

I can also accept that the answer to my questions may be that make is still the better choice than the others in a scenario like the one described above.

best regards

I am no expert of meson or cmake, but from what I know all of the use cases you highlighted should be well within the set of things they support. Indeed I think any modern build system will support your workflow.

Phillip at Embedded Artistry is a big fan of Meson, and he often writes about it. Here’s his Field Atlas entry about it: He also has courses on Meson that you could look into.