Monorepositório com C++: organização de código e melhores práticas

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Monorepositório com C++: organização de código e melhores práticas



O desenvolvimento de grandes projetos em C++ frequentemente enfrenta o problema de fragmentação de código: bibliotecas espalhadas por diferentes repositórios, versões não sincronizadas e a integração se torna uma dor de cabeça. A solução é o monorepositório (monorepo). Esta é uma abordagem onde todo o código, incluindo bibliotecas, utilitários e testes, é armazenado em um único repositório. Neste artigo, vamos analisar como organizar corretamente um monorepositório para projetos C++, usando ferramentas modernas (CMake, Conan, Git) e evitando erros típicos.



1. Estrutura de diretórios: a base da organização



O primeiro passo é criar uma estrutura de pastas única e clara. Aqui está um esquema recomendado para um monorepositório C++:



my-monorepo/├── cmake/                  # Módulos CMake comuns├── libs/                   # Bibliotecas│   ├── core/               # Núcleo (logging, alocadores)│   ├── math/               # Biblioteca matemática│   └── network/            # Biblioteca de rede├── apps/                   # Aplicações executáveis│   ├── server/             # Aplicação servidora│   └── client/             # Aplicação cliente├── tests/                  # Testes de integração├── scripts/                # Scripts de build e deploy├── third_party/            # Dependências externas (submodules)├── CMakeLists.txt          # Arquivo CMake raiz├── conanfile.txt           # Gerenciador de dependências (opcional)└── .github/                # CI/CD (GitHub Actions)


Por que isso funciona?

  • libs/ — todas as bibliotecas em um só lugar, fáceis de reutilizar.
  • apps/ — aplicações que dependem de libs.
  • third_party/ — dependências externas (via git submodules ou CMake FetchContent).
  • cmake/ — funções personalizadas (exemplo: add_library_with_tests).


2. CMake: configurando o projeto raiz



CMake é o padrão para build C++ em monorepositórios. Configure o CMakeLists.txt raiz para que ele inclua todos os subprojetos:



cmake_minimum_required(VERSION 3.20)project(MyMonorepo LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Opções comunsoption(BUILD_TESTS "Build tests" ON)

# Inclui as bibliotecasadd_subdirectory(libs/core)add_subdirectory(libs/math)add_subdirectory(libs/network)

# Inclui as aplicaçõesadd_subdirectory(apps/server)add_subdirectory(apps/client)

# Inclui os testesif(BUILD_TESTS) enable_testing() add_subdirectory(tests)endif()


Pontos importantes:

  • Use target_link_libraries para indicar explicitamente as dependências entre bibliotecas.
  • Para dependências externas (exemplo: Boost, fmt), use FetchContent ou Conan.
  • Evite include_directories globais — use target_include_directories com PUBLIC ou PRIVATE.


3. Gerenciamento de dependências dentro do monorepositório



Um dos principais problemas do monorepositório são as dependências cíclicas. Solução: hierarquia rigorosa. Exemplo:



  • core (não depende de nada, exceto da biblioteca padrão)
  • math (depende de core)
  • network (depende de core e math)
  • server (depende de core, math, network)


Exemplo de CMakeLists.txt para a biblioteca math:



add_library(math    src/vector.cpp    src/matrix.cpp    include/math/vector.h    include/math/matrix.h)

target_include_directories(math PUBLIC include PRIVATE src)

target_link_libraries(math PUBLIC core # Indica explicitamente a de

Blogs

Book Recommendations