C++ 单体仓库:代码组织与最佳实践

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

使用C++的单一代码库:代码组织与最佳实践



大型C++项目的开发常常面临代码碎片化的问题:库分散在不同的代码库中,版本不同步,集成变成令人头疼的事情。解决方案是单一代码库(monorepo)。这是一种将所有代码(包括库、工具和测试)存储在一个代码库中的方法。在本文中,我们将讨论如何正确组织C++项目的单一代码库,使用现代工具(CMake、Conan、Git)并避免常见错误。



1. 目录结构:秩序的基础



第一步是创建一个统一、清晰的文件夹结构。以下是C++单一代码库的推荐方案:



my-monorepo/├── cmake/                  # 通用CMake模块├── libs/                   # 库│   ├── core/               # 核心(日志、分配器)│   ├── math/               # 数学库│   └── network/            # 网络库├── apps/                   # 可执行应用程序│   ├── server/             # 服务器应用程序│   └── client/             # 客户端应用程序├── tests/                  # 集成测试├── scripts/                # 构建和部署脚本├── third_party/            # 外部依赖(子模块)├── CMakeLists.txt          # 根CMake文件├── conanfile.txt           # 依赖管理器(可选)└── .github/                # CI/CD(GitHub Actions)


为什么这样有效?

  • libs/ — 所有库都在一个地方,易于重用。
  • apps/ — 依赖于libs的应用程序。
  • third_party/ — 外部依赖(通过git submodules或CMake FetchContent)。
  • cmake/ — 自定义函数(例如add_library_with_tests)。


2. CMake:配置根项目



CMake是单一代码库中C++构建的标准。配置根CMakeLists.txt以包含所有子项目:



cmake_minimum_required(VERSION 3.20)project(MyMonorepo LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 通用选项option(BUILD_TESTS "Build tests" ON)

# 包含库add_subdirectory(libs/core)add_subdirectory(libs/math)add_subdirectory(libs/network)

# 包含应用程序add_subdirectory(apps/server)add_subdirectory(apps/client)

# 包含测试if(BUILD_TESTS) enable_testing() add_subdirectory(tests)endif()


重要事项:

  • 使用target_link_libraries明确指定库之间的依赖关系。
  • 对于外部依赖(例如Boost、fmt),使用FetchContent或Conan。
  • 避免全局include_directories — 使用带有PUBLIC或PRIVATE的target_include_directories。


3. 管理单一代码库内的依赖关系



单一代码库的主要问题之一是循环依赖。解决方案:严格的层次结构。例如:



  • core(不依赖任何东西,除了标准库)
  • math(依赖于core)
  • network(依赖于core和math)
  • server(依赖于core、math、network)


库math的CMakeLists.txt示例:



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 # 明确指定依赖关

博客

书籍推荐