Here’s a quick and easy way to make sure the version string in our firmware is never out of sync with our {% c-line %}git tag{% c-line-end %}.
We’re going to assume semantic versioning for the firmware, because it’s simple and easy to understand.
First we tag our first development release on {% c-line %}main{% c-line-end %} :
{% c-block language="bash" %}
$ git tag 0.0.1
$ git push --tags
{% c-block-end %}
We can now use the following line to generate a version string on any commit:
{% c-block language="bash" %}
$ git describe --tag --always --dirty="+"
0.0.1-4-g9913f2b8d
{% c-block-end %}
The above shows that the current branch is 4 commits ahead of the commit tagged as {% c-line %}0.0.1{% c-line-end %} and that the current branch's hash is {% c-line %}9913f2b8d{% c-line-end %}.
If, instead, we run that command on the most recently tagged commit on {% c-line %}main{% c-line-end %} , we'll get:
{% c-block language="bash" %}
$ git describe --tag --always --dirty="+"
0.0.1
{% c-block-end %}
We now have a handy tool for generating a version string that enables us to uniquely identify the firmware running on a device. Next we need to integrate that into our build system, for example {% c-line %}CMake{% c-line-end %}.
First let’s create a basic template for what our version header file will look like and name it {% c-line %}version.h.in{% c-line-end %}:
{% c-block language="c" %}
#ifndef VERSION_H
#define VERSION_H
#define GIT_VERSION "@GIT_VERSION@"
#endif //VERSION_H
{% c-block-end %}
Now, let’s add this snippet to one of our {% c-line %}CMakeLists.txt{% c-line-end %} files in the project:
{% c-block language="cmake" %}
find_package(Git)
if(GIT_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty="+"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else()
set(GIT_VERSION "0.0.0")
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_BINARY_DIR}/version.h @ONLY)
{% c-block-end %}
Now, when we build our project, a new file called {% c-line %}version.h{% c-line-end %} will be created in our {% c-line %}build{% c-line-end %} directory. This file contains the {% c-line %}GIT_VERSION{% c-line-end %} which is a {% c-line %}#define{% c-line-end %} of our generated version string. We can now include {% c-line %}version.h{% c-line-end %} in any file we want to grab our version string.
On device bootup, we can log what firmware version is running with {% c-line %}printf("Firmware Version: %s", GIT_VERSION);{% c-line-end %} or if we're using ZephyrRTOS, {% c-line %}LOG_INF("Firmware Version: %s", GIT_VERSION);{% c-line-end %}.
Reach out to learn more about Lager's hardware test automation platform.
Try One Month Free
hello@lagerdata.com