Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
doc/html/
doc/latex/
.vscode/settings.json
__pycache__
/lib/utilities/vcs_identifier_gen.h
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ Alternatively the software may be executed in a simulation environment.
This project uses [PlatformIO](https://platformio.org/) as build system and package manager.
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.

System requirements:

- [PlatformIO Core](https://docs.platformio.org/en/stable/core/index.html#piocore)
- optional: [git](https://git-scm.com/) client is used to generate version identifier if project files are in a git clone

In order to use the software (some call it "firmware"), the following steps are required:

1. Build (the default configuration of) the project.
Expand Down
25 changes: 25 additions & 0 deletions generate_vcs_identifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
generate_vcs_identifier.py

This script generates a source file containing a version control system (VCS)
identifier string. It retrieves the VCS identifier from the 'vcs_utils' module
and writes it to a specified source file.

This script should be loaded by PlatformIO during the project build and is not
designed to be run independently.
"""

from vcs_utils import get_vcs_id, write_vcs_id_to_file
import os.path
Import("env")

# Get the source directory path from PlatformIO configuration
source_dir = env.subst("$PROJECT_DIR")

# Path to the output file within
output_file = os.path.join(source_dir, 'lib', 'utilities', 'vcs_identifier_gen.h')

vcs_id = get_vcs_id()

if vcs_id:
write_vcs_id_to_file(vcs_id, output_file)
9 changes: 9 additions & 0 deletions lib/utilities/version.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <optional>
#if __has_include("vcs_identifier_gen.h")
#include "vcs_identifier_gen.h"
constexpr std::optional<const char *> vcsId = VCS_ID;
#else
constexpr std::optional<const char *> vcsId = std::nullopt;
#endif
2 changes: 2 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ build_flags =
-DLV_CONF_PATH="${PROJECT_DIR}/lib/3rd_party_adapters/LVGL/lv_conf.h" ; lvgl: use this config file
-DBAUD_RATE=${this.monitor_speed}
monitor_speed = 115200
extra_scripts =
pre:generate_vcs_identifier.py

[env:native]
platform = native
Expand Down
7 changes: 4 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
#include <user_interaction/guiEngine_factory_interface.hpp>
#include <user_interaction/keypad_factory_interface.hpp>
#include <user_interaction/statusindicators_factory_interface.hpp>
#include <version.hpp>

void setup()
{
serial_port::initialize();
serial_port::cout << "\x1b[20h"; // Tell the terminal to use CR/LF for newlines instead of just CR.
static constexpr const auto programIdentificationString = __FILE__ " compiled at " __DATE__ " " __TIME__;
serial_port::cout << std::endl
<< " begin program '" << programIdentificationString << std::endl;
serial_port::cout
<< std::endl
<< " begin program version '" << vcsId.value_or("unknown") << "'" << std::endl;
serial_port::setCallbackForLineReception([](const serial_port::String &commandLine) {
ProtocolHandler::execute(commandLine.c_str());
});
Expand Down
65 changes: 65 additions & 0 deletions vcs_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""
vcs_utils.py

This module provides utility functions to retrieve the version control system
(VCS) identifier using Git and to write it to a file.

The functions handle cases where Git is not installed or the current directory
is not a Git repository, and handle file write failures gracefully.
"""

import subprocess
import sys

def get_vcs_id():
"""
Attempts to retrieve the VCS identifier using the 'git describe' command.

Returns:
str: A string containing the VCS identifier if successful, or an empty
string if Git is not available or the directory is not a Git repository.

This function handles the following exceptions:
- subprocess.CalledProcessError: Raised if the 'git' command fails, e.g.,
if the current directory is not a Git repository.
- FileNotFoundError: Raised if 'git' is not installed or not found in the
system's PATH.

All warnings are printed to stderr.
"""
try:
vcs_output = subprocess.run(
["git", "describe", "--always", "--dirty", "--all", "--long"],
stdout=subprocess.PIPE, text=True, check=True
)
vcs_string = vcs_output.stdout.strip()
return vcs_string
except (subprocess.CalledProcessError, FileNotFoundError) as e:
# Print the warning to stderr
print("Warning: Unable to retrieve VCS description. Error:", str(e), file=sys.stderr)
return ""


def write_vcs_id_to_file(vcs_id, file_path):
"""
Defines a macro with the given VCS identifier as a string literal to a file.

Args:
vcs_id (str): The VCS identifier string to write to the file.
file_path (str): The path to the file to write to.

If the file exists, it will be overwritten. If writing to the file fails,
a warning will be printed to stderr, but the script will not terminate
with an error.
"""
try:
# Prepare the C-style string definition
c_content = f'#define VCS_ID "{vcs_id}"\n'

# Write the content to the file (overwriting if it exists)
with open(file_path, 'w') as file:
file.write(c_content)

except IOError as e:
# If writing to the file fails, print the warning to stderr
print(f"Warning: Unable to write VCS ID to file '{file_path}'. Error: {str(e)}", file=sys.stderr)
Loading