Introducción: ¿Por qué es necesario un monorepositorio en C++?
\n\nEn el mundo del desarrollo en C++, tarde o temprano surge la pregunta: ¿cómo organizar el código cuando hay muchos proyectos? Bibliotecas, utilidades, archivos ejecutables: todo esto necesita ser vinculado, versionado y compilado. El enfoque tradicional con múltiples repositorios separados (multirrepositorio) a menudo conduce a problemas: es difícil sincronizar cambios, es complicado probar la integración y las dependencias entre proyectos se convierten en un infierno.
\n\nLa alternativa es el monorepositorio. Es un único repositorio que almacena todos los componentes de su proyecto: bibliotecas, aplicaciones, pruebas, documentación. Este enfoque es utilizado activamente en Google, Facebook, Microsoft y muchas otras empresas. Para C++, el monorepositorio ofrece una serie de ventajas:
\n\n- \n
- Versión única de dependencias — siempre sabe qué versión de una biblioteca se utiliza en todos los proyectos. \n
- Commits atómicos — el cambio de la API de una biblioteca y la actualización de todos sus consumidores ocurren en un solo commit. \n
- CI/CD simplificado — un solo pipeline para todos los componentes. \n
- Transparencia — es fácil ver cómo está estructurado todo el proyecto. \n
En este artículo, analizaremos la organización práctica de un monorepositorio para C++ utilizando CMake, mostraremos la estructura de carpetas y ejemplos de código.
\n\n1. Estructura de carpetas: la base del orden
\n\nEl primer paso hacia un monorepositorio exitoso es una estructura de directorios bien pensada. Aquí hay una plantilla recomendada para un proyecto de C++:
\n\nmy_project/\n├── CMakeLists.txt # Archivo CMake raíz\n├── README.md\n├── .gitignore\n├── .clang-format\n├── cmake/ # Módulos CMake auxiliares\n│ └── FindMyLib.cmake\n├── libs/ # Bibliotecas\n│ ├── core/ # Biblioteca core\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/ # Biblioteca network\n│ ├── CMakeLists.txt\n│ ├── include/\n│ │ └── network/\n│ │ └── http_client.h\n│ └── src/\n│ └── http_client.cpp\n├── apps/ # Aplicaciones ejecutables\n│ ├── server/\n│ │ ├── CMakeLists.txt\n│ │ └── src/\n│ │ └── main.cpp\n│ └── cli_tool/\n│ ├── CMakeLists.txt\n│ └── src/\n│ └── main.cpp\n├── tests/ # Pruebas\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/ # Dependencias externas (git submodules o FetchContent)\n └── googletest/\n\n\nPrincipios clave:
\n- \n
- libs/ — todas las bibliotecas. Cada biblioteca es una carpeta separada con su propio CMakeLists.txt. \n
- apps/ — todos los archivos ejecutables. Dependen de las bibliotecas en libs/. \n
- tests/ — pruebas, organizadas por bibliotecas. \n
- third_party/ — dependencias externas. Use
git submodulesoFetchContentpara incluirlas. \n
2. CMake: configuración de la compilación del monorepositorio
\n\nCMake es la herramienta ideal para un monorepositorio. Veamos cómo configurar el CMakeLists.txt raíz y los archivos para las bibliotecas.
CMakeLists.txt raíz
\n\ncmake_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# Opciones para habilitar/deshabilitar componentes\noption(BUILD_TESTS "Build tests" ON)\noption(BUILD_APPS "Build applications" ON)\n\n# Incluir dependencias externas\ninclude(FetchConte