创建现代化 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
引入库)
这种设计使第三方项目能够无缝集成您的库,同时保持:
- ✅ 模块化分离:库核心与消费者(测试/应用/文档)完全解耦
- ✅ 二进制隔离:避免多组件交叉污染构建环境
- ✅ IDE 友好:原生支持 CLion/VSCode 开发体验
- ✅ 生产就绪:满足专业库开发的发行标准
三、使用说明:立即开始您的现代化之旅
创建项目
- 基于模板模板创建项目
# clone源码创建项目,或使用 github 的 `Use template`
git clone --depth 1 https://github.com/TheLartians/ModernCppStarter my-project
cd my-project && rm -rf .git && git init
- 重命名核心元素
操作项 | 命令/说明 | 注意事项 |
---|---|---|
项目名称 | 替换所有 CMakeLists.txt 中的 Greeter 为您的项目名称 |
Greeter 表示项目名称(大写开头),greeter 用于文件名(全小写) |
包含目录 | 将 include/greeter 重命名为 include/<小写项目名> |
同步更新相关 #include 路径 |
源文件 | 使用自己的源代码文件替换原有文件 | |
header-only 库支持 | 修改 CMakeLists.txt 中的 add_library 类型为 INTERFACE |
详见 CMakeLists.txt 中的注释 |
项目许可证 | 选择合适的开源许可证替换默认 License | 详见 CMakeLists.txt 中的注释 |
- 测试覆盖率支持:添加 CODECOV_TOKEN
在 GitHub 仓库的 Secrets 中添加 codecov token,命名为 CODECOV_TOKEN
- 清理不需要的部分
删除不需要的目录或文件(如 standalone
)和 GitHub Actions 工作流文件
- 开发阶段建议
使用 一次构建全项目 进行整体开发,一次性构建库/测试/可执行文件,提升开发效率。
编译及运行 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
博客中文章多为自己技术学习与实践备忘录,如果这篇文章对您有所启发或帮助,欢迎👍点赞或↪️分享,让更多开发者朋友受益!感谢您的阅读!
^_^