Introduction : Pourquoi un monorepôt en C++ ?
\n\nDans le monde du développement C++, la question se pose tôt ou tard : comment organiser le code lorsque les projets deviennent nombreux ? Bibliothèques, utilitaires, exécutables — tout cela doit être lié, versionné et compilé. L'approche traditionnelle avec de nombreux dépôts séparés (multirepôt) conduit souvent à des problèmes : il est difficile de synchroniser les modifications, l'intégration est complexe à tester, et les dépendances entre projets deviennent un enfer.
\n\nUne alternative — le monorepôt. C'est un dépôt unique qui contient tous les composants de votre projet : bibliothèques, applications, tests, documentation. Cette approche est activement utilisée chez Google, Facebook, Microsoft et de nombreuses autres entreprises. Pour C++, le monorepôt offre plusieurs avantages :
\n\n- \n
- Version unique des dépendances — vous savez toujours quelle version de la bibliothèque est utilisée dans tous les projets. \n
- Commits atomiques — la modification de l'API d'une bibliothèque et la mise à jour de tous ses consommateurs se font en un seul commit. \n
- CI/CD simplifié — un seul pipeline pour tous les composants. \n
- Transparence — il est facile de voir comment l'ensemble du projet est structuré. \n
Dans cet article, nous allons détailler l'organisation pratique d'un monorepôt pour C++ avec CMake, montrer la structure des dossiers et des exemples de code.
\n\n1. Structure des dossiers : la base de l'ordre
\n\nLa première étape vers un monorepôt réussi est une structure de répertoires bien pensée. Voici un modèle recommandé pour un projet C++ :
\n\nmy_project/\n├── CMakeLists.txt # Fichier CMake racine\n├── README.md\n├── .gitignore\n├── .clang-format\n├── cmake/ # Modules CMake auxiliaires\n│ └── FindMyLib.cmake\n├── libs/ # Bibliothèques\n│ ├── core/ # Bibliothèque core\n│ │ ├── CMakeLists.txt\n│ │ ├── include/\n│ │ │ └── core/\n│ │ │ ├── math.h\n│ │ │ └── string_utils.h\n│ │ └── src/\n│ │ ├── math.cpp\n│ │ └── string_utils.cpp\n│ └── network/ # Bibliothèque network\n│ ├── CMakeLists.txt\n│ ├── include/\n│ │ └── network/\n│ │ └── http_client.h\n│ └── src/\n│ └── http_client.cpp\n├── apps/ # Applications exécutables\n│ ├── server/\n│ │ ├── CMakeLists.txt\n│ │ └── src/\n│ │ └── main.cpp\n│ └── cli_tool/\n│ ├── CMakeLists.txt\n│ └── src/\n│ └── main.cpp\n├── tests/ # Tests\n│ ├── CMakeLists.txt\n│ ├── test_core/\n│ │ ├── CMakeLists.txt\n│ │ └── test_math.cpp\n│ └── test_network/\n│ ├── CMakeLists.txt\n│ └── test_http_client.cpp\n└── third_party/ # Dépendances externes (git submodules ou FetchContent)\n └── googletest/\n\n\nPrincipes clés :
\n- \n
- libs/ — toutes les bibliothèques. Chaque bibliothèque est un dossier séparé avec son propre CMakeLists.txt. \n
- apps/ — tous les exécutables. Ils dépendent des bibliothèques de libs/. \n
- tests/ — les tests, organisés par bibliothèque. \n
- third_party/ — les dépendances externes. Utilisez
git submodulesouFetchContentpour les intégrer. \n
2. CMake : configuration de la compilation du monorepôt
\n\nCMake est l'outil idéal pour un monorepôt. Voyons comment configurer le CMakeLists.txt racine et les fichiers pour les bibliothèques.
CMakeLists.txt racine
\n\ncmake_minimum_required(VERSION 3.20)\nproject(MyProject VERSION 1.0.0 LANGUAGES CXX)\n\nset(CMAKE_CXX_STANDARD 20)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\nset(CMAKE_CXX_EXTENSIONS OFF)\n\n# Options pour activer/désactiver des composants\noption(BUILD_TESTS "Build tests" ON)\noption(BUILD_APPS "Build applications" ON)\n\n# Intégration des dépendances externes\ninclude(FetchConte