21、团队共享策略:如何将 Presets 文件纳入版本控制并规范团队使用
Presets 文件写好了,配置调通了,接下来最关键的一步——怎么让整个团队都用起来?
说实话,我在不少团队里见过这样的场景:一个人折腾了三天,终于把 CMake Presets 调顺了,结果其他人要么不知道有这个文件,要么拉下来就跑不通。最后大家还是各写各的构建命令,Presets 文件躺在仓库里吃灰。
这其实不是技术问题,是策略问题。今天我们就聊聊,怎么把 Presets 文件真正变成团队的共同资产。
Presets 文件该不该提交到版本控制?
我的答案是:必须提交,但有选择地提交。
你想想看,Presets 文件本身就是用来统一构建行为的。如果它不在版本控制里,那「统一」二字从何谈起?
核心原则:CMakePresets.json 必须入库,CMakeUserPresets.json 绝对不能入库。
为什么这么分?
- CMakePresets.json:团队共享的公共配置。编译器路径、构建类型、测试选项、安装路径——这些大家都应该用同一套。
- CMakeUserPresets.json:个人本地的私有配置。比如你习惯用 Ninja 而同事用 Makefiles,或者你本地有特殊的工具链路径。这些跟别人没关系。
我记得有一次,一个新同事把 CMakeUserPresets.json 也提交上来了。结果里面写着他自己电脑上的 Qt 路径,其他人一拉代码,构建直接崩。嗯,从那以后我就在 .gitignore 里明确加了一行:
# 忽略用户私有配置
CMakeUserPresets.json
版本控制里的 Presets 文件长什么样?
团队共享的 CMakePresets.json,我建议只保留「通用配置」和「平台差异配置」。具体来说:
{
"version": 6,
"configurePresets": [
{
"name": "default",
"displayName": "默认配置",
"description": "团队通用 Debug 构建",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "release",
"inherits": "default",
"displayName": "发布版",
"description": "优化后的 Release 构建",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": "ON"
}
}
],
"buildPresets": [
{
"name": "default",
"configurePreset": "default"
},
{
"name": "release",
"configurePreset": "release"
}
],
"testPresets": [
{
"name": "default",
"configurePreset": "default",
"output": {
"outputOnFailure": true
}
}
]
}
这里有个细节:不要把绝对路径写进去。像 /home/zhangsan/toolchains 这种,一旦提交,别人拉下来肯定跑不了。用 ${sourceDir} 或者环境变量来替代,才是正道。
团队规范怎么定?
光有文件还不够,得有规矩。我建议团队内部约定几条「硬杠杠」:
我的经验:规范不用写太多,3-5 条核心规则就够了。写多了没人看,看了也记不住。
- 所有构建必须通过 Presets 触发。禁止直接敲
cmake ..这种裸命令。CI/CD 流水线也一样,统一用cmake --preset。 - 公共配置变更需要 Code Review。改
CMakePresets.json跟改代码一样,必须有人审核。我曾经见过有人把CMAKE_BUILD_TYPE从Debug改成Release提交了,结果大家 Debug 了一整天找不到断点。 - 本地特殊配置写在
CMakeUserPresets.json里。并且这个文件要加入.gitignore,谁都不准提交。 - 新增 Preset 必须附带文档说明。至少写清楚这个 Preset 是干什么的、适用于什么场景。别搞出那种「名字叫 debug 实际跑的是 release」的乌龙。
CI/CD 里怎么用?
团队共享 Presets 的一个大好处,就是 CI/CD 配置可以极度简化。以前你可能要在 Jenkinsfile 或者 GitHub Actions 里写一堆 cmake -DCMAKE_BUILD_TYPE=Debug -G Ninja 之类的参数,现在只需要一行:
cmake --preset default
cmake --build --preset default
ctest --preset default
你看,三行命令搞定整个构建-测试流程。而且 CI 和本地开发用的是同一套配置,再也不会出现「本地能跑 CI 跑不过」的尴尬情况。
注意:CI 环境里可能没有 Ninja,或者编译器路径不一样。这时候可以在 CI 的 CMakeUserPresets.json 里覆盖 generator 和 toolchain 字段。但记住,这个文件不要提交到仓库,而是由 CI 脚本在运行时动态生成。
知识体系结构图
下面这张图梳理了团队共享 Presets 的核心逻辑:
避坑指南
最后分享几个我踩过的坑,希望能帮你少走弯路:
- 不要用
includes字段引用本地路径。我见过有人把includes: ["/home/me/common.json"]写进 Presets,结果其他人根本找不到这个文件。用相对路径,或者干脆把公共部分直接写在CMakePresets.json里。 - 版本号要统一。团队里如果有人用 CMake 3.20,有人用 3.25,那
version字段就写3(兼容 3.20+),别写6(需要 3.25+)。不然低版本 CMake 的人直接报错。 - 定期清理废弃的 Preset。项目迭代过程中,可能会产生一些临时 Preset(比如
debug-with-sanitizer、experimental-clang)。用完了就删掉,别让文件越来越臃肿。
说白了,Presets 文件本身只是个工具。真正让团队受益的,是背后那套「大家都按同一个规矩来」的共识。文件可以提交到仓库,但共识需要靠沟通和规范来维持。
一句话总结:CMakePresets.json 入库共享,CMakeUserPresets.json 本地私有,CI/CD 统一调用,团队规范跟上。做到这四点,Presets 才能真正发挥价值。
公众号:蓝海资料掘金营,微信 deep3321