Version Numbering

Versioning

Knowing what version of code you are running is very important. Using a meaningful version numbering, such as semantic versioning, gives levels of detail implicit in the numbering.

Sometimes it's not enough to know the version, you sometimes also need to know who built the code, how, and when. Automating version numbering within your build flow can help with this.

Semantic Versioning

For years I've been in teams where we mumbled through when and how to manage a version number. Often we'd use a major and minor number, and possibly a build number. We were not the only teams considering the notion. There is now a good standard to follow from semver.org. At the time of writing Semantic Versioning 2.0.0 was the current version.

Semantic Versioning

Semver.org address the needs of package managers and build systems that look at package dependencies. By using the right versioning in a package release along with the appropriate patterns in a pre-requisite list the most recent, appropriate version of a package can be integrated.

The format laid out in the semver.org specification is a good rule set for any versioning scheme.

Sample Crate Dependency File

Here is an example of a Cargo.toml file for a Rust project:

[package]
name = "your_project_name"
version = "0.1.0"
authors = ["Your Name <[email protected]>"]
edition = "2018"

[dependencies]
serde = "1.0"
rand = "0.8"

In this file, you can see the version number specified for the project itself as well as for its dependencies. This helps in managing and maintaining the correct versions of the packages used in the project.

Automated Version ID

For years I have maintained version numbers by hand. Indeed, major and minor version identifiers are incremented as part of the release process. However build numbers are best managed automatically.

A problem that is prevalent in firmware development is the sharing or binaries, especially with QA and HW teams. You may be working on a branch of the repository and deploy a quick fix to a DUT in the lab. The you may be trying out a new bootloader, low power manager or main executable. You should have at least a commit for this release, but sometimes, in the heat of the development, you quickly iterate changes without and revision control actions.

The extra build information you can put into your binary automatically includes:

  • build time

  • incrementing build tag

  • machine name

  • user name

  • repo clone info

    • SHA

    • "dirty"

    • branch ID

Build time

Assuming the build machines time is synced periodically on the network, this should give good indication of the sequence of build.

There is always a risk of two machines having the build at the same time, but realistically, that is small.

Incrementing build number

If everything is built on the central build server, or every machine polls a common build counter, then all is good.

If machines manage build number locally, then two engineers working in parallel may build with the same sequence number.

Machine and User names

Adding the machine and user name will disambiguate any timestamp or sequence number issues.

Sample Code for Automated Versioning

This section generated in VS Code with CoPilot using ChatGPT 4o. Code not reviewed.

Here is a sample script in Python that reads a version.h file for major and minor version numbers, retrieves Git information, and polls the hardware for machine and user IDs:

This script reads the major and minor version numbers from a version.h file, retrieves the current Git SHA, branch name, and cleanliness of the working directory, and gets the machine and user names. This information can be used to automate versioning in your build process.

SCCS Identification Strings and what

SCCS (Source Code Control System) is an older source control system.

One feature of SCCS is the sccsid string which is embedded in source code. This identifier was maintained by SCCS as revisions were committed. If you are using another source control system, you can embed this string yourself.

The sccsid can propagate into the resultant binary files when the code is compiled. The command what will find all sccsids within a binary file.

The sccsid string is starts with the tag @(#) and ends with one of ", >, newline, \, nul. This format is detailed in the documentation for the what command.

I really like having the sccsid embedded in the binary. Filenames can get modified, so you never truly know what the image is, unless you open it with a hex editor and find the version string. With the sccsid, you can look for the tag within your hex editor. Even simpler, run the what command!

Last updated