2

Is there any way to get the current Git tag/commit identifier into an Arduino sketch binary?

For normal desktop program development, you can pull some tricks with the Makefile (as pointed out in this StackExchange answer). However, there is no Makefile for an Arduino sketch. Right?

I could make a batch file that I run before every compile, but there is the very real possibility I will forget to run it, and incorrect version information is worse than no version information.

At the moment, I am using the preprocessor macros __DATE__ and __TIME__ to try and identify what version is running on the board. This works, but tracking backwards from a compile date/time to a source control commit is more guesswork than anything.

  • You could ditch the Arduino IDE and go for a Makefile-based development. – Edgar Bonet May 1 '16 at 7:13
  • tracking backwards from a compile date/time to a source control commit is more guesswork than anything - why? Commits have the date in them. – Nick Gammon May 1 '16 at 21:17
  • @EdgarBonet I think that is what I am looking for! I will give that a try. If you post that as an answer, I can accept it. – DAVe3283 May 3 '16 at 1:37
3

Inspired by Cellie's answer, I investigated further and found a similar method that can be implemented using the regular interface of the Arduino IDE.

It appears that GitHub user Wackerbarth, while facing the very same problem, opened an issue on the Arduino bug tracker:

It would be very useful to be able to add a recipe to the platform specification that is executed at the start of the build process. (pre-build)

In particular, my use case is to generate version strings which will be incorporated in the Rom image based on information extracted from a SCM repository.

He went on to submit a pull request for adding “hooks” to the build process, which made it to release 1.6.2. See the documentation on these Pre and post build hooks.

Here is how you can use this feature for including git commit information into your program (tested on Arduino 1.8.5 / Ubuntu 16.04):

  1. Save the following file under the name make-git-version, somewhere in your PATH, and make it executable:
#!/bin/bash

# Go to the source directory.
[ -n "$1" ] && cd "$1" || exit 1

# Build a version string with git.
version=$(git describe --tags --always --dirty 2> /dev/null)

# If this is not a git repository, fallback to the compilation date.
[ -n "$version" ] || version=$(date -I)

# Save this in git-version.h.
echo "#define GIT_VERSION \"$version\"" > $2/sketch/git-version.h
  1. Locate the file named platform.txt in the Arduino installation directory (currently in arduino-1.8.5/hardware/arduino/avr for the AVR boards). In the same directory, create a file named platform.local.txt with the following content:
recipe.hooks.sketch.prebuild.1.pattern=make-git-version "{build.source.path}" "{build.path}"
  1. In your sketch, include "git-version.h" and use it like so:
#include "git-version.h"

void setup() {
  Serial.begin(9600);
  Serial.println("This is version " GIT_VERSION);
}
  1. Create an empty file in your sketch directory named git-version.h.

Note that the git-version.h in the current directory is only needed for the first compilation. The real git-version.h will be in the temporary build directory.

2

I struggled with Arduino (ESP32) versioning also. To make it somewhat more practical and less error prone I made some scripts to assist this process.

Using these scripts is as easy as adding them to your sketch folder and adding

#include "gitTagVersion.h"
...
Serial.println( sketchVersion );

to your Arduino sketch. That is all that is needed.

The output in the example above will be something like v1.0.0-3-gab3fb04.
That breaks down to tag v1.0.0, we had 3 commits since that tag, at commit ab3fb04.

HOW TO INSTALL AND USE?

There are 2 scripts involved, the first script is a replacement for the Arduino Verify button. Save it as verify.sh:

echo "const char * sketchVersion = \"$(git describe --tags --always --dirty)\";" > gitTagVersion.h
~/arduino-1.8.5/arduino --verify test.ino
rm gitTagVersion.h

And the second script replaces the Upload button. Save it as upload.sh:

echo "const char * sketchVersion = \"$(git describe --tags --always --dirty)\";" > gitTagVersion.h
~/arduino-1.8.5/arduino --upload test.ino --pref custom_DebugLevel=esp32_none
rm gitTagVersion.h

Some things to note about these scripts:

  • The scripts REPLACE the buttons. You won’t be able to use the buttons anymore, as these buttons don’t generate the necessary version info from git.

    Using them will result in this error:

    fatal error: gitTagVersion.h: No such file or directory

  • The scripts are hardcoded to use Arduino 1.8.5 and have to be updated if you update your Arduino IDE.

  • These script only work in Linux with a vanilla Arduino install.

  • If you use Windows, or are on a Mac the scripts will not work.

  • To change the debug output (using the LOGx_ESP macros) on ESP32 builds, change the custom_DebugLevel in the Upload script to esp32_xxxx, where xxxx is none, info, error, debug or verbose.

I posted this also on my blog and esp32.com

  • I would drop the -n in echo -n '";': it is customary in Unixland that text files (specially source code) end with a line feed. Also, you could replace the first three lines of each of those scripts by echo "const char * sketchVersion = \"$(git describe --tags --always --dirty)\";" > gitTagVersion.h – Edgar Bonet Apr 3 '18 at 20:18
  • In general, improving the answer is preferred whenever it makes sense to do so. – Edgar Bonet Apr 3 '18 at 21:16
1

I'm not sure what the commit ID would prove. I use git for source control for my Arduino sketches, but a particular upload might be halfway between the previous commit and the next one. That is, the code on the board might not match any particular commit.

The date/time would at least identify approximately where in the commit stream the code is.

A possibility would be to run a cron job that periodically (say, every minute) updates a .h file with the current commit ID from the branch, and include that in the sketch.

  • It is true that you can be compiling with a dirty working copy, but at least you know for sure what commit you started with for that firmware. With just a date, you can't know for sure which branch was compiled, especially if multiple branches were updated at about the same time. And finally, using date/time leads to problems with time zones, lending even more ambiguity to exactly what was compiled. – DAVe3283 May 3 '16 at 1:39
  • If you say so. A "dirty working copy" could be anything. I'm not sure what the original commit ID proves. using date/time leads to problems with time zones - how many time zones are you in? I'm in one, personally. – Nick Gammon May 3 '16 at 7:13
  • I still work with friends from college, and we now live in different states. The time zone thing has bit me in the past, I'm not trying to be a jerk or anything. Knowing the original commit ID lets me know what branch the sketch came from, at least. I do agree that a dirty working copy can indicate anything, but generally it is close to the base commit. – DAVe3283 May 7 '16 at 5:26
  • People have made makefiles to compiler their Arduino stuff. I can't think of any really simple way of doing it, short of my suggestion of a cron job to update a .h file regularly. – Nick Gammon May 7 '16 at 22:06
1

If you want to do Makefile-like tricks, one possibility is to use a Makefile-based workflow instead of the Arduino IDE. There are a few generic Arduino Makefiles floating around the Web. One quite popular is Sudar Muthu's Arduino Makefile. With it, you just write a small per-project Makefile that sets a few variables and then includes the generic Makefile. There is one limitation with this approach though: the Arduino IDE normally modifies your .ino file before submitting it to the compiler, in two ways:

  1. It #includes <Arduino.h>
  2. It writes prototypes near the beginning of the program for every function you define.

Sudar Muthu's Makefile does include Arduino.h (it does not touch your code, using instead the -include gcc option), but it does not write the function prototypes for you. It is thus not 100% compatible with the Arduino IDE.

Another possibility would be to completely write yourself a Makefile that calls Arduino Builder. This should be 100% compatible with the IDE.

1

If you're using Platformio, add this in platformio.ini file

build_flags = 
    !echo '-D GIT_VERSION=\\"'$(git rev-parse HEAD)'\\"'

And use it like this:

Serial.printf("Firmware version: %s\n", GIT_VERSION);

Check out relevant docs: http://docs.platformio.org/en/latest/projectconf/section_env_build.html#dynamic-build-flags

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.