Introdução: Por que usar um monorepositório em C++?
O desenvolvimento de grandes projetos C++ frequentemente enfrenta o problema de organização do código. As equipes escolhem entre monorepositório (um único repositório para todo o código) e multirrepositório (repositórios separados para cada biblioteca). No contexto de C++, o monorepositório oferece uma série de vantagens: simplificação de refatoração, versão única de dependências e sistema de build centralizado.
Este artigo guiará você pelos principais aspectos da organização de um monorepositório para C++: desde a estrutura de pastas até a configuração do CMake e gerenciamento de dependências. Você aprenderá como tornar o projeto escalável e conveniente para a equipe.
1. Estrutura do monorepositório para C++
Uma estrutura adequada é a base de um monorepositório de sucesso. Recomenda-se usar uma hierarquia que separe bibliotecas, aplicações e dependências externas.
Exemplo de estrutura básica
my_monorepo/├── CMakeLists.txt # Arquivo CMake raiz├── cmake/ # Módulos CMake auxiliares├── libs/ # Bibliotecas do projeto│ ├── core/ # Núcleo (lógica, utilitários)│ │ ├── include/│ │ │ └── core/│ │ ├── src/│ │ └── CMakeLists.txt│ ├── network/ # Módulos de rede│ │ ├── include/│ │ ├── src/│ │ └── CMakeLists.txt│ └── utils/ # Utilitários auxiliares│ ├── include/│ ├── src/│ └── CMakeLists.txt├── apps/ # Aplicações executáveis│ ├── server/│ │ ├── src/│ │ └── CMakeLists.txt│ └── client/│ ├── src/│ └── CMakeLists.txt├── tests/ # Testes de integração├── third_party/ # Dependências externas (git submodules)│ ├── fmt/│ └── spdlog/└── scripts/ # Scripts para CI/CD e desenvolvimentoPrincípios-chave
- libs/: Cada biblioteca é um módulo autossuficiente com seu próprio CMakeLists.txt.
- apps/: As aplicações usam as bibliotecas através de
target_link_libraries. - third_party/: Dependências externas são adicionadas via git submodules ou FetchContent.
- tests/: Diretório separado para testes que verificam a integração dos componentes.
2. Sistema de build: CMake para monorepositório
CMake é a ferramenta padrão para projetos C++. Em um monorepositório, ele permite gerenciar dependências entre bibliotecas e aplicações.
CMakeLists.txt raiz
Crie o arquivo raiz que inclui todos os subprojetos:
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)
# Inclui dependências externasadd_subdirectory(third_party/fmt)add_subdirectory(third_party/spdlog)
# Inclui bibliotecasadd_subdirectory(libs/core)add_subdirectory(libs/network)add_subdirectory(libs/utils)
# Inclui aplicaçõesadd_subdirectory(apps/server)add_subdirectory(apps/client)
# Inclui testesenable_testing()add_subdirectory(tests)Exemplo de CMakeLists.txt para uma biblioteca
# 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 e teste
Para compilar todo o projeto, use:
mkdir build && cd buildcmake .. -DCMAKE_BUILD_TYPE=Releasecmake --build . --parallelctest --output-on-failure3. Gerenciamento de dependências no monorepositório
Um dos principais problemas do monorepositório é o controle de versão das dependências. Em C++, existem algu