Monorepo with C++: Code Organization and Best Practices

онлайн тренажер по питону
Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Monorepo with C++: Code Organization and Best Practices



Developing large C++ projects often faces the problem of code fragmentation: libraries are scattered across different repositories, versions are not synchronized, and integration becomes a headache. The solution is a monorepo. This is an approach where all code, including libraries, utilities, and tests, is stored in a single repository. In this article, we will analyze how to properly organize a monorepo for C++ projects using modern tools (CMake, Conan, Git) and avoiding typical mistakes.



1. Directory Structure: The Foundation of Order



The first step is to create a unified, clear folder structure. Here is a recommended scheme for a C++ monorepo:



my-monorepo/├── cmake/                  # Common CMake modules├── libs/                   # Libraries│   ├── core/               # Core (logging, allocators)│   ├── math/               # Math library│   └── network/            # Network library├── apps/                   # Executable applications│   ├── server/             # Server application│   └── client/             # Client application├── tests/                  # Integration tests├── scripts/                # Build and deployment scripts├── third_party/            # External dependencies (submodules)├── CMakeLists.txt          # Root CMake file├── conanfile.txt           # Dependency manager (optional)└── .github/                # CI/CD (GitHub Actions)


Why does this work?

  • libs/ — all libraries in one place, easy to reuse.
  • apps/ — applications that depend on libs.
  • third_party/ — external dependencies (via git submodules or CMake FetchContent).
  • cmake/ — custom functions (e.g., add_library_with_tests).


2. CMake: Configuring the Root Project



CMake is the standard for C++ builds in monorepos. Configure the root CMakeLists.txt so that it includes all subprojects:



cmake_minimum_required(VERSION 3.20)project(MyMonorepo LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Common optionsoption(BUILD_TESTS "Build tests" ON)

# Include librariesadd_subdirectory(libs/core)add_subdirectory(libs/math)add_subdirectory(libs/network)

# Include applicationsadd_subdirectory(apps/server)add_subdirectory(apps/client)

# Include testsif(BUILD_TESTS) enable_testing() add_subdirectory(tests)endif()


Important points:

  • Use target_link_libraries to explicitly specify dependencies between libraries.
  • For external dependencies (e.g., Boost, fmt), use FetchContent or Conan.
  • Avoid global include_directories — use target_include_directories with PUBLIC or PRIVATE.


3. Managing Dependencies Inside the Monorepo



One of the main problems of a monorepo is circular dependencies. The solution: a strict hierarchy. For example:



  • core (depends on nothing except the standard library)
  • math (depends on core)
  • network (depends on core and math)
  • server (depends on core, math, network)


Example CMakeLists.txt for the math library:



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 # Explicitly specify de

Blogs

Book Recommendations