From 2ebce5bc859d1d2550bce655edd92e3e6759987a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Wed, 9 Apr 2025 02:24:38 +0200
Subject: [PATCH] [BSP] Print CMake target and Git info during boot log

---
 .vscode/c_cpp_properties.json                 | 33 ++++++-
 cmake/boardcore.cmake                         |  6 +-
 cmake/sbs.cmake                               | 26 +++++-
 cmake/version.cmake                           | 93 +++++++++++++++++++
 .../stm32f205rc_ciuti/interfaces-impl/bsp.cpp |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../stm32f429zi_nokia/interfaces-impl/bsp.cpp |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  7 +-
 .../stm32f429zi_rig/interfaces-impl/bsp.cpp   |  4 +
 .../interfaces-impl/bsp.cpp                   |  3 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 .../interfaces-impl/bsp.cpp                   |  4 +
 version/version.cpp.in                        | 37 ++++++++
 version/version.h                             | 49 ++++++++++
 30 files changed, 334 insertions(+), 8 deletions(-)
 create mode 100644 cmake/version.cmake
 create mode 100644 version/version.cpp.in
 create mode 100644 version/version.h

diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 10e282c57..550933eaf 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -16,16 +16,17 @@
             "${workspaceFolder}/libs/mxgui",
             "${workspaceFolder}/libs/tscpp",
             "${workspaceFolder}/src/shared",
-            "${workspaceFolder}/src/tests"
+            "${workspaceFolder}/src/tests",
+            "${workspaceFolder}/version"
         ]
     },
     "configurations": [
-        // Skyward boards
         {
             "name": "stm32f205rc_ciuti",
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f205rc_ciuti",
@@ -48,6 +49,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_death_stack_v1",
@@ -72,6 +74,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_death_stack_v2",
@@ -95,6 +98,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_death_stack_v3",
@@ -118,6 +122,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_nokia",
@@ -141,6 +146,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_parafoil",
@@ -164,6 +170,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_pyxis_auxiliary",
@@ -186,6 +193,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_rig",
@@ -209,6 +217,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_con_rig",
@@ -232,6 +241,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_conrig_v2",
@@ -254,6 +264,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f756zg_nucleo",
@@ -277,6 +288,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_automated_antennas",
@@ -300,6 +312,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_compute_unit",
@@ -323,6 +336,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_compute_unit_v2",
@@ -346,6 +360,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_rig_v2",
@@ -369,6 +384,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_lyra_biscotto",
@@ -392,6 +408,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_lyra_motor",
@@ -415,6 +432,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_death_stack_v4",
@@ -438,6 +456,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_gemini_gs",
@@ -461,6 +480,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_gemini_motor",
@@ -484,6 +504,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_lyra_gs",
@@ -507,6 +528,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_orion_biscotto",
@@ -530,6 +552,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_orion_engine",
@@ -548,12 +571,12 @@
                 "${workspaceFolder}/src/bsps/stm32f767zi_orion_engine"
             ]
         },
-        // Miosix boards
         {
             "name": "stm32f407vg_stm32f4discovery",
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f407vg_stm32f4discovery",
@@ -576,6 +599,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_stm32f4discovery",
@@ -599,6 +623,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f767zi_nucleo",
@@ -622,6 +647,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f769ni_discovery",
@@ -645,6 +671,7 @@
             "cStandard": "c11",
             "cppStandard": "c++14",
             "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
+            "compileCommands": "${workspaceFolder}/build/compile_commands.json",
             "defines": [
                 "${defaultDefines}",
                 "_MIOSIX_BOARDNAME=stm32f429zi_lyra_cubesat",
diff --git a/cmake/boardcore.cmake b/cmake/boardcore.cmake
index 12c0eff42..503803036 100644
--- a/cmake/boardcore.cmake
+++ b/cmake/boardcore.cmake
@@ -19,8 +19,10 @@
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # THE SOFTWARE.
 
-# Load in BOARDCORE_PATH the project path
-cmake_path(GET CMAKE_CURRENT_LIST_DIR PARENT_PATH BOARDCORE_PATH)
+# Load in BOARDCORE_PATH the project path if not already defined
+if (NOT DEFINED BOARDCORE_PATH)
+    cmake_path(GET CMAKE_CURRENT_LIST_DIR PARENT_PATH BOARDCORE_PATH)
+endif()
 
 # Include dependencies and board list
 include(${BOARDCORE_PATH}/cmake/dependencies.cmake)
diff --git a/cmake/sbs.cmake b/cmake/sbs.cmake
index 8cfd4768d..bb8f93ced 100644
--- a/cmake/sbs.cmake
+++ b/cmake/sbs.cmake
@@ -26,6 +26,12 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 # Load in SBS_BASE the project path
 cmake_path(GET CMAKE_CURRENT_LIST_DIR PARENT_PATH SBS_BASE)
+# Load in BOARDCORE_PATH the boardcore path
+cmake_path(GET CMAKE_CURRENT_LIST_DIR PARENT_PATH BOARDCORE_PATH)
+
+# Add the version information header to the global include path, so that all 
+# targets defined after this point will have access to it (Boardcore, Kernel)
+include_directories(${BOARDCORE_PATH}/version)
 
 # Include the Boardcore libraries
 list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
@@ -37,14 +43,30 @@ function(sbs_target TARGET OPT_BOARD)
         message(FATAL_ERROR "No board selected")
     endif()
 
-    # The only include directory of Boardcore is shared!
     target_include_directories(${TARGET} PRIVATE src/shared)
 
+    # Define the version information generation command
+    add_custom_target(${TARGET}-version-info
+        BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/generated/${TARGET}/version.cpp
+        COMMAND "${CMAKE_COMMAND}"
+        "-D" "TARGET_NAME=${TARGET}"
+        "-D" "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
+        "-D" "BOARDCORE_PATH=${BOARDCORE_PATH}"
+        "-D" "OUT_DIR=${CMAKE_CURRENT_BINARY_DIR}/generated/${TARGET}"
+        "-P" "${BOARDCORE_PATH}/cmake/version.cmake"
+        COMMENT "Generating version information file for ${TARGET}"
+        VERBATIM
+    )
+    # Build the generated version information file as part of the target
+    target_sources(${TARGET} PRIVATE
+        ${CMAKE_CURRENT_BINARY_DIR}/generated/${TARGET}/version.cpp
+    )
+
     if(CMAKE_CROSSCOMPILING)
         # Link the embedded Boardcore library
         target_link_libraries(${TARGET} PRIVATE Skyward::Boardcore::${OPT_BOARD})
 
-        # Linker script and linking options are eredited from the kernel library
+        # Linker script and linking options are inherited from the kernel library
 
         # Add a post build command to create the hex file to flash on the board
         add_custom_command(
diff --git a/cmake/version.cmake b/cmake/version.cmake
new file mode 100644
index 000000000..df2997bdd
--- /dev/null
+++ b/cmake/version.cmake
@@ -0,0 +1,93 @@
+# Copyright (c) 2025 Skyward Experimental Rocketry
+# Author: Niccolò Betto
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# --- Version Information File Generation ---
+
+# Find Git executable
+find_package(Git REQUIRED QUIET)
+
+set(GIT_WORKING_DIR ${CMAKE_SOURCE_DIR})
+
+# Determine dirty status
+execute_process(
+    COMMAND ${GIT_EXECUTABLE} describe --dirty --always --broken
+    WORKING_DIRECTORY ${GIT_WORKING_DIR}
+    OUTPUT_VARIABLE GIT_DESCRIBE_OUTPUT # We don't use the output directly, just for the dirty check
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+    RESULT_VARIABLE GIT_DESCRIBE_RESULT
+    ERROR_QUIET # Ignore errors
+)
+set(GIT_DIRTY_SUFFIX "")
+# Check if the command succeeded AND if its output ends with "-dirty"
+if(GIT_DESCRIBE_RESULT EQUAL 0 AND GIT_DESCRIBE_OUTPUT MATCHES "-dirty$")
+    set(GIT_DIRTY_SUFFIX "-dirty")
+endif()
+
+# Get *annotated* tag name
+execute_process(
+    COMMAND ${GIT_EXECUTABLE} describe --exact-match HEAD
+    WORKING_DIRECTORY ${GIT_WORKING_DIR}
+    OUTPUT_VARIABLE GIT_TAG # Captures the annotated tag name if successful
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+    RESULT_VARIABLE GIT_EXACT_TAG_RESULT # Will be 0 on success, non-zero on failure
+    ERROR_QUIET # Ignore errors, we expect this to fail when not on an annotated tag
+)
+
+# Get branch name
+execute_process(
+    COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
+    WORKING_DIRECTORY ${GIT_WORKING_DIR}
+    OUTPUT_VARIABLE GIT_BRANCH
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+    # No ERROR_QUIET/RESULT_VARIABLE -> CMake halts on git command failure
+)
+
+# Get short commit hash
+execute_process(
+    COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
+    WORKING_DIRECTORY ${GIT_WORKING_DIR}
+    OUTPUT_VARIABLE GIT_REV
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+    # No ERROR_QUIET/RESULT_VARIABLE -> CMake halts on git command failure
+)
+
+# Determine the version info based on tag match result
+set(GIT_VERSION_INFO "")
+if(GIT_EXACT_TAG_RESULT EQUAL 0)
+    # Use the tag name when exactly on an annotated tag
+    set(GIT_VERSION_INFO "${GIT_TAG}")
+else()
+    # Use branch-rev when not on a tag
+    set(GIT_VERSION_INFO "${GIT_BRANCH}-${GIT_REV}")
+endif()
+
+# Construct the final version string
+# Format: <annotated_tag>[-dirty] OR <branch>-<hash>[-dirty]
+set(GIT_VERSION_STRING "${GIT_VERSION_INFO}${GIT_DIRTY_SUFFIX}")
+
+# Additional variables set by the called of this script via command line args:
+# - TARGET_NAME
+# - CMAKE_BUILD_TYPE
+
+configure_file(
+  "${BOARDCORE_PATH}/version/version.cpp.in"
+  "${OUT_DIR}/version.cpp"
+)
diff --git a/src/bsps/stm32f205rc_ciuti/interfaces-impl/bsp.cpp b/src/bsps/stm32f205rc_ciuti/interfaces-impl/bsp.cpp
index 07e96ca01..c689fe5ac 100644
--- a/src/bsps/stm32f205rc_ciuti/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f205rc_ciuti/interfaces-impl/bsp.cpp
@@ -45,6 +45,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 using namespace std;
 
@@ -143,6 +144,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f429zi_con_rig/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_con_rig/interfaces-impl/bsp.cpp
index 02a27c32d..5350dd911 100644
--- a/src/bsps/stm32f429zi_con_rig/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f429zi_con_rig/interfaces-impl/bsp.cpp
@@ -45,6 +45,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -257,6 +258,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f429zi_death_stack_v1/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_death_stack_v1/interfaces-impl/bsp.cpp
index 6e54d48a8..e9bef821e 100644
--- a/src/bsps/stm32f429zi_death_stack_v1/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f429zi_death_stack_v1/interfaces-impl/bsp.cpp
@@ -45,6 +45,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -449,6 +450,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     // PA2,PA3
     intrusive_ref_ptr<DevFs> devFs =
diff --git a/src/bsps/stm32f429zi_death_stack_v2/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_death_stack_v2/interfaces-impl/bsp.cpp
index 8dc6f3db0..25db6f8c5 100644
--- a/src/bsps/stm32f429zi_death_stack_v2/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f429zi_death_stack_v2/interfaces-impl/bsp.cpp
@@ -45,6 +45,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -466,6 +467,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     // PA2,PA3
     intrusive_ref_ptr<DevFs> devFs =
diff --git a/src/bsps/stm32f429zi_death_stack_v3/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_death_stack_v3/interfaces-impl/bsp.cpp
index 4b7e269fe..bab51027f 100644
--- a/src/bsps/stm32f429zi_death_stack_v3/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f429zi_death_stack_v3/interfaces-impl/bsp.cpp
@@ -45,6 +45,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -473,6 +474,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     // PA2,PA3
     intrusive_ref_ptr<DevFs> devFs =
diff --git a/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp.cpp
index e4447baca..56570dcae 100644
--- a/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp.cpp
@@ -45,6 +45,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -386,6 +387,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     // PA2,PA3
     intrusive_ref_ptr<DevFs> devFs =
diff --git a/src/bsps/stm32f429zi_nokia/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_nokia/interfaces-impl/bsp.cpp
index ab9c05cc6..d1588b06d 100644
--- a/src/bsps/stm32f429zi_nokia/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f429zi_nokia/interfaces-impl/bsp.cpp
@@ -46,6 +46,7 @@
 #include "kernel/logging.h"
 #include "kernel/sync.h"
 // #include "kernel/IRQDisplayPrint.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -256,6 +257,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f429zi_parafoil/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_parafoil/interfaces-impl/bsp.cpp
index f4304b85a..7e53e9b6f 100644
--- a/src/bsps/stm32f429zi_parafoil/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f429zi_parafoil/interfaces-impl/bsp.cpp
@@ -45,6 +45,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -272,6 +273,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f429zi_pyxis_auxiliary/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_pyxis_auxiliary/interfaces-impl/bsp.cpp
index 8a9efa1a4..fbd28338e 100644
--- a/src/bsps/stm32f429zi_pyxis_auxiliary/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f429zi_pyxis_auxiliary/interfaces-impl/bsp.cpp
@@ -45,6 +45,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -108,7 +109,11 @@ void IRQbspInit()
                                               : STM32Serial::NOFLOWCTRL)));
 }
 
-void bspInit2() {}
+void bspInit2()
+{
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+}
 
 /**
  * For safety reasons, we never want the board to shutdown.
diff --git a/src/bsps/stm32f429zi_rig/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_rig/interfaces-impl/bsp.cpp
index 42bd1607a..8834f85c3 100644
--- a/src/bsps/stm32f429zi_rig/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f429zi_rig/interfaces-impl/bsp.cpp
@@ -45,6 +45,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -323,6 +324,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f756zg_nucleo/interfaces-impl/bsp.cpp b/src/bsps/stm32f756zg_nucleo/interfaces-impl/bsp.cpp
index b6a873312..0e18c4a05 100644
--- a/src/bsps/stm32f756zg_nucleo/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f756zg_nucleo/interfaces-impl/bsp.cpp
@@ -92,6 +92,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_automated_antennas/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_automated_antennas/interfaces-impl/bsp.cpp
index c9fb4d970..d124e909f 100644
--- a/src/bsps/stm32f767zi_automated_antennas/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_automated_antennas/interfaces-impl/bsp.cpp
@@ -47,6 +47,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -301,6 +302,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_compute_unit/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_compute_unit/interfaces-impl/bsp.cpp
index c1f5a0d80..70a709dfb 100644
--- a/src/bsps/stm32f767zi_compute_unit/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_compute_unit/interfaces-impl/bsp.cpp
@@ -46,6 +46,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -236,6 +237,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp.cpp
index 91166cd57..b8046e81b 100644
--- a/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp.cpp
@@ -46,6 +46,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -260,6 +261,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_conrig_v2/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_conrig_v2/interfaces-impl/bsp.cpp
index 3be9bfc94..67fb4d9e4 100644
--- a/src/bsps/stm32f767zi_conrig_v2/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_conrig_v2/interfaces-impl/bsp.cpp
@@ -47,6 +47,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -301,6 +302,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_death_stack_v4/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_death_stack_v4/interfaces-impl/bsp.cpp
index f839dacd5..e44e7614b 100644
--- a/src/bsps/stm32f767zi_death_stack_v4/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_death_stack_v4/interfaces-impl/bsp.cpp
@@ -47,6 +47,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -353,6 +354,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_gemini_gs/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_gemini_gs/interfaces-impl/bsp.cpp
index 6737470e3..a9295f7fe 100644
--- a/src/bsps/stm32f767zi_gemini_gs/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_gemini_gs/interfaces-impl/bsp.cpp
@@ -47,6 +47,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -288,6 +289,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     // Init devfs with empty device
     basicFilesystemSetup(intrusive_ref_ptr<Device>());
diff --git a/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp.cpp
index aba922231..1b9214364 100644
--- a/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp.cpp
@@ -46,6 +46,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -304,6 +305,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_lyra_biscotto/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_lyra_biscotto/interfaces-impl/bsp.cpp
index 98eca468c..e2e11d0f0 100644
--- a/src/bsps/stm32f767zi_lyra_biscotto/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_lyra_biscotto/interfaces-impl/bsp.cpp
@@ -47,6 +47,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -372,6 +373,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_lyra_gs/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_lyra_gs/interfaces-impl/bsp.cpp
index 753e2dbeb..fabbd381a 100644
--- a/src/bsps/stm32f767zi_lyra_gs/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_lyra_gs/interfaces-impl/bsp.cpp
@@ -46,6 +46,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -342,6 +343,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_lyra_motor/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_lyra_motor/interfaces-impl/bsp.cpp
index 2f8f98c30..6ae339b52 100644
--- a/src/bsps/stm32f767zi_lyra_motor/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_lyra_motor/interfaces-impl/bsp.cpp
@@ -47,6 +47,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -316,6 +317,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_orion_biscotto/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_orion_biscotto/interfaces-impl/bsp.cpp
index a0096a7c7..317be180a 100644
--- a/src/bsps/stm32f767zi_orion_biscotto/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_orion_biscotto/interfaces-impl/bsp.cpp
@@ -47,6 +47,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -373,6 +374,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_orion_engine/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_orion_engine/interfaces-impl/bsp.cpp
index 74de72857..1ab925983 100644
--- a/src/bsps/stm32f767zi_orion_engine/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_orion_engine/interfaces-impl/bsp.cpp
@@ -47,6 +47,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -330,6 +331,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/src/bsps/stm32f767zi_rig_v2/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_rig_v2/interfaces-impl/bsp.cpp
index 02d1867e6..bb197b843 100644
--- a/src/bsps/stm32f767zi_rig_v2/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_rig_v2/interfaces-impl/bsp.cpp
@@ -47,6 +47,7 @@
 #include "kernel/kernel.h"
 #include "kernel/logging.h"
 #include "kernel/sync.h"
+#include "version.h"
 
 namespace miosix
 {
@@ -393,6 +394,9 @@ void IRQbspInit()
 
 void bspInit2()
 {
+    // Print Skyward version info
+    bootlog("%s\n", SKYWARD_VERSION_STRING);
+
 #ifdef WITH_FILESYSTEM
     basicFilesystemSetup(SDIODriver::instance());
 #endif  // WITH_FILESYSTEM
diff --git a/version/version.cpp.in b/version/version.cpp.in
new file mode 100644
index 000000000..73a939309
--- /dev/null
+++ b/version/version.cpp.in
@@ -0,0 +1,37 @@
+/* Copyright (c) 2025 Skyward Experimental Rocketry
+ * Author: Niccolò Betto
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// This file is generated by CMake. Do not edit it directly.
+// See cmake/version.cmake for details.
+
+const char* GIT_REV    = "@GIT_REV@@GIT_DIRTY_SUFFIX@";
+const char* GIT_TAG    = "@GIT_TAG@";
+const char* GIT_BRANCH = "@GIT_BRANCH@";
+
+const char* GIT_VERSION_STRING = "@GIT_VERSION_STRING@";
+
+const char* TARGET_NAME = "@TARGET_NAME@";
+const char* BUILD_TYPE  = "@CMAKE_BUILD_TYPE@";
+
+const char* SKYWARD_VERSION_STRING =
+    "Skyward Eperimental Rocketry (c) @TARGET_NAME@ @ @GIT_VERSION_STRING@ "
+    "(@CMAKE_BUILD_TYPE@)";
diff --git a/version/version.h b/version/version.h
new file mode 100644
index 000000000..5774db9c2
--- /dev/null
+++ b/version/version.h
@@ -0,0 +1,49 @@
+/* Copyright (c) 2025 Skyward Experimental Rocketry
+ * Author: Niccolò Betto
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @file version.h
+ * @brief Generated version information header
+ *
+ * This file contains forward declarations for version information variables.
+ * CMake generates and populates these variables during the build process.
+ * Refer to version.cpp.in for the format and content of the generated file.
+ *
+ * @example Usage:
+ *
+ * #include <version.h>
+ *
+ * std::cout << "Version: " << GIT_VERSION_STRING << std::endl;
+ */
+
+#pragma once
+
+extern const char* GIT_REV;  //< Short commit hash + dirty suffix
+extern const char* GIT_TAG;  //< Tag name if current commit is tagged, or empty
+extern const char* GIT_BRANCH;  //< Current branch name
+
+extern const char* GIT_VERSION_STRING;  //< branch-rev[-dirty] or tag[-dirty]
+
+extern const char* TARGET_NAME;  //< CMake target name
+extern const char* BUILD_TYPE;   //< CMake build type (e.g. Debug, Release)
+
+extern const char* SKYWARD_VERSION_STRING;  //< Skyward version string
-- 
GitLab