Einleitung: Warum ein Monorepo in C++?
Die Entwicklung großer C++-Projekte steht oft vor dem Problem der Code-Organisation. Teams wählen zwischen einem Monorepo (ein Repository für den gesamten Code) und einem Multirepo (separate Repositories für jede Bibliothek). Im Kontext von C++ bietet ein Monorepo eine Reihe von Vorteilen: vereinfachtes Refactoring, eine einheitliche Version der Abhängigkeiten und ein zentralisiertes Build-System.
Dieser Artikel führt Sie durch die wichtigsten Aspekte der Organisation eines Monorepos für C++: von der Ordnerstruktur bis zur Konfiguration von CMake und der Verwaltung von Abhängigkeiten. Sie erfahren, wie Sie Ihr Projekt skalierbar und teamfreundlich gestalten.
1. Struktur eines Monorepos für C++
Die richtige Struktur ist die Grundlage eines erfolgreichen Monorepos. Es wird empfohlen, eine Hierarchie zu verwenden, die Bibliotheken, Anwendungen und externe Abhängigkeiten trennt.
Beispiel einer Basisstruktur
my_monorepo/├── CMakeLists.txt # Root CMake-Datei├── cmake/ # Hilfs-CMake-Module├── libs/ # Projektbibliotheken│ ├── core/ # Kern (Logik, Hilfsprogramme)│ │ ├── include/│ │ │ └── core/│ │ ├── src/│ │ └── CMakeLists.txt│ ├── network/ # Netzwerkmodule│ │ ├── include/│ │ ├── src/│ │ └── CMakeLists.txt│ └── utils/ # Hilfsprogramme│ ├── include/│ ├── src/│ └── CMakeLists.txt├── apps/ # Ausführbare Anwendungen│ ├── server/│ │ ├── src/│ │ └── CMakeLists.txt│ └── client/│ ├── src/│ └── CMakeLists.txt├── tests/ # Integrationstests├── third_party/ # Externe Abhängigkeiten (git submodules)│ ├── fmt/│ └── spdlog/└── scripts/ # Skripte für CI/CD und EntwicklungWichtige Prinzipien
- libs/: Jede Bibliothek ist ein eigenständiges Modul mit eigener CMakeLists.txt.
- apps/: Anwendungen nutzen Bibliotheken über
target_link_libraries. - third_party/: Externe Abhängigkeiten werden über git submodules oder FetchContent hinzugefügt.
- tests/: Ein separates Verzeichnis für Tests, die die Integration der Komponenten überprüfen.
2. Build-System: CMake für ein Monorepo
CMake ist das Standardwerkzeug für C++-Projekte. In einem Monorepo ermöglicht es die Verwaltung von Abhängigkeiten zwischen Bibliotheken und Anwendungen.
Root CMakeLists.txt
Erstellen Sie eine Root-Datei, die alle Unterprojekte einbindet:
cmake_minimum_required(VERSION 3.20)project(MyMonorepo VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Externe Abhängigkeiten einbindenadd_subdirectory(third_party/fmt)add_subdirectory(third_party/spdlog)
# Bibliotheken einbindenadd_subdirectory(libs/core)add_subdirectory(libs/network)add_subdirectory(libs/utils)
# Anwendungen einbindenadd_subdirectory(apps/server)add_subdirectory(apps/client)
# Tests einbindenenable_testing()add_subdirectory(tests)Beispiel CMakeLists.txt für eine Bibliothek
# libs/core/CMakeLists.txtadd_library(core src/core_module.cpp src/utilities.cpp)
target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(core PUBLIC fmt::fmt spdlog::spdlog)Build und Test
Verwenden Sie Folgendes, um das gesamte Projekt zu bauen:
mkdir build && cd buildcmake .. -DCMAKE_BUILD_TYPE=Releasecmake --build . --parallelctest --output-on-failure3. Abhängigkeitsverwaltung im Monorepo
Eines der Hauptprobleme eines Monorepos ist die Versionskontrolle der Abhängigkeiten. In C++ gibt es mehrere