3、基础配置项:name、hidden、vendor、version 等顶层字段详解
咱们直接切入正题。CMake Presets 的顶层字段,说白了就是整个配置文件的「身份证」和「开关」。我刚开始接触 Presets 时,觉得这些字段不就是填个名字嘛,有啥好讲的?结果有一次在团队里因为 vendor 字段没写对,导致 CI 工具解析失败,折腾了大半天。嗯,从那以后我再也不敢小看这些基础配置了。
3.1 name:每个 Preset 的唯一标识
name 字段是必须的。它就像每个人的身份证号,在一个文件中不能重复。我个人习惯用 「平台-构建类型-编译器」 的命名方式,比如 linux-release-gcc。这样一看名字就知道这个 Preset 是干啥的。
- 同一个
CMakePresets.json中,name不能重复 - 区分大小写,
Debug和debug是两个不同的 Preset - 建议使用小写字母和连字符,避免空格和特殊字符
{
"version": 3,
"configurePresets": [
{
"name": "linux-release-gcc",
"displayName": "Linux Release (GCC)",
"description": "面向 Linux 平台的 Release 构建,使用 GCC 编译器"
},
{
"name": "linux-debug-clang",
"displayName": "Linux Debug (Clang)",
"description": "面向 Linux 平台的 Debug 构建,使用 Clang 编译器"
}
]
}
你看,displayName 和 description 是给人看的,name 是给机器用的。我在项目中遇到过有人把 name 写得特别长,比如 "This is my special debug build for testing on Windows with MSVC"。说实话,这虽然能跑,但你在命令行里敲 cmake --preset 的时候,补全起来会疯掉的。
win-msvc-debug、mac-clang-release。
3.2 hidden:让 Preset 隐身
hidden 字段是个布尔值,默认是 false。把它设为 true 后,这个 Preset 就不会出现在 cmake --list-presets 的输出里。但注意,它仍然可以被其他 Preset 通过 inherits 继承。
为什么会需要隐藏 Preset?说白了,就是用来做「基类」的。我经常定义一个 common-flags 的隐藏 Preset,里面放所有平台都通用的编译选项,然后让各个平台的 Preset 去继承它。
{
"configurePresets": [
{
"name": "common-base",
"hidden": true,
"cacheVariables": {
"CMAKE_CXX_STANDARD": "17",
"CMAKE_CXX_EXTENSIONS": "OFF"
}
},
{
"name": "linux-debug",
"hidden": false,
"inherits": "common-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
}
]
}
hidden 设为 true 后,忘了在别的 Preset 里 inherits 它。结果这个 Preset 就真的「消失」了,谁也找不到。所以隐藏 Preset 一定要有被继承的地方,否则就是死代码。
3.3 vendor:给工具链留个「后门」
vendor 字段是个 JSON 对象,用来存放 CMake 官方不直接支持的、特定于某个工具链或 IDE 的配置。比如 Visual Studio、CLion、Qt Creator 这些工具,它们可能会在 vendor 里放一些自己的扩展字段。
我个人的经验是:尽量少用 vendor。因为一旦用了,你的 Preset 文件就和某个特定工具绑定了。换到另一个 IDE 或者 CI 环境,这些配置可能就失效了。
| 工具 | vendor 常见用途 |
|---|---|
| Visual Studio | 指定解决方案配置名称、平台工具集 |
| CLion | 工具链路径、环境变量 |
| Qt Creator | Kit 名称、Qt 版本路径 |
{
"configurePresets": [
{
"name": "vs2022-debug",
"vendor": {
"microsoft.com/VisualStudioSettings": {
"platformToolset": "v143",
"configurationType": "Debug"
}
}
}
]
}
CMakeUserPresets.json 里。这样每个人的 IDE 配置不会互相干扰。
3.4 version:版本号决定你能用啥
version 字段指定了 Preset 文件的格式版本。目前主流的是 版本 3(CMake 3.21+),版本 4 在 CMake 3.23 中引入,增加了 buildPresets 和 testPresets 的更多功能。
我建议直接写 "version": 3,除非你明确需要版本 4 的新特性。为什么?因为版本 3 的兼容性最好,大多数 CI 环境和团队成员的 CMake 版本都能支持。
- 版本 1:CMake 3.19+,基础功能
- 版本 2:CMake 3.20+,增加了
hidden、vendor - 版本 3:CMake 3.21+,增加了
condition、workflowPresets - 版本 4:CMake 3.23+,增加了
buildPresets的targets过滤等
3.5 其他顶层字段:displayName、description、environment
这几个字段虽然不强制,但我建议每个 Preset 都写上。尤其是 displayName 和 description,在 cmake --list-presets 时能显示出来,方便团队成员快速理解每个 Preset 的用途。
{
"configurePresets": [
{
"name": "win-msvc-release",
"displayName": "Windows MSVC Release",
"description": "面向 Windows 平台的 Release 构建,使用 MSVC 编译器,开启 LTO",
"environment": {
"MY_CUSTOM_VAR": "some_value"
}
}
]
}
environment 字段可以设置环境变量,这些变量只在当前 Preset 的构建过程中生效。我在项目中遇到过需要设置 CC 和 CXX 环境变量来指定编译器的情况,用 environment 就比在系统层面改要干净得多。
3.6 知识体系总览
下面这张图把顶层字段的关系梳理清楚了。你看,name 是核心,hidden 控制可见性,vendor 是扩展接口,version 决定能力边界,其他字段则是辅助信息。
3.7 实战建议:如何组织你的 Preset 文件
最后,我分享一个我在实际项目中用的组织方式。说白了就是「分层设计」:
- 底层: 定义几个
hidden: true的基类 Preset,放通用配置(C++ 标准、通用编译选项) - 中间层: 按平台分,比如
linux-base、win-base,继承底层,添加平台特有配置 - 顶层: 具体的构建 Preset,比如
linux-release-gcc,继承中间层,指定构建类型
这样改起来特别方便。比如有一天你想给所有 Linux 构建加一个 -Wall 选项,只需要改 linux-base 这一个地方就行。我曾经在接手一个老项目时,看到人家把同样的编译选项复制粘贴了 20 多遍,改一次要改 20 多个地方……嗯,那滋味可不好受。
公众号:蓝海资料掘金营,微信deep3321