How to automatically get Git tag into STM32CubeIDE code

One very important aspect of any development is versioning. Sure, for small projects it might not be necessary, but I’ve gotten used to using Git (in the form of EGit plugin in CubeIDE) for almost all of my projects. And of course for larger (commercial) projects with multiple prototype runs, firmware versions etc., proper versioning is a must.

Well yesterday I read this article about getting Git commit tag and hash into your C code and I immediately realized just how powerful this could be – for example, on almost all of my projects I have a UART TX for debug, so at startup, I’d be capable of printing the commit hash, tag and for example build date. So this way, I’ll always know exactly what code is running on that particular device.

The two problems with the linked article is that it’s written mostly for Linux and, more importantly, it’s modifying a makefile. I use Windows and CubeIDE, which uses automatically generated makefile, so you cannot just copy what’s in the linked article. Anyways, I decided to modify the workflow to suit my setup. Originally, I thought that it will be a matter of tens of minutes – well, I spent most of yesterday’s afternoon on this.

The first point worth mentioning is that the GNU GCC compiler, used by CubeIDE, already has some built in macros, which could be used for some primitive versioning – those are, for example the __DATE__ or __FILE__ macros. But my goal was getting the Git commit hash into my C code.

Fortunately, CubeIDE allows you to run a command from console (right click on Project -> Properties -> C/C++ Build -> Build steps) before and after the build process itself, so I tried running a bat file. While it kind of worked (note that CubeIDE starts the console in the /Debug folder, so the bat had to be placed there), I was getting a lot of Access Denied errors on various commands – I am still not sure why, those commands should not have required admin privileges.

My next try was using a powershell script (*.ps1 file), which worked much better and powershell also allows much easier formatting of strings than a bat file. I never used powershell before, so it took me quite some time, but I finally managed to make a script which creates/rewrites version.h file in the /Inc folder. This file contains multiple defines:

  • _V_GIT_FULL
  • _V_BUILD_TAG
  • _V_COMMIT
  • _V_COMMITS_AHEAD
  • _V_GIT_DIRTY_FLAG
  • _V_DATE
  • _V_COMPNAME

These can then be, of course, used as arguments in a printf or whatever. This is how the script looks:

$gitVersion =  &"C:\Program Files\Git\cmd\git.exe" describe --long --dirty --tags
#echo $gitVersion

$gitSplit = $gitVersion.Split('-')
$currentDate = Get-Date -Format "dd.MM.yyyy HH:mm"
$targetFile = $PSScriptRoot + "\Inc\version.h"

Clear-Content -Path $targetFile
Add-Content -Path $targetFile -Value ("#ifndef VERSION_H_`n#define VERSION_H_`n")

Add-Content -Path $targetFile -Value ("#define _V_GIT_FULL       (const char*)""" + $gitVersion + """") 

Add-Content -Path $targetFile -Value ("#define _V_BUILD_TAG      (const char*)""" + $gitSplit[0] + """")
Add-Content -Path $targetFile -Value ("#define _V_COMMIT         (const char*)""" + $gitSplit[2] + """") 
Add-Content -Path $targetFile -Value ("#define _V_COMMITS_AHEAD   " + $gitSplit[1]) 

if ($gitSplit[3] -eq "dirty")
{
    Add-Content -Path $targetFile -Value ("#define _V_GIT_DIRTY_FLAG")  
}

Add-Content -Path $targetFile -Value ("#define _V_DATE           (const char*)""" + $currentDate + """") 
Add-Content -Path $targetFile -Value ("#define _V_COMPNAME       (const char*)""" + $env:computername + """") 

Add-Content -Path $targetFile -Value "`n#endif"

echo "git2header executed"

Some notes on the above script:

  • For some reason I had to put absolute path to git.exe, even though in normal powershell I can just use git.
  • The ps1 file is placed in the root of the project.
  • The project folder is also a repository, meaning that there is a hidden .git folder. While this is not recommended by the EGit manual, because then you cannot have multiple projects in one repository, for me that’s ok.
  • I recommend adding the version.h file into the .gitnore (by adding the entry /Inc/version.h into .gitignore file)
  • The command used to run the script before build itself is powershell.exe "..\git2header.ps1"

Update 04/21: Just as a sidenote, you can get the current CMSIS version by using the macro __STM32G0_CMSIS_VERSION (substitute the G0 for the family you are using).

3 Replies to “How to automatically get Git tag into STM32CubeIDE code”

  1. Brilliant!

    Do you think that there’s is a Linux equivalent of your script?

    If not, and if you have posted your Powershell version on Github, I can send you a PR with the bash script, once I will find a moment to code it 🙂

    Thanks for sharing your work!

    1. Hi,

      I’m sure this is possible in linux, but I’ve never worked with bash, so I cannot be of any help… But if you make a PR with it, I’ll gladly accept it on Github and of course give you all the due credit for it.

    2. Did the about the same but with perl (works for Win/Linux/Mac)

      #!/usr/bin/perl

      open(OUTPUT, “> fw_version.h”);

      # get current commit hash
      $ver = `git rev-parse –short=8 HEAD`;
      $ver =~ s/\R//g;

      #get latest tag
      # $tag = `git describe –abbrev=0`;

      #get tag at HEAD commit
      $tag = `git tag –points-at HEAD`;
      $tag =~ s/\R//g;

      $dirty = “”;
      # check if there are changed files
      `git diff –quiet HEAD`;
      if( $?>0 )
      {
      $dirty = “-d”;
      }
      # check if there are new untracked files
      $ret = `git ls-files –others –exclude-standard .`;
      if( $ret ne “” )
      {
      $dirty = “-d”;
      }

      if( $tag eq “” )
      {
      print(OUTPUT “#define FW_VERSION \””.$ver.$dirty.”\”\n” );
      }
      else
      {
      print(OUTPUT “#define FW_VERSION \””.$ver.$dirty.”\”\n”);
      }

Leave a Reply

Your email address will not be published. Required fields are marked *