Version Numbering
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.
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:
import os
import subprocess
def get_version_info():
# Read version.h file
with open('version.h', 'r') as file:
lines = file.readlines()
version_info = {}
for line in lines:
if 'MAJOR' in line:
version_info['major'] = line.split()[-1]
elif 'MINOR' in line:
version_info['minor'] = line.split()[-1]
# Get Git information
git_sha = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8')
git_branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).strip().decode('utf-8')
git_status = subprocess.check_output(['git', 'status', '--porcelain']).strip()
git_dirty = 'dirty' if git_status else 'clean'
# Get machine and user information
machine_name = os.uname().nodename
user_name = os.getlogin()
# Combine all information
version_info.update({
'git_sha': git_sha,
'git_branch': git_branch,
'git_dirty': git_dirty,
'machine_name': machine_name,
'user_name': user_name
})
return version_info
if __name__ == "__main__":
version_info = get_version_info()
print("Version Information:")
for key, value in version_info.items():
print(f"{key}: {value}")
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.
Last updated