@chengzhao-dev/dsh-cpp-workflow 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -20
- package/README.en.md +18 -16
- package/README.md +18 -16
- package/cordis.patch.yml +2 -5
- package/lib/index.js +7 -8
- package/lib/workspace.js +14 -14
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +5 -5
- package/skills/building-cpp/SKILL.md +6 -6
- package/skills/building-cpp/assets/config/.clang-format +3 -38
- package/skills/building-cpp/assets/config/.clang-tidy +8 -39
- package/skills/building-cpp/assets/config/.clangd +2 -5
- package/skills/building-cpp/assets/config/.vscode/extensions.json +2 -1
- package/skills/building-cpp/assets/config/.vscode/settings.json +16 -1
- package/skills/building-cpp/assets/templates/projects/common/running-build.sh +29 -18
- package/skills/building-cpp/assets/templates/projects/multi/CMakeLists.txt +9 -5
- package/skills/building-cpp/assets/templates/projects/multi/include/greeting.h +5 -3
- package/skills/building-cpp/assets/templates/projects/multi/src/greeting.cc +18 -0
- package/skills/building-cpp/assets/templates/projects/multi/src/main.cc +8 -0
- package/skills/building-cpp/assets/templates/projects/shared-library/CMakeLists.txt +8 -3
- package/skills/building-cpp/assets/templates/projects/shared-library/greeting/CMakeLists.txt +15 -5
- package/skills/building-cpp/assets/templates/projects/shared-library/greeting/include/greeting.h +5 -3
- package/skills/building-cpp/assets/templates/projects/shared-library/greeting/src/greeting.cc +18 -0
- package/skills/building-cpp/assets/templates/projects/shared-library/src/main.cc +8 -0
- package/skills/building-cpp/assets/templates/projects/single/CMakeLists.txt +7 -3
- package/skills/building-cpp/assets/templates/projects/single/src/main.cc +15 -0
- package/skills/building-cpp/assets/templates/projects/static-library/CMakeLists.txt +8 -3
- package/skills/building-cpp/assets/templates/projects/static-library/greeting/CMakeLists.txt +15 -5
- package/skills/building-cpp/assets/templates/projects/static-library/greeting/include/greeting.h +5 -3
- package/skills/building-cpp/assets/templates/projects/static-library/greeting/src/greeting.cc +18 -0
- package/skills/building-cpp/assets/templates/projects/static-library/src/main.cc +8 -0
- package/skills/building-cpp/examples/cmake.md +17 -17
- package/skills/building-cpp/examples/environment.md +4 -3
- package/skills/building-cpp/examples/tooling.md +31 -16
- package/skills/building-cpp/references/build-script.md +2 -2
- package/skills/building-cpp/references/cmake.md +35 -17
- package/skills/building-cpp/references/environment.md +17 -13
- package/skills/building-cpp/references/linking.md +6 -6
- package/skills/building-cpp/references/standards/README.md +165 -0
- package/skills/building-cpp/references/standards/c++11/README.md +50 -0
- package/skills/building-cpp/references/standards/c++11/cmake-snippet.cmake +7 -0
- package/skills/building-cpp/references/standards/c++14/README.md +48 -0
- package/skills/building-cpp/references/standards/c++14/cmake-snippet.cmake +7 -0
- package/skills/building-cpp/references/standards/c++17/README.md +49 -0
- package/skills/building-cpp/references/standards/c++17/cmake-snippet.cmake +7 -0
- package/skills/building-cpp/references/standards/c++20/README.md +49 -0
- package/skills/building-cpp/references/standards/c++20/cmake-snippet.cmake +7 -0
- package/skills/building-cpp/references/standards/c++23/README.md +50 -0
- package/skills/building-cpp/references/standards/c++23/cmake-snippet.cmake +7 -0
- package/skills/building-cpp/references/static-analysis.md +27 -15
- package/skills/building-cpp/scripts/checking-environment.mjs +21 -21
- package/skills/building-cpp/steps/01-build.md +78 -76
- package/skills/building-cpp/steps/02-tooling.md +43 -41
- package/skills/building-cpp/steps/03-check.md +60 -60
- package/skills/developing-cpp/SKILL.md +6 -6
- package/skills/developing-cpp/examples/comments.md +10 -8
- package/skills/developing-cpp/examples/exceptions.md +64 -45
- package/skills/developing-cpp/examples/naming.md +2 -2
- package/skills/developing-cpp/examples/structure.md +12 -9
- package/skills/developing-cpp/references/comments.md +10 -8
- package/skills/developing-cpp/references/declaration-order.md +7 -4
- package/skills/developing-cpp/references/exceptions.md +83 -46
- package/skills/developing-cpp/references/glossary.md +6 -6
- package/skills/developing-cpp/references/google-cpp-style.md +27 -37
- package/skills/developing-cpp/references/language.md +4 -4
- package/skills/developing-cpp/references/layout.md +14 -14
- package/skills/developing-cpp/references/naming.md +7 -6
- package/skills/developing-cpp/references/project-design.md +3 -3
- package/skills/developing-cpp/references/standard-library.md +1 -1
- package/skills/developing-cpp/steps/02-boundary.md +7 -7
- package/skills/developing-cpp/steps/03-declaration.md +9 -8
- package/skills/developing-cpp/steps/04-implementation.md +11 -7
- package/templates/cpp-workflow-project/SKILL.md +1 -1
- package/templates/cpp-workflow-project/environment.json +2 -1
- package/skills/building-cpp/assets/templates/projects/multi/src/greeting.cpp +0 -13
- package/skills/building-cpp/assets/templates/projects/multi/src/main.cpp +0 -8
- package/skills/building-cpp/assets/templates/projects/shared-library/greeting/src/greeting.cpp +0 -13
- package/skills/building-cpp/assets/templates/projects/shared-library/src/main.cpp +0 -8
- package/skills/building-cpp/assets/templates/projects/single/src/main.cpp +0 -9
- package/skills/building-cpp/assets/templates/projects/static-library/greeting/src/greeting.cpp +0 -13
- package/skills/building-cpp/assets/templates/projects/static-library/src/main.cpp +0 -8
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# C++23 标准档案
|
|
2
|
+
|
|
3
|
+
[返回标准索引](../README.md)
|
|
4
|
+
|
|
5
|
+
| 项 | 值 |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| `standard` | `c++23` |
|
|
8
|
+
| CMake meta-feature | `cxx_std_23` |
|
|
9
|
+
| `CXX_STANDARD` | `23` |
|
|
10
|
+
| `__cplusplus` | `202302L` |
|
|
11
|
+
| clang-format 21/22 | `Standard: Latest` |
|
|
12
|
+
| 模板实用下限 | GCC 13 / Clang 17(模板只用 `std::format`) |
|
|
13
|
+
|
|
14
|
+
## 最重要的三件事
|
|
15
|
+
|
|
16
|
+
1. C++23 在 GCC/Clang 上仍是 Partial;`std::print` 要 libstdc++ 14+/libc++ 19+,`std::stacktrace` 还要链接库。
|
|
17
|
+
2. clang-format 21/22 不认识 `c++23`,配置写 `Standard: Latest`;`.clangd` 不写 `-std`,否则会把编译数据库降回 C++20。
|
|
18
|
+
3. 模板默认 23,但模板只强依赖 `std::format`;不要因为默认 23 就在公共头里用 `std::expected`/`std::print`,先确认所有 target 和库门槛。
|
|
19
|
+
|
|
20
|
+
## 本档能用
|
|
21
|
+
|
|
22
|
+
- C++20 的全部内容。
|
|
23
|
+
- `std::print` / `std::println`、`std::expected`、`std::stacktrace`。
|
|
24
|
+
- `if consteval`、显式对象参数(deducing this)、`std::mdspan`、`std::flat_map`。
|
|
25
|
+
- ranges 的 C++23 增补(工具链实现为准)。
|
|
26
|
+
|
|
27
|
+
## 本档不能假设
|
|
28
|
+
|
|
29
|
+
- C++23 在 GCC/Clang 上仍是 Partial:具体设施要查编译器状态页,不能只看 `-std=c++23`。
|
|
30
|
+
- `std::print` 的库门槛是 libstdc++ 14+ / libc++ 19+;`std::stacktrace` 还要链接对应库,链接失败不是语法错误。
|
|
31
|
+
- `std::expected` 的 monadic 接口、`std::flat_map` 等设施在旧标准库上可能缺失。
|
|
32
|
+
- 模板只用 `std::format`,不会因为默认 C++23 就强依赖 `print`/`stacktrace`。
|
|
33
|
+
|
|
34
|
+
## CMake
|
|
35
|
+
|
|
36
|
+
把 [cmake-snippet.cmake](cmake-snippet.cmake) 的 target 名换成实际 target。默认模板的 `cxx_std_23` 和 `CXX_STANDARD 23` 必须与 `environment.json` 的 `standard` 一致。
|
|
37
|
+
|
|
38
|
+
## 工具
|
|
39
|
+
|
|
40
|
+
- `.clang-format`:`Standard: Latest`(21/22 不接受 `c++23`;`Latest` 按工具支持的最高标准解析)。
|
|
41
|
+
- `.clangd`:不写 `-std`,从 `compile_commands.json` 读;写死 `-std=c++20` 会让 `<print>` 和 `if consteval` 解析失败。
|
|
42
|
+
- `.clang-tidy`:Google 基线;不要因为 C++23 就打开 `cppcoreguidelines-*` 整包。
|
|
43
|
+
|
|
44
|
+
## 降档/升级
|
|
45
|
+
|
|
46
|
+
从 C++23 降到 C++20 见 [C++20 档案](../c++20/README.md)。升级到 C++26 前先确认 CMake 3.25+、编译器/标准库支持、clang-format 的 `c++26` 枚举;新增目录流程见[标准索引](../README.md#新增标准)。
|
|
47
|
+
|
|
48
|
+
## 验证
|
|
49
|
+
|
|
50
|
+
configure、build、run 必测;`compile_commands.json` 的最后一个 `-std=` 必须是 `-std=c++23`。模板在 C++23 下走 `std::format` 分支;若使用 `print`/`stacktrace`,另做链接测试。
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# 静态分析与语言服务
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
三件语言工具各管一段:`clang-format` 排版、`clang-tidy` 诊断、`clangd` 提供补全/跳转/诊断。它们都读同一份编译数据库,但职责不重叠。编辑器侧只保留 CMake Tools 作为配置、构建、运行和调试入口;C/C++ 扩展只做 `CMake: Debug` 的调试后端,不参与语言服务。
|
|
4
4
|
|
|
5
5
|
## clang-format
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
clang-format --dry-run --Werror src/*.
|
|
8
|
+
clang-format --dry-run --Werror src/*.cc include/*.h tests/*.cc
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
- 检查用 `--dry-run --Werror`;需要自动修复时单独跑 `clang-format -i`,不要在构建脚本里悄悄改源码。
|
|
12
12
|
- 工程必须有根 `.clang-format`;缺失时先复制配置,不要回退到内置风格,回退会掩盖配置缺失。
|
|
13
13
|
- 只扫描项目源码:`src/`、`include/`、`apps/`、`tests/` 等实际存在的目录;不扫描 `build/`、第三方、生成文件。
|
|
14
14
|
- 配置文件在工程根 `.clang-format`;不要依赖用户主目录或编辑器内置配置。
|
|
15
|
-
- `
|
|
15
|
+
- `BasedOnStyle: Google`、`Standard: Latest`;clang-format 21/22 不接受 `c++23`,`Latest` 按工具支持的最高标准解析。列宽 80、2 空格、包含顺序都取 Google 预设,不另写 `ColumnLimit` 或 `IncludeCategories`。
|
|
16
16
|
- 格式化失败就是失败,不要用 `// clang-format off` 绕过;确需关闭时只包住无法排版的宏或表格,并写一句理由。
|
|
17
17
|
|
|
18
18
|
## clang-tidy
|
|
@@ -21,7 +21,7 @@ clang-format --dry-run --Werror src/*.cpp include/*.h tests/*.cpp
|
|
|
21
21
|
clang-tidy -p build/clang \
|
|
22
22
|
--header-filter="^$(pwd -P)/(include|src|apps|tests)/" \
|
|
23
23
|
--warnings-as-errors='*' \
|
|
24
|
-
src/*.
|
|
24
|
+
src/*.cc apps/*.cc tests/*.cc
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
- `-p` 指向当前编译器的构建目录,读取 `compile_commands.json`。
|
|
@@ -30,7 +30,7 @@ clang-tidy -p build/clang \
|
|
|
30
30
|
- 系统头默认被排除,不要加 `--system-headers`。
|
|
31
31
|
- 只扫描项目源文件;不要把 `build/` 或第三方源码传给 clang-tidy。
|
|
32
32
|
- `--warnings-as-errors='*'` 把警告当失败;修代码,不要新增 `NOLINT`。确需抑制时写 `// NOLINT(检查名): 理由`,理由必须具体。
|
|
33
|
-
- 配置在工程根 `.clang-tidy
|
|
33
|
+
- 配置在工程根 `.clang-tidy`;默认集合是 `google-*` 加 `readability-identifier-naming`。关闭某条时逐条写理由,不整族关闭;命名规则只配项目确实统一的项,不设 `FunctionCase`。
|
|
34
34
|
- 没有编译数据库时先回到 `building-cpp` 的定构建生成;不要用 `--` 手工拼编译参数绕过。
|
|
35
35
|
- `clang-tidy` 的诊断可能指向头文件;修头文件里的声明或实现,不要只改调用点。
|
|
36
36
|
|
|
@@ -41,17 +41,13 @@ clang-tidy -p build/clang \
|
|
|
41
41
|
```yaml
|
|
42
42
|
CompileFlags:
|
|
43
43
|
CompilationDatabase: build/clang
|
|
44
|
-
Add:
|
|
45
|
-
- -std=c++20
|
|
46
|
-
- -Wall
|
|
47
|
-
- -Wextra
|
|
48
44
|
Diagnostics:
|
|
49
45
|
Suppress:
|
|
50
46
|
- pp_file_not_found
|
|
51
47
|
```
|
|
52
48
|
|
|
53
49
|
- `CompilationDatabase` 指向当前编译器目录;GCC 模式改 `build/gcc`。
|
|
54
|
-
- `
|
|
50
|
+
- 不要在 `.clangd` 写 `-std`:它会覆盖 `compile_commands.json`,把 C++23 工程降成旧标准。标准只由构建声明和编译数据库决定。
|
|
55
51
|
- 静态检查规则只在 `.clang-tidy` 里维护;clangd 读取同一份配置,不要在这里复制检查列表。
|
|
56
52
|
- `Suppress` 只放确实无法避免的解析噪声(如 `pp_file_not_found`),并写理由。
|
|
57
53
|
|
|
@@ -82,7 +78,11 @@ Diagnostics:
|
|
|
82
78
|
|
|
83
79
|
```json
|
|
84
80
|
{
|
|
85
|
-
"recommendations": [
|
|
81
|
+
"recommendations": [
|
|
82
|
+
"llvm-vs-code-extensions.vscode-clangd",
|
|
83
|
+
"ms-vscode.cmake-tools",
|
|
84
|
+
"ms-vscode.cpptools"
|
|
85
|
+
]
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
88
|
|
|
@@ -96,13 +96,25 @@ Diagnostics:
|
|
|
96
96
|
"--background-index"
|
|
97
97
|
],
|
|
98
98
|
"cmake.buildDirectory": "${workspaceFolder}/build/clang",
|
|
99
|
-
"cmake.generator": "Ninja"
|
|
99
|
+
"cmake.generator": "Ninja",
|
|
100
|
+
"cmake.buildBeforeRun": true,
|
|
101
|
+
"cmake.exportCompileCommandsFile": true,
|
|
102
|
+
"cmake.debugConfig": {
|
|
103
|
+
"type": "cppdbg",
|
|
104
|
+
"request": "launch",
|
|
105
|
+
"MIMode": "lldb",
|
|
106
|
+
"miDebuggerPath": "/usr/bin/lldb",
|
|
107
|
+
"stopAtEntry": false
|
|
108
|
+
},
|
|
109
|
+
"C_Cpp.intelliSenseEngine": "disabled"
|
|
100
110
|
}
|
|
101
111
|
```
|
|
102
112
|
|
|
113
|
+
- 配置、构建、运行和调试只从 CMake Tools 进入;不要同时维护 `tasks.json` 或 `launch.json`,否则会出现第二套构建或启动路径。
|
|
114
|
+
- C/C++ 扩展只作为 CMake 快速调试的 `cppdbg` 后端;IntelliSense 关闭,补全、跳转、诊断和格式化只由 clangd 提供。
|
|
103
115
|
- 不推荐与 clangd 冲突的 C++ 智能提示插件;只保留一个语言服务。
|
|
104
116
|
- 不把 `compile_commands.json` 提交进仓库;它是构建产物。
|
|
105
|
-
- 切换编译器时同时改 `.clangd`、`settings.json` 和构建目录;三处不一致会让诊断指向旧代码。
|
|
117
|
+
- 切换编译器时同时改 `.clangd`、`settings.json` 和构建目录;三处不一致会让诊断指向旧代码。GCC 模式把 `MIMode` 改为 `gdb`、`miDebuggerPath` 改为 `/usr/bin/gdb`。
|
|
106
118
|
|
|
107
119
|
## 门禁分级
|
|
108
120
|
|
|
@@ -110,9 +122,9 @@ Diagnostics:
|
|
|
110
122
|
|
|
111
123
|
| 级别 | 典型检查 | 处理 |
|
|
112
124
|
| --- | --- | --- |
|
|
113
|
-
| 失败 | `
|
|
125
|
+
| 失败 | `google-*`、`readability-identifier-naming`、项目声明的致命集 | 修代码;不允许用 NOLINT 掩盖 |
|
|
114
126
|
| 失败 | 编译诊断、链接诊断、格式检查 | 直接失败 |
|
|
115
|
-
| 观察 |
|
|
127
|
+
| 观察 | 迁移期暂时无法修完的个别 `google-*` 子项 | 在项目技能里列清单、写负责人和退出条件;不默认全仓关闭 |
|
|
116
128
|
|
|
117
129
|
- 致命集宁可小、可解释,也不要把所有检查一刀切。
|
|
118
130
|
- 观察项不是免死金牌:新代码不应新增观察项,已有项只能减少。
|
|
@@ -15,6 +15,8 @@ import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
|
15
15
|
export const HOSTS = ['windows', 'linux', 'macos']
|
|
16
16
|
export const BUILD_HOSTS = ['native', 'wsl']
|
|
17
17
|
export const COMPILERS = ['clang', 'gcc']
|
|
18
|
+
export const STANDARDS = ['c++11', 'c++14', 'c++17', 'c++20', 'c++23']
|
|
19
|
+
export const DEFAULT_STANDARD = 'c++23'
|
|
18
20
|
const PROJECT_SKILL_DIR = path.join('.agents', 'skills', 'cpp-workflow-project')
|
|
19
21
|
const MAX_ASCENT = 64
|
|
20
22
|
|
|
@@ -34,8 +36,9 @@ function normalize(value) {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/**
|
|
37
|
-
* Validate the three axes and their combination.
|
|
38
|
-
*
|
|
39
|
+
* Validate the three environment axes, the language standard, and their combination.
|
|
40
|
+
* Pure: no filesystem or PATH.
|
|
41
|
+
* @returns {{ok: boolean, issues: string[], notes: string[], axes: {host?: string, build_host?: string, compiler?: string, standard?: string}}}
|
|
39
42
|
*/
|
|
40
43
|
export function validateEnvironment(value) {
|
|
41
44
|
const issues = []
|
|
@@ -53,6 +56,18 @@ export function validateEnvironment(value) {
|
|
|
53
56
|
host: normalize(value.host),
|
|
54
57
|
build_host: normalize(value.build_host),
|
|
55
58
|
compiler: normalize(value.compiler),
|
|
59
|
+
standard: normalize(value.standard),
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (axes.standard === undefined || axes.standard === null || axes.standard === '') {
|
|
63
|
+
axes.standard = DEFAULT_STANDARD
|
|
64
|
+
notes.push(`standard 未声明或为空;按默认 ${DEFAULT_STANDARD} 处理,请在 environment.json 中显式写出`)
|
|
65
|
+
} else if (Array.isArray(axes.standard)) {
|
|
66
|
+
issues.push(`standard 只能声明一个值,当前是数组 [${axes.standard.join(', ')}]`)
|
|
67
|
+
} else if (typeof axes.standard !== 'string') {
|
|
68
|
+
issues.push(`standard 必须是字符串,当前是 ${typeof axes.standard}`)
|
|
69
|
+
} else if (!STANDARDS.includes(axes.standard)) {
|
|
70
|
+
issues.push(`standard 的值 "${axes.standard}" 非法;允许:${STANDARDS.join(' / ')}`)
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
for (const [key, allowed] of [
|
|
@@ -85,12 +100,12 @@ export function validateEnvironment(value) {
|
|
|
85
100
|
}
|
|
86
101
|
|
|
87
102
|
if (axes.host === 'windows' && axes.build_host === 'native') {
|
|
88
|
-
|
|
103
|
+
issues.push('本版本不能在 Windows 原生壳里构建')
|
|
89
104
|
}
|
|
90
105
|
|
|
91
106
|
for (const key of Object.keys(value)) {
|
|
92
|
-
if (!['host', 'build_host', 'compiler'].includes(key)) {
|
|
93
|
-
notes.push(`忽略未知键 "${key}";环境只认 host / build_host / compiler`)
|
|
107
|
+
if (!['host', 'build_host', 'compiler', 'standard'].includes(key)) {
|
|
108
|
+
notes.push(`忽略未知键 "${key}";环境只认 host / build_host / compiler / standard`)
|
|
94
109
|
}
|
|
95
110
|
}
|
|
96
111
|
|
|
@@ -245,25 +260,10 @@ export function checkLive(declaration, options = {}) {
|
|
|
245
260
|
}
|
|
246
261
|
const { host, build_host: buildHost, compiler } = validation.axes
|
|
247
262
|
|
|
248
|
-
if (host === 'windows' && buildHost === 'native') {
|
|
249
|
-
return {
|
|
250
|
-
ok: false,
|
|
251
|
-
issues: [
|
|
252
|
-
'Windows 原生构建缺少 POSIX 壳;本版本没有 PowerShell 构建脚本。缺的是壳,不是编译器。请改用 WSL 并把 build_host 改成 wsl,或补一个 PowerShell 版本。',
|
|
253
|
-
],
|
|
254
|
-
notes: validation.notes,
|
|
255
|
-
checks,
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
263
|
if (buildHost === 'wsl') {
|
|
260
264
|
if (platform !== 'linux' || !isWsl(env)) {
|
|
261
265
|
issues.push('声明 build_host=wsl,但当前进程不在 WSL 内;请在 WSL 里运行 --live')
|
|
262
266
|
}
|
|
263
|
-
} else if (host === 'windows') {
|
|
264
|
-
if (platform !== 'win32') {
|
|
265
|
-
issues.push(`声明 host=windows + build_host=native,但当前平台是 ${platform};请在 Windows 上运行 --live`)
|
|
266
|
-
}
|
|
267
267
|
} else if (host === 'linux' && platform !== 'linux') {
|
|
268
268
|
issues.push(`声明 host=linux,但当前平台是 ${platform};请在 Linux 上运行 --live`)
|
|
269
269
|
} else if (host === 'macos' && platform !== 'darwin') {
|
|
@@ -358,7 +358,7 @@ export function checkLive(declaration, options = {}) {
|
|
|
358
358
|
['clang-tidy', tidyVersion],
|
|
359
359
|
]) {
|
|
360
360
|
if (version && version.major < 16) {
|
|
361
|
-
issues.push(`${role} ${versionText(version)}
|
|
361
|
+
issues.push(`${role} ${versionText(version)} 过旧;本工作流要求 >= 16`)
|
|
362
362
|
}
|
|
363
363
|
}
|
|
364
364
|
|
|
@@ -1,76 +1,78 @@
|
|
|
1
|
-
# 第 1 步:定构建
|
|
2
|
-
|
|
3
|
-
## 产出
|
|
4
|
-
|
|
5
|
-
一组 target-based 的 CMake 规则、一个固定的构建目录、一个可用的编译数据库。构建结果只取决于 `environment.json` 声明的组合,不取决于当前 shell 碰巧有什么。
|
|
6
|
-
|
|
7
|
-
```text
|
|
8
|
-
CMakeLists.txt
|
|
9
|
-
build/
|
|
10
|
-
clang/ # compiler=clang
|
|
11
|
-
compile_commands.json
|
|
12
|
-
gcc/ # compiler=gcc
|
|
13
|
-
compile_commands.json
|
|
14
|
-
compile_commands.json # 指向上面的当前数据库
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## 通用情况
|
|
18
|
-
|
|
19
|
-
先读 `environment.json
|
|
20
|
-
|
|
21
|
-
| 轴 | 取值 | 含义 |
|
|
22
|
-
| --- | --- | --- |
|
|
23
|
-
| `host` | `windows` / `linux` / `macos` | 编辑器与代理壳所在系统 |
|
|
24
|
-
| `build_host` | `native` / `wsl` | 执行编译和运行产物的环境;`native` 表示 `host` 本机,`wsl` 表示 Windows 的 WSL,且只允许 `host=windows` |
|
|
25
|
-
| `compiler` | `clang` / `gcc` | 用哪个编译器;一次只配一个 |
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
- `
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
1
|
+
# 第 1 步:定构建
|
|
2
|
+
|
|
3
|
+
## 产出
|
|
4
|
+
|
|
5
|
+
一组 target-based 的 CMake 规则、一个固定的构建目录、一个可用的编译数据库。构建结果只取决于 `environment.json` 声明的组合,不取决于当前 shell 碰巧有什么。
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
CMakeLists.txt
|
|
9
|
+
build/
|
|
10
|
+
clang/ # compiler=clang
|
|
11
|
+
compile_commands.json
|
|
12
|
+
gcc/ # compiler=gcc
|
|
13
|
+
compile_commands.json
|
|
14
|
+
compile_commands.json # 指向上面的当前数据库
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 通用情况
|
|
18
|
+
|
|
19
|
+
先读 `environment.json`。源文件清单来自 `developing-cpp` 的定边界和定实现;定构建只把它们写进 target,不重新决定库与程序的边界。三个环境轴加语言标准分别表示:
|
|
20
|
+
|
|
21
|
+
| 轴 | 取值 | 含义 |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| `host` | `windows` / `linux` / `macos` | 编辑器与代理壳所在系统 |
|
|
24
|
+
| `build_host` | `native` / `wsl` | 执行编译和运行产物的环境;`native` 表示 `host` 本机,`wsl` 表示 Windows 的 WSL,且只允许 `host=windows`;`windows` + `native` 本版本不支持 |
|
|
25
|
+
| `compiler` | `clang` / `gcc` | 用哪个编译器;一次只配一个 |
|
|
26
|
+
| `standard` | `c++11`–`c++23` | 一个工程一个语言标准;新工程默认 `c++23`,已有工程按原声明 |
|
|
27
|
+
|
|
28
|
+
环境轴为空、`standard` 非法或组合非法(如 `host=linux` + `build_host=wsl`、`host=windows` + `build_host=native`)时,停在定构建,先让用户把 `environment.json` 填对。不要替用户选 WSL、Clang 或构建目录。`windows` + `native` 只给一句「本版本不能在 Windows 原生壳里构建」,不要建议改 WSL、不要提出补 PowerShell 脚本。
|
|
29
|
+
|
|
30
|
+
构建规则:
|
|
31
|
+
|
|
32
|
+
- CMake 最低 3.20;`project(... LANGUAGES CXX)`;只有确有 C 源时才写 `LANGUAGES C CXX`。新工程默认标准 C++23;已有工程按 `environment.json` 的 `standard` 或现有 target 声明,不擅自升降。
|
|
33
|
+
- 生成器固定单配置 Ninja,不用 Ninja Multi-Config:同一源文件会写多条命令,clangd 默认只取第一条,容易读错数据库(clangd#2026);构建目录固定 `build/clang` 或 `build/gcc`。
|
|
34
|
+
- 一个 configure 只用一个编译器:`-DCMAKE_CXX_COMPILER=clang++` 或 `g++`。
|
|
35
|
+
- 程序 target 固定叫 `app`;库 target 用组件名,程序链接库。库与程序分开,不把 `main()` 编进库。
|
|
36
|
+
- 用 `target_include_directories`、`target_compile_features`、`target_link_libraries` 表达依赖;禁止全局 `include_directories()`、`add_definitions()`、`CMAKE_CXX_FLAGS` 污染所有 target。
|
|
37
|
+
- 库的公共 include 根用 `PUBLIC`;实现私有头用 `PRIVATE`;测试 target 只链接被测库的公共接口。头文件按 Google 规则从仓库根写完整路径,构建时把仓库根加入搜索路径,不要改成组件的 `include/` 根后再写裸文件名。
|
|
38
|
+
- `set(CMAKE_EXPORT_COMPILE_COMMANDS ON)`;Ninja 生成器下会产出 `compile_commands.json`。
|
|
39
|
+
- 输出目录统一:可执行文件到 `build/<compiler>/bin`,库到 `build/<compiler>/lib`;不要用源码目录当输出目录。
|
|
40
|
+
- 开启 `CMAKE_EXPORT_COMPILE_COMMANDS` 后,把 `build/<compiler>/compile_commands.json` 符号链接到 `build/compile_commands.json`,让 clangd 默认能找到当前数据库。本插件固定产出 `build/<compiler>/` 并在 `build/` 下维护链接,不生成 `out/build/`,也不把两套构建根混用。
|
|
41
|
+
- 目标标准写在 target 上:`target_compile_features(app PRIVATE cxx_std_23)`;库用 `PUBLIC` 传播标准。再加 `set_target_properties(... CXX_STANDARD 23 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)`:meta-feature 只保证“至少”,`CXX_STANDARD_REQUIRED` 防 decay,`CXX_EXTENSIONS OFF` 把 `-std=gnu++23` 收成 `-std=c++23`。configure 后读 `compile_commands.json` 的最后一个 `-std=`,必须与 `environment.json` 的 `standard` 一致。
|
|
42
|
+
- 工程确有 C 源时才写 `LANGUAGES C CXX`,并且 `CMAKE_C_COMPILER` 与 `CMAKE_CXX_COMPILER` 必须来自同一套编译器(`clang`/`clang++` 或 `gcc`/`g++`);没有 C 源时只启用 CXX。
|
|
43
|
+
- 不写 `file(GLOB ...)`;源文件显式列出,新增文件时改 CMake。
|
|
44
|
+
- 不加 `-march=native`、`-ffast-math` 等改变语义或可移植性的选项;警告选项按团队约定统一加。
|
|
45
|
+
- 配置阶段不隐式下载依赖;需要 GoogleTest 时由项目显式选择固定版本、带哈希的 `FetchContent`,或使用项目自带的 cmake 模块,只把下载用于测试依赖。
|
|
46
|
+
|
|
47
|
+
命令形状:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cmake -S . -B build/clang -G Ninja \
|
|
51
|
+
-DCMAKE_BUILD_TYPE=Debug \
|
|
52
|
+
-DCMAKE_CXX_COMPILER=clang++ \
|
|
53
|
+
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
|
54
|
+
cmake --build build/clang
|
|
55
|
+
rm -f build/compile_commands.json
|
|
56
|
+
ln -s clang/compile_commands.json build/compile_commands.json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
GCC 模式把目录和编译器换成 `build/gcc`、`g++`。工程确有 C 源时,再补 `-DCMAKE_C_COMPILER=clang` 或 `gcc`,和 C++ 编译器同属一套。每次构建都重新 configure;不要依赖上一次的缓存。
|
|
60
|
+
|
|
61
|
+
## 情况
|
|
62
|
+
|
|
63
|
+
**新工程**:从 `assets/templates/projects/` 选形态:`single` 单文件、`multi` 多文件单程序、`static-library` 静态库 + 程序、`shared-library` 动态库 + 程序。只复制目标工程缺的文件;已有的 `CMakeLists.txt`、`.clang-*`、源码不覆盖。模板里的 `{{PROJECT_NAME}}` 换成真实工程名,默认标准 C++23;四套模板已按 `__cplusplus` 条件使用 `std::format`,把 `standard`、`cxx_std_*`、`CXX_STANDARD` 和 `.clang-format` 的解析档位一起降到 C++11–C++20 后仍应能构建,降完跑 `references/standards/README.md` 的五档矩阵。模板源码是 `.cc`,头文件用路径式 `#define` 守卫;新增文件沿用 `.cc` / `.h`,已有工程保持原有扩展名。
|
|
64
|
+
|
|
65
|
+
**已有工程**:先读现有 `CMakeLists.txt`,找出全局设置、GLOB、输出目录和 target 命名;只改与当前任务相关的一处。大改前先让通过检查的项目入口跑通,保留可回退点。
|
|
66
|
+
|
|
67
|
+
**库 + 程序**:库 target 的 `PUBLIC` include 根按项目约定设置;本工作流把仓库根作为源码根,程序按 `#include "component/include/name.h"` 包含公共头,不直接包含库的 `src/`。静态库与动态库的接口相同;动态库额外设置运行时库路径。
|
|
68
|
+
|
|
69
|
+
**测试**:`enable_testing()` 放在顶层,`add_subdirectory(tests)` 在 `add_subdirectory(<component>)` 之后;测试 target 用 `add_test(NAME ... COMMAND ...)` 注册。没有测试时不要为了「看起来完整」加空测试。
|
|
70
|
+
|
|
71
|
+
**CMakePresets**:如果项目使用 preset,名称固定 `clang` / `gcc`,与构建目录一致;没有 preset 时直接用上面的命令,不要两套并存。
|
|
72
|
+
|
|
73
|
+
## 正反例指针
|
|
74
|
+
|
|
75
|
+
- 全局 include、GLOB、把 `main()` 编进库:`examples/cmake.md`。
|
|
76
|
+
- 正确的最小库 + 程序:`examples/cmake.md`「最小可用形状」。
|
|
77
|
+
- target 与目录的完整说明:`references/cmake.md`。
|
|
78
|
+
- 五档标准的下限、降档替换和工具映射:`references/standards/README.md`。
|
|
@@ -1,41 +1,43 @@
|
|
|
1
|
-
# 第 2 步:定工具配置
|
|
2
|
-
|
|
3
|
-
## 产出
|
|
4
|
-
|
|
5
|
-
工程自己的 `.clang-format`、`.clang-tidy`、`.clangd` 和编辑器推荐配置。三份配置各管一段:格式化、静态检查、语言服务,不互相复制规则。
|
|
6
|
-
|
|
7
|
-
## 通用情况
|
|
8
|
-
|
|
9
|
-
- 工程拥有配置:`.clang-format`、`.clang-tidy`、`.clangd`、`.vscode/` 放在工程根;不要依赖用户主目录或插件目录里的同名文件。
|
|
10
|
-
- 只复制缺失的文件。已有配置先读再改,不覆盖;需要合并时逐项说明理由。
|
|
11
|
-
- 工具角色固定:`clang-format` 管排版,`clang-tidy` 管静态诊断,`clangd` 管补全/跳转/诊断;无论 `compiler` 是 clang 还是 gcc,这三件都用 Clang 工具链。
|
|
12
|
-
- 版本要求见 `references/environment.md`:Clang 模式要求 `clang++`、`clang-format`、`clang-tidy`、`clangd` 同一 LLVM 主版本;GCC 模式要求 `clang-format` / `clang-tidy` ≥ 16,`clangd` 只要求可用。
|
|
13
|
-
- `.clangd` 的 `CompilationDatabase` 指向 `build/<compiler
|
|
14
|
-
- `--query-driver` 是 clangd 的命令行参数,写在 `.vscode/settings.json` 的 `clangd.arguments` 里,不是 `.clangd` 的 YAML 键。它告诉 clangd 允许执行哪个编译器驱动来取系统头路径;路径写绝对路径,并与 `environment.json` 的编译器一致。
|
|
15
|
-
-
|
|
16
|
-
- `.clang-format`
|
|
17
|
-
- `.clang-tidy`
|
|
18
|
-
- `.
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
1
|
+
# 第 2 步:定工具配置
|
|
2
|
+
|
|
3
|
+
## 产出
|
|
4
|
+
|
|
5
|
+
工程自己的 `.clang-format`、`.clang-tidy`、`.clangd` 和编辑器推荐配置。三份配置各管一段:格式化、静态检查、语言服务,不互相复制规则。
|
|
6
|
+
|
|
7
|
+
## 通用情况
|
|
8
|
+
|
|
9
|
+
- 工程拥有配置:`.clang-format`、`.clang-tidy`、`.clangd`、`.vscode/` 放在工程根;不要依赖用户主目录或插件目录里的同名文件。
|
|
10
|
+
- 只复制缺失的文件。已有配置先读再改,不覆盖;需要合并时逐项说明理由。
|
|
11
|
+
- 工具角色固定:`clang-format` 管排版,`clang-tidy` 管静态诊断,`clangd` 管补全/跳转/诊断;无论 `compiler` 是 clang 还是 gcc,这三件都用 Clang 工具链。
|
|
12
|
+
- 版本要求见 `references/environment.md`:Clang 模式要求 `clang++`、`clang-format`、`clang-tidy`、`clangd` 同一 LLVM 主版本;GCC 模式要求 `clang-format` / `clang-tidy` ≥ 16,`clangd` 只要求可用。
|
|
13
|
+
- `.clangd` 的 `CompilationDatabase` 指向 `build/<compiler>`;切换编译器时同步改,不能留旧目录。**不要写 `-std`**:它会覆盖 `compile_commands.json`,把 C++23 工程降成旧标准;标准只由构建声明和编译数据库决定。
|
|
14
|
+
- `--query-driver` 是 clangd 的命令行参数,写在 `.vscode/settings.json` 的 `clangd.arguments` 里,不是 `.clangd` 的 YAML 键。它告诉 clangd 允许执行哪个编译器驱动来取系统头路径;路径写绝对路径,并与 `environment.json` 的编译器一致。
|
|
15
|
+
- 首次复制时按轴替换三处:`compiler=clang` 用 `CompilationDatabase: build/clang`、`--query-driver=/usr/bin/clang++` 和 `cmake.debugConfig` 的 `MIMode: lldb` / `miDebuggerPath: /usr/bin/lldb`;`compiler=gcc` 用 `build/gcc`、`/usr/bin/g++` 和 `MIMode: gdb` / `/usr/bin/gdb`。只复制模板而不改这三处,GCC 模式会指向错误的数据库、驱动或调试器。原工程已有的 `.clangd` 不覆盖;要改先征得同意。
|
|
16
|
+
- `.clang-format` 只保留 `Language: Cpp`、`BasedOnStyle: Google`、`Standard: Latest`(clang-format 21/22 不接受 `c++23`)。列宽 80、每级 2 空格、不用 tab、包含顺序都取 Google 预设;不要覆盖 `ColumnLimit`、`TabWidth`、`IncludeCategories` 或指针对齐。需要新规则时先改 `references/google-cpp-style.md` 并说明理由。
|
|
17
|
+
- `.clang-tidy` 用 `Checks: '-*, google-*, readability-identifier-naming'`,保留 `WarningsAsErrors: '*'` 和 `FormatStyle: file`。`google-*` 覆盖 Google 风格能静态检查的部分;`readability-identifier-naming` 只配项目确实统一的命名项:类型/枚举/别名/模板参数 PascalCase,变量/参数/成员 snake_case,类成员尾随 `_`,结构体成员不尾随,常量 `k` + PascalCase。不要设 `FunctionCase`,Google 允许 `count()` / `set_count()` 这类访问器;不要重新打开 `cppcoreguidelines-*` 整包或 `portability-avoid-pragma-once`。
|
|
18
|
+
- `.clang-tidy` 关闭项和例外必须写理由;不要借 `-*` 之后再打开 `cppcoreguidelines-*` 这类非 Google 整族检查。
|
|
19
|
+
- `.vscode/extensions.json` 推荐 clangd、CMake Tools 与 C/C++ 扩展;`.vscode/settings.json` 固定 clangd 参数、CMake 构建目录和 `cmake.debugConfig`。配置、构建、运行和调试只从 CMake Tools 进入,不写 `tasks.json` 或 `launch.json`;C/C++ 扩展只作为 CMake 快速调试的后端,IntelliSense 关闭,避免和 clangd 并行。配置注释用 JSONC 的 `//`,贴在被解释的键上方。
|
|
20
|
+
- 配置注释写「为什么这样设」,不写「这一项是什么」;不写策略头、不指向文档路径。
|
|
21
|
+
- 格式化与静态检查只扫描项目源码:`src/`、`include/`、`apps/`、`tests/` 等实际存在的源码根;不扫描 `build/`、第三方目录、生成文件。
|
|
22
|
+
- `clang-tidy` 用 `-p build/<compiler>` 读取编译数据库,`--header-filter` 只列项目根下的顶层目录,避免把第三方头纳入;不要加 `--system-headers`,也不要用 clang-tidy 19 才加入、16 没有的 `--exclude-header-filter`。
|
|
23
|
+
- 格式化用 `--dry-run --Werror` 做检查;需要自动修复时单独运行 `-i`,不要让构建脚本悄悄改源码。
|
|
24
|
+
- 工程模板里不预置 `compile_commands.json`;它由定构建的 configure 生成,是构建产物。
|
|
25
|
+
|
|
26
|
+
## 情况
|
|
27
|
+
|
|
28
|
+
**新工程**:从 `assets/config/` 复制 `.clang-format`、`.clang-tidy`、`.clangd` 和 `.vscode/` 下的 `extensions.json`、`settings.json`,按编译器的映射改 `.clangd` 的编译数据库目录、`.vscode/settings.json` 的 `--query-driver` 路径和 `cmake.debugConfig` 的调试后端。不要复制 `build/`。
|
|
29
|
+
|
|
30
|
+
**已有工程**:新工程默认 C++23;已有工程按 `environment.json` 的 `standard` 对齐 CMake target 与 `.clang-format`,不要只改一处。先跑一次 `clang-format --dry-run --Werror` 和 `clang-tidy`,看现有配置实际报什么;只改导致当前失败或与声明环境冲突的项。不要借机重排全工程格式。
|
|
31
|
+
|
|
32
|
+
**换编译器**:改 `.clangd` 的 `CompilationDatabase`,改 `--query-driver` 指向的编译器,清理旧构建目录;不要同时保留两套 clangd 配置。
|
|
33
|
+
|
|
34
|
+
**GCC 模式**:`clangd` 仍可工作,但系统头来自 GCC;`--query-driver` 指向 `g++`。`clang-format` / `clang-tidy` 仍是 Clang 工具,版本要求不因编译器是 GCC 而降低。
|
|
35
|
+
|
|
36
|
+
**共享库**:静态检查不因链接方式改变;运行时库路径在定构建的 CMake 里设置,不要写进 clang 配置。
|
|
37
|
+
|
|
38
|
+
## 正反例指针
|
|
39
|
+
|
|
40
|
+
- `.clangd` 指错编译数据库、`query-driver` 写进 YAML:`examples/tooling.md`。
|
|
41
|
+
- 配置文件堆策略头、关闭检查不写理由:`examples/tooling.md`「配置注释」。
|
|
42
|
+
- 工具调用与头文件过滤:`references/static-analysis.md`。
|
|
43
|
+
- 每个标准对应的 clang-format 档位与 `.clangd` 读库规则:`references/standards/README.md`。
|