How to build got revision into binary for version output?

I solved this problem with git describe and the advanced scripting.

First off, I use git tags for versioning. I dont bother with manually writing it anywhere, it should all be based on the git tags. This makes CI and such really easy, Since I never forget to update the version in some file somewhere.

Here is an example:

platformio.ini

[env:my_env]
platform = teensy
board = teensy40
framework = arduino
extra_scripts = 
    pre:auto_firmware_version.py

auto_firmware_version.py

import subprocess

Import("env")

def get_firmware_specifier_build_flag():
    ret = subprocess.run(["git", "describe"], stdout=subprocess.PIPE, text=True) #Uses only annotated tags
    #ret = subprocess.run(["git", "describe", "--tags"], stdout=subprocess.PIPE, text=True) #Uses any tags
    build_version = ret.stdout.strip()
    build_flag = "-D AUTO_VERSION=\\\"" + build_version + "\\\""
    print ("Firmware Revision: " + build_version)
    return (build_flag)

env.Append(
    BUILD_FLAGS=[get_firmware_specifier_build_flag()]
)

main.cpp

#include <Arduino.h>

void setup(){
    serial.begin(115200);
    serial.print("Firmware Version: ");
    serial.println(AUTO_VERSION);   // Use the preprocessor directive

   // OR //

   char firmware_char_array[] = AUTO_VERSION;
   serial.println(firmware_char_array, sizeof(firmware_char_array));
}

void loop(){
    // Loop
}

With this configuration, you get the firmware version as a string literal. You can use it however you want since it is dealt with in the preprocessor and not compiler.


This, for example, will print the tag that the commit is aligned with:

v1.2.3

or, if there isnt a tag at the commit, the relation to the latest tag:

v1.2.3-13-gabc1234
└────┤ └┤  └─────┴─ Short commit Hash (not the g)
     │  └─ Distance from tag
     └─ Latest Tag in Git

You can customize this string however you like in the python script, For example:

build_version = "My_Project_Firmware-" + ret.stdout.strip() + "-" + env['PIOENV'].upper()

would produce:

My_Project_Firmware-v1.2.3-13-gabc1234-MY_ENV

I use the env['PIOENV'] to distinguish between different build environments, Useful if you have regular builds and debug builds.

3 Likes