Monorepository with C++: Organizing Code in Practice

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

Introduction: Why Do You Need a Monorepository in C++?

\n\n

In the world of C++ development, sooner or later the question arises: how to organize code when there are many projects? Libraries, utilities, executables — all of this needs to be linked, versioned, and built. The traditional approach with many separate repositories (multirepository) often leads to problems: it's difficult to synchronize changes, integration testing is hard, and dependencies between projects become a nightmare.

\n\n

The alternative is a monorepository. This is a single repository that stores all components of your project: libraries, applications, tests, documentation. This approach is actively used at Google, Facebook, Microsoft, and many other companies. For C++, a monorepository offers several advantages:

\n\n
    \n
  • Single version of dependencies — you always know which version of a library is used across all projects.
  • \n
  • Atomic commits — changing a library's API and updating all its consumers happens in one commit.
  • \n
  • Simplified CI/CD — one pipeline for all components.
  • \n
  • Transparency — it's easy to see how the entire project is structured.
  • \n
\n\n

In this article, we will break down the practical organization of a monorepository for C++ using CMake, show the folder structure, and provide code examples.

\n\n

1. Folder Structure: The Foundation of Order

\n\n

The first step to a successful monorepository is a well-thought-out directory structure. Here is a recommended template for a C++ project:

\n\n
my_project/\n├── CMakeLists.txt          # Root CMake file\n├── README.md\n├── .gitignore\n├── .clang-format\n├── cmake/                  # Helper CMake modules\n│   └── FindMyLib.cmake\n├── libs/                   # Libraries\n│   ├── core/               # Core library\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/            # Network library\n│       ├── CMakeLists.txt\n│       ├── include/\n│       │   └── network/\n│       │       └── http_client.h\n│       └── src/\n│           └── http_client.cpp\n├── apps/                   # Executable applications\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/            # External dependencies (git submodules or FetchContent)\n    └── googletest/\n
\n\n

Key principles:

\n
    \n
  • libs/ — all libraries. Each library is a separate folder with its own CMakeLists.txt.
  • \n
  • apps/ — all executable files. They depend on libraries from libs/.
  • \n
  • tests/ — tests organized by library.
  • \n
  • third_party/ — external dependencies. Use git submodules or FetchContent to include them.
  • \n
\n\n

2. CMake: Configuring the Monorepository Build

\n\n

CMake is the ideal tool for a monorepository. Let's look at how to set up the root CMakeLists.txt and files for libraries.

\n\n

Root CMakeLists.txt

\n\n
cmake_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 to enable/disable components\noption(BUILD_TESTS "Build tests" ON)\noption(BUILD_APPS "Build applications" ON)\n\n# Include external dependencies\ninclude(FetchConte                

Blogs

Book Recommendations