PlatformIO Community

How to build got revision into binary for version output?

Hi all,

first post, please be gentle…

When building, I need to include the git HEAD’s commit hash into a header, so I can have the program print out its version/commit (and whether the tree was dirty or not) on startup. For C++/CMAKE projects, I use GetGitRevisionDescription.cmake. Is there something like this in platformio?

I was thinking to use “extra_scripts = pre:custom.py” and have that append the output of “git rev-parse HEAD” to a file that already contains "#define GIT_SHA1 ". That would work, right?

And then I thought it’d be nice to put this magic into a library, so that I can just include e.g. the version.h from that library and re-use that in multiple projects.

And then it seems like this probably has been done before, or maybe even is a standard feature in platformio that haven’t found yet?

What’s the best way of doing this?

Thanks!

Depends… is being slapped with a wet fish considered gentle? :fishing_pole_and_fish: :laughing: Welcome to the forum! :wink:

@sblantipodi made this automation that you can plug in for a self-incrementing version number.

It sounds like that would be a good starting point to make something that grabs the commit/tag version/tree state, or even another feature that could be added.

Thanks pfeerick! Looks like @sblantipodi is doing this using the same extra_scripts hook, so I tried something along those lines. Created a “version” library/folder, contents are:

version.h

#pragma once
#include <string>
class Version {
  public:
    static std::string getGitCommitSha1();
    static std::string getBuildTimestamp();
};

custom.py

import datetime
import os
import subprocess

Import("env")

VERSION_FILE = 'version.cpp'

result = subprocess.run(['git', 'rev-parse', 'HEAD'], stdout=subprocess.PIPE).stdout.decode('utf-8')

VERSION_CONTENTS = """
#include "version.h"
std::string Version::getGitCommitSha1() {
 return "{}";
}
std::string Version::getBuildTimestamp() {
 return "{}";
}
""".format(result, datetime.datetime.now())

if os.environ.get('PLATFORMIO_INCLUDE_DIR') is not None:
    VERSION_FILE = os.environ.get('PLATFORMIO_INCLUDE_DIR') + os.sep + VERSION_FILE
elif os.path.exists("include"):
    VERSION_FILE = "include" + os.sep + VERSION_FILE
else:
    PROJECT_DIR = env.subst("$PROJECT_DIR")
    os.mkdir(PROJECT_DIR + os.sep + "include")
    VERSION_FILE = "include" + os.sep + VERSION_FILE

print("Updating {} with version/timestamp...".format(VERSION_FILE))
with open(VERSION_FILE, 'w+') as FILE:
        FILE.write(VERSION_CONTENTS)

platformio.ini

extra_scripts = pre:custom.py

The problem is when I include version.h from my project, it builds, but linking fails because undefined reference to Version::getGitCommitSha1[abi:cxx11](). And I cannot find a version.cpp, or the output of custom.py’s print(). Do I need to explicitly tell platformio to evaluate the platform.ini of the version-library?

If you’re using *nix (macOS should work too, but can’t check due to lack of hardware ;-)) you can use some shell “magic” and add something like that

build_flags = !echo "-DSOME_MACRO="$(git log |head -1 |cut -c8-)

to your platformio.ini. If you start your build SOME_MACRO will be set to commit hash and you can use it anywhere in your sourcecode without the need of an additional include file.

g++ -o .pio/build/native/src/json_consts.o -c -DPLATFORMIO=40304 -DSOME_MACRO=84c84ff34077768c89b5e2b82122db53fa3b8ff5 -Iinclude -Isrc -I.pio/libdeps/native/ArduinoJson/src -I.pio/libdeps/native/googletest -I.pio/libdeps/native/googletest/googlemock/include -I.pio/libdeps/native/googletest/googlemock -I.pio/libdeps/native/googletest/googletest/include -I.pio/libdeps/native/googletest/googletest -I.pio/libdeps/native/ArduinoFake_ID1689/src src/json_consts.cpp

1 Like