什么是单一代码仓库,为什么在C++中需要它?
单一代码仓库(monorepo)是一种代码管理方法,项目的所有组件、库、工具甚至文档都存储在一个仓库中。对于C++项目来说,这尤其重要,因为该语言传统上需要清晰的文件和依赖关系结构。
单一代码仓库对C++的优势:
- 统一的依赖版本 — 所有模块使用相同版本的库,从而消除ABI冲突。
- 简化的构建 — 一个CMakeLists.txt或构建系统管理整个项目。
- 原子提交 — 多个模块的更改可以合并到一个提交中,从而简化代码审查。
- 轻松重构 — 在一个地方更改API会立即在所有依赖模块中可见。
然而,单一代码仓库并不适合所有人:如果团队完全独立并使用不同版本的编译器,最好考虑多仓库。对于初学者来说,单一代码仓库是避免路径和依赖配置麻烦的绝佳方式。
主要部分:为C++项目创建单一代码仓库
1. 目录结构
正确的结构是任何单一代码仓库的基础。推荐的C++模板:
my_monorepo/├── CMakeLists.txt # 根CMake文件├── cmake/ # 辅助CMake模块│ └── helpers.cmake├── libs/ # 库│ ├── core/ # 项目核心│ │ ├── CMakeLists.txt│ │ ├── include/core/│ │ └── src/│ └── utils/ # 工具│ ├── CMakeLists.txt│ ├── include/utils/│ └── src/├── apps/ # 可执行应用程序│ ├── main_app/│ │ ├── CMakeLists.txt│ │ └── main.cpp│ └── test_app/│ ├── CMakeLists.txt│ └── main.cpp├── tests/ # 测试(如果未内置于模块中)│ └── test_core.cpp├── scripts/ # 构建和CI脚本│ └── build.sh├── .gitignore└── README.md关键规则:每个模块(库或应用程序)都应该是自包含的。它包含自己的CMakeLists.txt、include/中的头文件和src/中的源文件。
2. 配置根CMakeLists.txt
根CMakeLists.txt管理整个构建。它应定义通用的编译器设置、C++标准并包含子模块:
cmake_minimum_required(VERSION 3.20)project(MyMonorepo VERSION 1.0.0 LANGUAGES CXX)
# 为整个项目设置统一的C++17标准set(CMAKE_CXX_STANDARD 17)set(CMAKE_CXX_STANDARD_REQUIRED ON)set(CMAKE_CXX_EXTENSIONS OFF)
# 构建测试的选项option(BUILD_TESTS "Build tests" OFF)
# 包含辅助模块include(cmake/helpers.cmake)
# 添加包含库的子目录add_subdirectory(libs/core)add_subdirectory(libs/utils)
# 添加应用程序add_subdirectory(apps/main_app)add_subdirectory(apps/test_app)
# 如果启用了测试,则包含它们if(BUILD_TESTS) enable_testing() add_subdirectory(tests)endif()3. 库示例:libs/core
考虑core库,它包含一个用于数字运算的类。文件结构:
libs/core/├── CMakeLists.txt├── include/core/│ └── calculator.h└── src/ └── calculator.cppinclude/core/calculator.h的内容:
#ifndef CORE_CALCULATOR_H#define CORE_CALCULATOR_H
namespace core {
class Calculator {public: Calculator() = default; int add(int a, int b); int multiply(int a, int b);};
} // namespace core
#endif // CORE_CALCULATOR_H