现代 C++ 项目脚手架:ModernCppStarter

发布于:2025-07-27 ⋅ 阅读:(18) ⋅ 点赞:(0)

在这里插入图片描述

创建现代化 C++ 项目通常需要经历繁琐的初始化流程:搭建构建系统、集成测试框架、配置持续集成流水线…这些重复性工作往往会消耗数小时甚至数天时间。​​ModernCppStarter​​ 模板凝结了多个工业级项目的实践经验,通过预置一体化工具链,将项目初始化工作压缩到分钟级,让开发者聚焦业务逻辑而非环境配置。

一、核心特性

类别 功能 价值点
智能构建 现代模块化 CMake 架构,CPM.cmake 依赖包管理 支持header-only及任意规模的项目
质量保障 Catch2 测试框架 + Codecov 覆盖 测试驱动开发闭环
持续集成 GitHub Actions 五合一流水线 构建/测试/文档/多平台自动验证
代码规范 强约束格式化(clang-format + cmake-format) 统一团队编码风格
文档体系 Doxygen + GitHub Pages 专业文档自动生成与发布
生产级支持 Sanitizers/静态分析器集成 内存安全与代码质量双重保障

二、cmake 代码架构说明

在ModernCppStarter项目中,作者选择了将测试目录、独立可执行程序目录和文档目录作为独立的CMake子项目。构建时,用户可以选择单独构建子目录(如cmake -S test -B build/test)或通过all目录一次性构建所有子项目。

这种方法使得第三方项目能够轻松复用项目的库代码。为了让集成开发环境(IDE)能够看到项目的全部目标,模板包含了 all 目录,该目录将为所有子项目创建一个统一的构建入口。为了获得最佳的 IDE 支持,可以将此目录用作主目录。

模板采用分离式 CMake 结构

  • 📁 主目录:仅定义核心 目标(纯净无污染)
  • 📂 test/standalone/:独立消费者项目,作为独立模块各自管理(通过 CPMAddPackage 引入库)
隔离构建环境
纯净输出
独立构建
CI流水线
测试组件
安装包
可执行程序
GitHub Pages
文档系统
库核心

这种设计使第三方项目能够无缝集成您的库,同时保持:

  • ✅ 模块化分离​​:库核心与消费者(测试/应用/文档)完全解耦
  • ​✅ ​二进制隔离​​:避免多组件交叉污染构建环境
  • ✅ ​IDE 友好​​:原生支持 CLion/VSCode 开发体验
  • ✅ ​生产就绪​​:满足专业库开发的发行标准

三、使用说明:立即开始您的现代化之旅

创建项目

  1. 基于模板模板创建项目
# clone源码创建项目,或使用 github 的 `Use template`
git clone --depth 1 https://github.com/TheLartians/ModernCppStarter my-project
cd my-project && rm -rf .git && git init
  1. 重命名核心元素
操作项 命令/说明 注意事项
项目名称 替换所有 CMakeLists.txt 中的 Greeter 为您的项目名称 Greeter 表示项目名称(大写开头),greeter 用于文件名(全小写)
包含目录 include/greeter 重命名为 include/<小写项目名> 同步更新相关 #include 路径
源文件 使用自己的源代码文件替换原有文件
header-only 库支持 修改 CMakeLists.txt 中的 add_library 类型为 INTERFACE 详见 CMakeLists.txt 中的注释
项目许可证 选择合适的开源许可证替换默认 License 详见 CMakeLists.txt 中的注释
  1. 测试覆盖率支持:添加 CODECOV_TOKEN

在 GitHub 仓库的 Secrets 中添加 codecov token,命名为 CODECOV_TOKEN

  1. 清理不需要的部分

删除不需要的目录或文件(如 standalone)和 GitHub Actions 工作流文件

  1. 开发阶段建议

使用 一次构建全项目 进行整体开发,一次性构建库/测试/可执行文件,提升开发效率。

编译及运行 standalone 可执行程序

在项目根目录执行下面的指令

cmake -S standalone -B build/standalone
cmake --build build/standalone
./build/standalone/Greeter --help

编译及运行 test

要收集测试覆盖率信息,请在运行 CMake 时添加 -DENABLE_TEST_COVERAGE=1 选项。

cmake -S test -B build/test # -DENABLE_TEST_COVERAGE=1 测试覆盖率
cmake --build build/test
CTEST_OUTPUT_ON_FAILURE=1 cmake --build build/test --target test

# 直接运行: 
./build/test/GreeterTests

代码格式化

基于.clang-format.cmake-format,通过以下命令统一 C++/CMake 代码风格(​​需提前安装依赖工具​​):clang-format, cmake-format and pyyaml
VSCode 可支持保存时自动格式化

cmake -S test -B build/test

# 检查代码风格问题
cmake --build build/test --target format

# 自动修复风格问题
cmake --build build/test --target fix-format

更多详情可查阅 Format.cmake.

使用 python pip 安装依赖:

pip install clang-format==14.0.6 cmake_format==0.6.11 pyyaml

生成文档

The documentation is automatically built and published whenever a GitHub Release is created.
To manually build documentation, call the following command.

文档会在创建GitHub Release 版本 时自动构建并发布
若要手动构建文档执行以下命令(已安装 Doxygen, jinja2 及 Pygments):

cmake -S documentation -B build/doc
cmake --build build/doc --target GenerateDocs
# 预览
open build/doc/doxygen/html/index.html

一次构建全项目

该项目同时提供了 all 目录,通过 add_subdirectory,支持一次性构建所有目标。该方式在开发阶段尤其高效,它能够:

  • 向 IDE 完整暴露所有子项目​​ - 便于代码导航和调试
  • ​​避免库的重复构建​​ - 显著提升编译效率
cmake -S all -B build
cmake --build build

# 运行测试
./build/test/GreeterTests
# 格式化
cmake --build build --target fix-format
# 运行可执行程序
./build/standalone/Greeter --help
# 生成文档
cmake --build build --target GenerateDocs

附加工具

测试和可执行程序子项目通过 tools.cmake 提供按需扩展能力,可通过 CMake 配置参数按需启用增强工具。当前支持以下工具:

内存检测工具 (Sanitizers)

通过配置 CMake 参数启用:

-DUSE_SANITIZER=<Address | Memory | MemoryWithOrigins | Undefined | Thread | Leak | 'Address;Undefined'>
静态代码分析

Static Analyzers can be enabled by setting -DUSE_STATIC_ANALYZER=<clang-tidy | iwyu | cppcheck>, or a combination of those in quotation marks, separated by semicolons.
By default, analyzers will automatically find configuration files such as .clang-format.
Additional arguments can be passed to the analyzers by setting the CLANG_TIDY_ARGS, IWYU_ARGS or CPPCHECK_ARGS variables.

通过配置单个启用:-DUSE_STATIC_ANALYZER=<clang-tidy | iwyu | cppcheck>。或组合启用(引号内用分号分隔):-DUSE_STATIC_ANALYZER="clang-tidy;cppcheck"

默认自动加载配置文件(如 .clang-format),可通过变量传递额外参数:CLANG_TIDY_ARGS, IWYU_ARGS, CPPCHECK_ARGS

编译缓存加速 (Ccache)

通过配置-DUSE_CCACHE=<ON | OFF>启用。需要安装 ccache, 通过设置环境变量 CPM_SOURCE_CACHE=<path> 设置缓存路径。

如:export CPM_SOURCE_CACHE=$HOME/.cache/CPM

注意事项
  • 该脚手架在 CMakeLists.txt 中使用 GLOB 来添加源文件,源代码文件结构的改动可能无法被 CMake 构建系统自动捕获,此时必须手动重新调用 CMake 更新构建。虽然 GLOB 存在该限制,但作者偏好其简洁性而采用;可以按需改为显式列出源文件。

    # 两种模式对比示例
    # ---------------
    # (1) GLOB 便捷模式(需手动触发CMake更新)
    file(GLOB SOURCES "src/*.cpp") 
    
    # (2) 显式声明模式(自动检测文件变化)
    set(SOURCES
        src/core.cpp
        src/utils.cpp
        # 添加新文件需手动更新此处
    )
    add_library(MyProject ${SOURCES})
    
  • 避免在库的 CMakeLists 中直接添加衍生项目​​(尽管这在 C++ 生态中很常见),应参考 standalone 创建独立子项目目录。因为这种做法会导致:
    🔄 ​​依赖关系倒置​​:破坏 “库 → 消费者” 的自然层级
    🧩 ​​系统复杂度失控​​:构建逻辑难以维护和扩展

总结

无论您是:

  • 💼 企业团队需要标准化开发流程
  • 🎓 学生开启首个开源项目
  • 🔬 研究机构开发高性能库

ModernCppStarter 都能让您赢得起跑线优势。

END

博客中文章多为自己技术学习与实践备忘录,如果这篇文章对您有所启发或帮助,欢迎👍点赞或↪️分享,让更多开发者朋友受益!感谢您的阅读! ^_^


网站公告

今日签到

点亮在社区的每一天
去签到