Skip to content

Commit 585791b

Browse files
authored
improve self identification string (#136)
Resolves #93
2 parents 8b3cd29 + cd10fa4 commit 585791b

File tree

7 files changed

+112
-3
lines changed

7 files changed

+112
-3
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
doc/html/
88
doc/latex/
99
.vscode/settings.json
10+
__pycache__
11+
/lib/utilities/vcs_identifier_gen.h

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ Alternatively the software may be executed in a simulation environment.
3939
This project uses [PlatformIO](https://platformio.org/) as build system and package manager.
4040
PlatformIO may be used via a GUI (PlatformIO IDE) or command line interface (PlatformIO Core). The project configuration ([`platformio.ini`](platformio.ini)) is part of this repository.
4141

42+
System requirements:
43+
44+
- [PlatformIO Core](https://docs.platformio.org/en/stable/core/index.html#piocore)
45+
- optional: [git](https://git-scm.com/) client is used to generate version identifier if project files are in a git clone
46+
4247
In order to use the software (some call it "firmware"), the following steps are required:
4348

4449
1. Build (the default configuration of) the project.

generate_vcs_identifier.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""
2+
generate_vcs_identifier.py
3+
4+
This script generates a source file containing a version control system (VCS)
5+
identifier string. It retrieves the VCS identifier from the 'vcs_utils' module
6+
and writes it to a specified source file.
7+
8+
This script should be loaded by PlatformIO during the project build and is not
9+
designed to be run independently.
10+
"""
11+
12+
from vcs_utils import get_vcs_id, write_vcs_id_to_file
13+
import os.path
14+
Import("env")
15+
16+
# Get the source directory path from PlatformIO configuration
17+
source_dir = env.subst("$PROJECT_DIR")
18+
19+
# Path to the output file within
20+
output_file = os.path.join(source_dir, 'lib', 'utilities', 'vcs_identifier_gen.h')
21+
22+
vcs_id = get_vcs_id()
23+
24+
if vcs_id:
25+
write_vcs_id_to_file(vcs_id, output_file)

lib/utilities/version.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
#include <optional>
4+
#if __has_include("vcs_identifier_gen.h")
5+
#include "vcs_identifier_gen.h"
6+
constexpr std::optional<const char *> vcsId = VCS_ID;
7+
#else
8+
constexpr std::optional<const char *> vcsId = std::nullopt;
9+
#endif

platformio.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ build_flags =
2121
-DLV_CONF_PATH="${PROJECT_DIR}/lib/3rd_party_adapters/LVGL/lv_conf.h" ; lvgl: use this config file
2222
-DBAUD_RATE=${this.monitor_speed}
2323
monitor_speed = 115200
24+
extra_scripts =
25+
pre:generate_vcs_identifier.py
2426

2527
[env:native]
2628
platform = native

src/main.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@
1313
#include <user_interaction/guiEngine_factory_interface.hpp>
1414
#include <user_interaction/keypad_factory_interface.hpp>
1515
#include <user_interaction/statusindicators_factory_interface.hpp>
16+
#include <version.hpp>
1617

1718
void setup()
1819
{
1920
serial_port::initialize();
2021
serial_port::cout << "\x1b[20h"; // Tell the terminal to use CR/LF for newlines instead of just CR.
21-
static constexpr const auto programIdentificationString = __FILE__ " compiled at " __DATE__ " " __TIME__;
22-
serial_port::cout << std::endl
23-
<< " begin program '" << programIdentificationString << std::endl;
22+
serial_port::cout
23+
<< std::endl
24+
<< " begin program version '" << vcsId.value_or("unknown") << "'" << std::endl;
2425
serial_port::setCallbackForLineReception([](const serial_port::String &commandLine) {
2526
ProtocolHandler::execute(commandLine.c_str());
2627
});

vcs_utils.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""
2+
vcs_utils.py
3+
4+
This module provides utility functions to retrieve the version control system
5+
(VCS) identifier using Git and to write it to a file.
6+
7+
The functions handle cases where Git is not installed or the current directory
8+
is not a Git repository, and handle file write failures gracefully.
9+
"""
10+
11+
import subprocess
12+
import sys
13+
14+
def get_vcs_id():
15+
"""
16+
Attempts to retrieve the VCS identifier using the 'git describe' command.
17+
18+
Returns:
19+
str: A string containing the VCS identifier if successful, or an empty
20+
string if Git is not available or the directory is not a Git repository.
21+
22+
This function handles the following exceptions:
23+
- subprocess.CalledProcessError: Raised if the 'git' command fails, e.g.,
24+
if the current directory is not a Git repository.
25+
- FileNotFoundError: Raised if 'git' is not installed or not found in the
26+
system's PATH.
27+
28+
All warnings are printed to stderr.
29+
"""
30+
try:
31+
vcs_output = subprocess.run(
32+
["git", "describe", "--always", "--dirty", "--all", "--long"],
33+
stdout=subprocess.PIPE, text=True, check=True
34+
)
35+
vcs_string = vcs_output.stdout.strip()
36+
return vcs_string
37+
except (subprocess.CalledProcessError, FileNotFoundError) as e:
38+
# Print the warning to stderr
39+
print("Warning: Unable to retrieve VCS description. Error:", str(e), file=sys.stderr)
40+
return ""
41+
42+
43+
def write_vcs_id_to_file(vcs_id, file_path):
44+
"""
45+
Defines a macro with the given VCS identifier as a string literal to a file.
46+
47+
Args:
48+
vcs_id (str): The VCS identifier string to write to the file.
49+
file_path (str): The path to the file to write to.
50+
51+
If the file exists, it will be overwritten. If writing to the file fails,
52+
a warning will be printed to stderr, but the script will not terminate
53+
with an error.
54+
"""
55+
try:
56+
# Prepare the C-style string definition
57+
c_content = f'#define VCS_ID "{vcs_id}"\n'
58+
59+
# Write the content to the file (overwriting if it exists)
60+
with open(file_path, 'w') as file:
61+
file.write(c_content)
62+
63+
except IOError as e:
64+
# If writing to the file fails, print the warning to stderr
65+
print(f"Warning: Unable to write VCS ID to file '{file_path}'. Error: {str(e)}", file=sys.stderr)

0 commit comments

Comments
 (0)