- Reorganize docs/ (flatten to architecture/ and implementation/) - Remove MonitoringModule from MVP (no app detection) - Add LanguageLearningModule to MVP - Create CLAUDE.md (concise project overview) - Add language learning to README and architecture - Update all examples to use SchedulerModule instead of MonitoringModule 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
678 lines
18 KiB
Markdown
678 lines
18 KiB
Markdown
# Module Versioning System
|
|
|
|
## Vue d'Ensemble
|
|
|
|
Le système de versioning des modules utilise un format **MAJOR.MINOR.PATCH.BUILD** automatiquement généré par CMake lors de la compilation. Ce système permet de :
|
|
|
|
- **Tracer les versions** : Identifier précisément quelle version du code a créé une save
|
|
- **Détecter incompatibilités** : Alerter si une save utilise une version différente
|
|
- **Debugging** : Reproduire bugs avec la version exacte du module
|
|
- **Développement** : Versions incrémentales automatiques sans maintenance manuelle
|
|
|
|
## Format de Version
|
|
|
|
### Structure : MAJOR.MINOR.PATCH.BUILD
|
|
|
|
```
|
|
0.1.15.3847
|
|
│ │ │ │
|
|
│ │ │ └─── BUILD : Auto-increment à chaque build (hash sources)
|
|
│ │ └────── PATCH : Auto-increment à chaque commit
|
|
│ └──────── MINOR : Manuel (fonctionnalités nouvelles)
|
|
└────────── MAJOR : Manuel (breaking changes)
|
|
```
|
|
|
|
### Composantes
|
|
|
|
#### MAJOR (Manuel)
|
|
- **Incrémenté** : Breaking changes, incompatibilités majeures
|
|
- **Exemples** : Refonte complète architecture, changement format save incompatible
|
|
- **Gestion** : Modifié manuellement dans fichier `VERSION`
|
|
- **Valeur initiale** : `0` (pré-release), `1` (première version stable)
|
|
|
|
#### MINOR (Manuel)
|
|
- **Incrémenté** : Nouvelles fonctionnalités, ajouts non-breaking
|
|
- **Exemples** : Nouveau type de tank, nouveau système économique
|
|
- **Gestion** : Modifié manuellement dans fichier `VERSION`
|
|
- **Valeur initiale** : `1`
|
|
|
|
#### PATCH (Automatique)
|
|
- **Incrémenté** : À chaque commit Git
|
|
- **Calcul** : Nombre de commits depuis le début du projet
|
|
- **Exemples** : Bugfixes, optimisations, refactoring mineur
|
|
- **Gestion** : Calculé automatiquement par CMake via `git rev-list --count HEAD`
|
|
|
|
#### BUILD (Automatique)
|
|
- **Incrémenté** : À chaque rebuild (si sources modifiées)
|
|
- **Calcul** : Hash MD5 des fichiers sources (`.cpp`, `.h`)
|
|
- **But** : Distinguer builds de dev avec code non-commité
|
|
- **Gestion** : Calculé automatiquement par CMake
|
|
|
|
### Exemples de Versions
|
|
|
|
```
|
|
0.1.0.0 → Première version dev (MAJOR.MINOR manuel, PATCH/BUILD = 0)
|
|
0.1.5.1234 → Après 5 commits, build 1234
|
|
0.1.5.1235 → Même commit, sources modifiées → nouveau build
|
|
0.1.6.1235 → Nouveau commit, sources identiques → même build (théorique)
|
|
0.2.10.3847 → MINOR bump (nouvelle feature) + 10 commits
|
|
1.0.0.0 → Release stable, reset PATCH/BUILD
|
|
```
|
|
|
|
## Implémentation CMake
|
|
|
|
### Fichier VERSION
|
|
|
|
Chaque module contient un fichier `VERSION` à la racine :
|
|
|
|
```
|
|
modules/tank/VERSION
|
|
```
|
|
|
|
Contenu du fichier :
|
|
```
|
|
0.1
|
|
```
|
|
|
|
Ce fichier contient uniquement `MAJOR.MINOR`. Les composantes `PATCH.BUILD` sont calculées automatiquement.
|
|
|
|
### CMakeLists.txt du Module
|
|
|
|
```cmake
|
|
cmake_minimum_required(VERSION 3.20)
|
|
project(TankModule)
|
|
|
|
# ============================================================================
|
|
# MODULE VERSIONING
|
|
# ============================================================================
|
|
|
|
# 1. Lire MAJOR.MINOR depuis fichier VERSION
|
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
|
|
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BASE_VERSION)
|
|
string(STRIP "${BASE_VERSION}" BASE_VERSION)
|
|
else()
|
|
set(BASE_VERSION "0.1")
|
|
message(WARNING "No VERSION file found, using default: ${BASE_VERSION}")
|
|
endif()
|
|
|
|
# 2. Calculer PATCH : nombre de commits Git
|
|
execute_process(
|
|
COMMAND git rev-list --count HEAD
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
OUTPUT_VARIABLE PATCH_COUNT
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
ERROR_QUIET
|
|
RESULT_VARIABLE GIT_RESULT
|
|
)
|
|
|
|
if(NOT GIT_RESULT EQUAL 0)
|
|
set(PATCH_COUNT "0")
|
|
message(WARNING "Git not available, PATCH set to 0")
|
|
endif()
|
|
|
|
# 3. Calculer BUILD : hash des fichiers sources
|
|
file(GLOB_RECURSE MODULE_SOURCES
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/*.h"
|
|
)
|
|
|
|
# Concaténer contenu de tous les fichiers
|
|
set(SOURCES_CONTENT "")
|
|
foreach(SOURCE_FILE ${MODULE_SOURCES})
|
|
file(READ ${SOURCE_FILE} FILE_CONTENT)
|
|
string(APPEND SOURCES_CONTENT ${FILE_CONTENT})
|
|
endforeach()
|
|
|
|
# Hash MD5 du contenu total
|
|
string(MD5 SOURCES_HASH "${SOURCES_CONTENT}")
|
|
|
|
# Convertir hash hex en nombre décimal (4 premiers caractères)
|
|
string(SUBSTRING ${SOURCES_HASH} 0 4 BUILD_HEX)
|
|
# Calculer valeur numérique (modulo 10000 pour limiter à 4 chiffres)
|
|
math(EXPR BUILD_NUM "0x${BUILD_HEX} % 10000")
|
|
|
|
# 4. Assembler version complète
|
|
set(MODULE_VERSION "${BASE_VERSION}.${PATCH_COUNT}.${BUILD_NUM}")
|
|
|
|
message(STATUS "Module version: ${MODULE_VERSION}")
|
|
message(STATUS " BASE: ${BASE_VERSION} (from VERSION file)")
|
|
message(STATUS " PATCH: ${PATCH_COUNT} (git commits)")
|
|
message(STATUS " BUILD: ${BUILD_NUM} (sources hash)")
|
|
|
|
# 5. Définir macro C++ pour accès au runtime
|
|
add_definitions(-DMODULE_VERSION="${MODULE_VERSION}")
|
|
|
|
# ============================================================================
|
|
# MODULE BUILD
|
|
# ============================================================================
|
|
|
|
# Inclure sources
|
|
file(GLOB_RECURSE TANK_SOURCES src/*.cpp)
|
|
|
|
# Créer bibliothèque partagée (.so)
|
|
add_library(tank-module SHARED ${TANK_SOURCES})
|
|
|
|
# Configuration compilation
|
|
target_include_directories(tank-module PRIVATE include)
|
|
target_compile_features(tank-module PRIVATE cxx_std_20)
|
|
|
|
# Sortie
|
|
set_target_properties(tank-module PROPERTIES
|
|
OUTPUT_NAME "tank"
|
|
PREFIX ""
|
|
SUFFIX ".so"
|
|
)
|
|
|
|
message(STATUS "Building TankModule v${MODULE_VERSION}")
|
|
```
|
|
|
|
### Utilisation dans le Code C++
|
|
|
|
```cpp
|
|
// src/TankModule.h
|
|
#ifndef MODULE_VERSION
|
|
#define MODULE_VERSION "unknown"
|
|
#endif
|
|
|
|
class TankModule : public IModule, public IModuleSave {
|
|
public:
|
|
std::string getVersion() const override {
|
|
return MODULE_VERSION; // Défini par CMake
|
|
}
|
|
|
|
nlohmann::json serialize() override {
|
|
json data;
|
|
data["module_name"] = "tank";
|
|
data["module_version"] = getVersion(); // "0.1.15.3847"
|
|
// ... reste de la sérialisation
|
|
return data;
|
|
}
|
|
};
|
|
```
|
|
|
|
### Affichage au Runtime
|
|
|
|
```cpp
|
|
void TankModule::initialize() {
|
|
LOG_INFO("TankModule v{} initializing...", getVersion());
|
|
}
|
|
```
|
|
|
|
Sortie console :
|
|
```
|
|
[INFO] TankModule v0.1.15.3847 initializing...
|
|
```
|
|
|
|
## Workflow de Développement
|
|
|
|
### 1. Création Nouveau Module
|
|
|
|
```bash
|
|
# Créer structure module
|
|
mkdir -p modules/new_module/src
|
|
cd modules/new_module
|
|
|
|
# Créer fichier VERSION
|
|
echo "0.1" > VERSION
|
|
|
|
# Créer CMakeLists.txt avec système versioning
|
|
# (copier template ci-dessus)
|
|
```
|
|
|
|
**Première compilation** :
|
|
```bash
|
|
cmake . && make
|
|
```
|
|
|
|
Sortie :
|
|
```
|
|
-- Module version: 0.1.0.0
|
|
-- BASE: 0.1 (from VERSION file)
|
|
-- PATCH: 0 (git commits)
|
|
-- BUILD: 0 (sources hash)
|
|
-- Building NewModule v0.1.0.0
|
|
```
|
|
|
|
### 2. Développement Itératif
|
|
|
|
**Scénario 1 : Modifier code sans commit**
|
|
|
|
```bash
|
|
# Éditer src/NewModule.cpp
|
|
nano src/NewModule.cpp
|
|
|
|
# Rebuild
|
|
make
|
|
```
|
|
|
|
Sortie :
|
|
```
|
|
-- Module version: 0.1.0.4582
|
|
-- PATCH: 0 (aucun commit)
|
|
-- BUILD: 4582 (hash sources a changé)
|
|
```
|
|
|
|
**Scénario 2 : Commit modifications**
|
|
|
|
```bash
|
|
git add .
|
|
git commit -m "Add feature X"
|
|
|
|
# Rebuild
|
|
make
|
|
```
|
|
|
|
Sortie :
|
|
```
|
|
-- Module version: 0.1.1.4582
|
|
-- PATCH: 1 (nouveau commit)
|
|
-- BUILD: 4582 (sources identiques au commit)
|
|
```
|
|
|
|
**Scénario 3 : Rebuild sans modification**
|
|
|
|
```bash
|
|
# Rebuild immédiat
|
|
make
|
|
```
|
|
|
|
Sortie :
|
|
```
|
|
-- Module version: 0.1.1.4582
|
|
(version identique, aucun changement)
|
|
```
|
|
|
|
### 3. Release Mineure (Nouvelle Feature)
|
|
|
|
```bash
|
|
# Bump MINOR version
|
|
echo "0.2" > VERSION
|
|
|
|
# Commit
|
|
git add VERSION
|
|
git commit -m "Bump version to 0.2 (new feature: advanced tactics)"
|
|
|
|
# Rebuild
|
|
cmake . && make
|
|
```
|
|
|
|
Sortie :
|
|
```
|
|
-- Module version: 0.2.2.5123
|
|
-- BASE: 0.2 (nouvelle version)
|
|
-- PATCH: 2 (commits depuis début projet)
|
|
-- BUILD: 5123 (hash actuel)
|
|
```
|
|
|
|
### 4. Release Majeure (Breaking Change)
|
|
|
|
```bash
|
|
# Bump MAJOR version
|
|
echo "1.0" > VERSION
|
|
|
|
git add VERSION
|
|
git commit -m "Release 1.0.0 - Stable API"
|
|
|
|
cmake . && make
|
|
```
|
|
|
|
Sortie :
|
|
```
|
|
-- Module version: 1.0.3.5123
|
|
-- BASE: 1.0 (version stable)
|
|
-- PATCH: 3 (total commits)
|
|
-- BUILD: 5123
|
|
```
|
|
|
|
## Comparaison de Versions
|
|
|
|
### Dans le Système de Save
|
|
|
|
Lors du chargement d'une save, comparaison des versions :
|
|
|
|
```cpp
|
|
bool SaveSystem::loadModule(const std::string& moduleName) {
|
|
auto module = moduleSystem->getModule(moduleName);
|
|
|
|
json moduleData = readJsonFile(modulePath);
|
|
std::string savedVersion = moduleData["module_version"];
|
|
std::string currentVersion = module->getVersion();
|
|
|
|
if (savedVersion != currentVersion) {
|
|
LOG_WARN("Module {} version mismatch:", moduleName);
|
|
LOG_WARN(" Save version: {}", savedVersion);
|
|
LOG_WARN(" Current version: {}", currentVersion);
|
|
|
|
// Analyser différences
|
|
VersionInfo saved = parseVersion(savedVersion);
|
|
VersionInfo current = parseVersion(currentVersion);
|
|
|
|
if (saved.major != current.major) {
|
|
LOG_ERROR(" MAJOR version mismatch - likely incompatible!");
|
|
return false; // Incompatibilité critique
|
|
}
|
|
else if (saved.minor != current.minor) {
|
|
LOG_WARN(" MINOR version mismatch - some features may differ");
|
|
// Continuer avec warning
|
|
}
|
|
else if (saved.patch != current.patch) {
|
|
LOG_INFO(" PATCH version mismatch - minor changes only");
|
|
// Sûr, juste bugfixes
|
|
}
|
|
else {
|
|
LOG_DEBUG(" BUILD version mismatch - dev builds differ");
|
|
// Totalement sûr
|
|
}
|
|
}
|
|
|
|
return module->deserialize(moduleData);
|
|
}
|
|
```
|
|
|
|
### Structure VersionInfo
|
|
|
|
```cpp
|
|
struct VersionInfo {
|
|
int major;
|
|
int minor;
|
|
int patch;
|
|
int build;
|
|
|
|
static VersionInfo parse(const std::string& versionStr) {
|
|
VersionInfo info;
|
|
std::sscanf(versionStr.c_str(), "%d.%d.%d.%d",
|
|
&info.major, &info.minor, &info.patch, &info.build);
|
|
return info;
|
|
}
|
|
|
|
bool isCompatibleWith(const VersionInfo& other) const {
|
|
// Compatible si MAJOR identique
|
|
return major == other.major;
|
|
}
|
|
|
|
bool hasBreakingChanges(const VersionInfo& other) const {
|
|
return major != other.major;
|
|
}
|
|
};
|
|
```
|
|
|
|
## Gestion Multi-Modules
|
|
|
|
### Script CMake Global
|
|
|
|
Pour centraliser la logique de versioning, créer un fichier CMake réutilisable :
|
|
|
|
```cmake
|
|
# cmake/ModuleVersioning.cmake
|
|
|
|
function(setup_module_versioning)
|
|
# Lire VERSION
|
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
|
|
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BASE_VERSION)
|
|
string(STRIP "${BASE_VERSION}" BASE_VERSION)
|
|
else()
|
|
set(BASE_VERSION "0.1")
|
|
endif()
|
|
|
|
# Calculer PATCH
|
|
execute_process(
|
|
COMMAND git rev-list --count HEAD
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
OUTPUT_VARIABLE PATCH_COUNT
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
ERROR_QUIET
|
|
RESULT_VARIABLE GIT_RESULT
|
|
)
|
|
if(NOT GIT_RESULT EQUAL 0)
|
|
set(PATCH_COUNT "0")
|
|
endif()
|
|
|
|
# Calculer BUILD
|
|
file(GLOB_RECURSE MODULE_SOURCES
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/*.h"
|
|
)
|
|
set(SOURCES_CONTENT "")
|
|
foreach(SOURCE_FILE ${MODULE_SOURCES})
|
|
file(READ ${SOURCE_FILE} FILE_CONTENT)
|
|
string(APPEND SOURCES_CONTENT ${FILE_CONTENT})
|
|
endforeach()
|
|
string(MD5 SOURCES_HASH "${SOURCES_CONTENT}")
|
|
string(SUBSTRING ${SOURCES_HASH} 0 4 BUILD_HEX)
|
|
math(EXPR BUILD_NUM "0x${BUILD_HEX} % 10000")
|
|
|
|
# Assembler version
|
|
set(MODULE_VERSION "${BASE_VERSION}.${PATCH_COUNT}.${BUILD_NUM}" PARENT_SCOPE)
|
|
|
|
# Log
|
|
message(STATUS "Module version: ${BASE_VERSION}.${PATCH_COUNT}.${BUILD_NUM}")
|
|
endfunction()
|
|
```
|
|
|
|
### Utilisation dans Module
|
|
|
|
```cmake
|
|
# modules/tank/CMakeLists.txt
|
|
cmake_minimum_required(VERSION 3.20)
|
|
project(TankModule)
|
|
|
|
# Importer fonction versioning
|
|
include(${CMAKE_SOURCE_DIR}/cmake/ModuleVersioning.cmake)
|
|
|
|
# Setup version automatique
|
|
setup_module_versioning()
|
|
|
|
# Définir macro
|
|
add_definitions(-DMODULE_VERSION="${MODULE_VERSION}")
|
|
|
|
# ... reste du CMakeLists
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Quand Bumper MAJOR ?
|
|
|
|
**Situations justifiant MAJOR bump** :
|
|
- Changement format save incompatible
|
|
- Refonte API du module (signatures fonctions changent)
|
|
- Suppression de fonctionnalités existantes
|
|
- Changement architecture fondamentale
|
|
|
|
**Exemple** :
|
|
```bash
|
|
# Avant : TankModule v0.8.x utilise grille 10x10
|
|
# Après : TankModule v1.0.0 utilise grille 16x16 (incompatible)
|
|
echo "1.0" > VERSION
|
|
```
|
|
|
|
### 2. Quand Bumper MINOR ?
|
|
|
|
**Situations justifiant MINOR bump** :
|
|
- Ajout nouveau type de tank/composant
|
|
- Nouvelle fonctionnalité (mode formation, tactiques AI)
|
|
- Amélioration significative sans breaking change
|
|
|
|
**Exemple** :
|
|
```bash
|
|
# Ajout système de camouflage → 0.1 → 0.2
|
|
echo "0.2" > VERSION
|
|
```
|
|
|
|
### 3. PATCH et BUILD sont Automatiques
|
|
|
|
**Ne jamais modifier manuellement** :
|
|
- PATCH suit automatiquement les commits
|
|
- BUILD suit automatiquement les modifications code
|
|
|
|
### 4. Versioning pour Tests
|
|
|
|
En environnement de test, fixer une version stable :
|
|
|
|
```cmake
|
|
if(DEFINED ENV{CI_BUILD})
|
|
# Build CI : version fixe pour reproductibilité
|
|
set(MODULE_VERSION "0.0.0.0")
|
|
else()
|
|
# Build normal : versioning automatique
|
|
setup_module_versioning()
|
|
endif()
|
|
```
|
|
|
|
### 5. Affichage Version au Démarrage
|
|
|
|
```cpp
|
|
void logModuleVersions() {
|
|
LOG_INFO("=== Module Versions ===");
|
|
for (auto& module : moduleSystem->getAllModules()) {
|
|
LOG_INFO(" {}: v{}", module->getName(), module->getVersion());
|
|
}
|
|
LOG_INFO("=======================");
|
|
}
|
|
```
|
|
|
|
Sortie :
|
|
```
|
|
[INFO] === Module Versions ===
|
|
[INFO] tank: v0.1.15.3847
|
|
[INFO] economy: v0.2.8.1203
|
|
[INFO] factory: v0.1.20.4512
|
|
[INFO] transport: v0.1.5.982
|
|
[INFO] =======================
|
|
```
|
|
|
|
## Debugging avec Versions
|
|
|
|
### Reproduire un Bug
|
|
|
|
Si un bug est reporté avec une save :
|
|
|
|
1. **Lire version du module dans la save** :
|
|
```bash
|
|
cat saves/abc123/server_1/tank.json | grep module_version
|
|
# "module_version": "0.1.15.3847"
|
|
```
|
|
|
|
2. **Retrouver commit correspondant** :
|
|
```bash
|
|
# PATCH = 15 commits
|
|
git log --oneline | head -n 15 | tail -n 1
|
|
```
|
|
|
|
3. **Vérifier hash sources** :
|
|
```bash
|
|
# BUILD = 3847 correspond à un certain hash
|
|
# Comparer avec hashes de commits proches
|
|
```
|
|
|
|
4. **Checkout version exacte pour debugging** :
|
|
```bash
|
|
git checkout <commit_hash>
|
|
cmake . && make
|
|
# Version devrait matcher ou être proche
|
|
```
|
|
|
|
### Logs de Version
|
|
|
|
```cpp
|
|
void TankModule::initialize() {
|
|
LOG_INFO("TankModule v{} initializing", getVersion());
|
|
LOG_DEBUG(" Compiled: {} {}", __DATE__, __TIME__);
|
|
LOG_DEBUG(" Compiler: {}", __VERSION__);
|
|
}
|
|
```
|
|
|
|
## Alternatives et Limitations
|
|
|
|
### Alternative 1 : Semantic Versioning Manuel
|
|
|
|
**Avantage** : Contrôle total sur versions
|
|
**Inconvénient** : Maintenance manuelle, oublis fréquents
|
|
|
|
### Alternative 2 : Git Tags Only
|
|
|
|
```cmake
|
|
execute_process(
|
|
COMMAND git describe --tags --always
|
|
OUTPUT_VARIABLE MODULE_VERSION
|
|
)
|
|
```
|
|
|
|
**Avantage** : Simple, suit git
|
|
**Inconvénient** : Nécessite tags, pas de granularité build
|
|
|
|
### Limitation Actuelle : Hash Non-Déterministe
|
|
|
|
Le hash des sources peut varier selon :
|
|
- Ordre de lecture des fichiers (filesystem dépendant)
|
|
- Encodage des fichiers
|
|
- Whitespace differences
|
|
|
|
**Solution future** : Hash déterministe avec tri des fichiers et normalisation.
|
|
|
|
## Migration depuis Système Existant
|
|
|
|
Si des modules existants utilisent un autre système :
|
|
|
|
```cmake
|
|
# Détecter ancien système
|
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/version.txt")
|
|
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/version.txt" OLD_VERSION)
|
|
message(WARNING "Found old version.txt, migrating to VERSION file")
|
|
|
|
# Extraire MAJOR.MINOR
|
|
string(REGEX MATCH "^[0-9]+\\.[0-9]+" BASE_VERSION ${OLD_VERSION})
|
|
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" "${BASE_VERSION}")
|
|
|
|
message(STATUS "Migration complete: ${OLD_VERSION} -> ${BASE_VERSION}.x.x")
|
|
endif()
|
|
```
|
|
|
|
## Références Croisées
|
|
|
|
- `systeme-sauvegarde.md` : Utilisation des versions dans le système de save
|
|
- `architecture-modulaire.md` : Interface IModule, contraintes modules
|
|
- `claude-code-integration.md` : Optimisation builds pour développement AI
|
|
|
|
## Exemples Complets
|
|
|
|
### Module Complet avec Versioning
|
|
|
|
Voir structure complète dans :
|
|
```
|
|
modules/tank/
|
|
├── VERSION # "0.1"
|
|
├── CMakeLists.txt # Setup versioning + build
|
|
├── src/
|
|
│ ├── TankModule.cpp # Utilise MODULE_VERSION
|
|
│ └── Tank.cpp
|
|
└── include/
|
|
└── TankModule.h # Déclare getVersion()
|
|
```
|
|
|
|
### Test Versioning
|
|
|
|
```cpp
|
|
#ifdef TESTING
|
|
#include <cassert>
|
|
|
|
void testVersioning() {
|
|
TankModule module;
|
|
|
|
std::string version = module.getVersion();
|
|
assert(!version.empty());
|
|
assert(version != "unknown");
|
|
|
|
// Parse version
|
|
VersionInfo info = VersionInfo::parse(version);
|
|
assert(info.major >= 0);
|
|
assert(info.minor >= 0);
|
|
assert(info.patch >= 0);
|
|
assert(info.build >= 0);
|
|
|
|
std::cout << "Versioning test passed: " << version << std::endl;
|
|
}
|
|
#endif
|
|
```
|