I am evaluating if cmake
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 (https://semver.org/) 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:
product_v1.2.3-alpha.1+3e4d243-dirty.elf
or
product_v1.2.3+a45cb2f.map
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 binary 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.
Having said this long premise I would like to understand (with you) if CMake can be used in such a context. Is it possible for CMake to generate a set of makefiles or ninja that respect the above constraints and behave similar (or identical) to our current build flow?
best regards
Max