@chengzhao-dev/dsh-cpp-workflow 0.0.0-stage → 0.1.1

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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +106 -0
  3. package/README.md +105 -2
  4. package/cordis.patch.yml +11 -0
  5. package/icon.svg +7 -0
  6. package/lib/index.js +203 -0
  7. package/lib/workspace.js +168 -0
  8. package/locale/en.json +6 -0
  9. package/locale/zh.json +6 -0
  10. package/package.json +80 -4
  11. package/skills/building-cpp/SKILL.md +44 -0
  12. package/skills/building-cpp/assets/cmake/applying-warnings.cmake +10 -0
  13. package/skills/building-cpp/assets/cmake/fetching-googletest.cmake +15 -0
  14. package/skills/building-cpp/assets/cmake/setting-rpath.cmake +8 -0
  15. package/skills/building-cpp/assets/config/.clang-format +40 -0
  16. package/skills/building-cpp/assets/config/.clang-tidy +92 -0
  17. package/skills/building-cpp/assets/config/.clangd +12 -0
  18. package/skills/building-cpp/assets/config/.vscode/extensions.json +6 -0
  19. package/skills/building-cpp/assets/config/.vscode/settings.json +34 -0
  20. package/skills/building-cpp/assets/templates/projects/common/running-build.sh +152 -0
  21. package/skills/building-cpp/assets/templates/projects/multi/CMakeLists.txt +18 -0
  22. package/skills/building-cpp/assets/templates/projects/multi/include/greeting.h +10 -0
  23. package/skills/building-cpp/assets/templates/projects/multi/src/greeting.cpp +13 -0
  24. package/skills/building-cpp/assets/templates/projects/multi/src/main.cpp +8 -0
  25. package/skills/building-cpp/assets/templates/projects/shared-library/CMakeLists.txt +24 -0
  26. package/skills/building-cpp/assets/templates/projects/shared-library/greeting/CMakeLists.txt +5 -0
  27. package/skills/building-cpp/assets/templates/projects/shared-library/greeting/include/greeting.h +10 -0
  28. package/skills/building-cpp/assets/templates/projects/shared-library/greeting/src/greeting.cpp +13 -0
  29. package/skills/building-cpp/assets/templates/projects/shared-library/src/main.cpp +8 -0
  30. package/skills/building-cpp/assets/templates/projects/single/CMakeLists.txt +14 -0
  31. package/skills/building-cpp/assets/templates/projects/single/src/main.cpp +9 -0
  32. package/skills/building-cpp/assets/templates/projects/static-library/CMakeLists.txt +18 -0
  33. package/skills/building-cpp/assets/templates/projects/static-library/greeting/CMakeLists.txt +5 -0
  34. package/skills/building-cpp/assets/templates/projects/static-library/greeting/include/greeting.h +10 -0
  35. package/skills/building-cpp/assets/templates/projects/static-library/greeting/src/greeting.cpp +13 -0
  36. package/skills/building-cpp/assets/templates/projects/static-library/src/main.cpp +8 -0
  37. package/skills/building-cpp/examples/cmake.md +150 -0
  38. package/skills/building-cpp/examples/environment.md +125 -0
  39. package/skills/building-cpp/examples/tooling.md +155 -0
  40. package/skills/building-cpp/references/build-script.md +63 -0
  41. package/skills/building-cpp/references/cmake.md +168 -0
  42. package/skills/building-cpp/references/environment.md +104 -0
  43. package/skills/building-cpp/references/linking.md +101 -0
  44. package/skills/building-cpp/references/static-analysis.md +136 -0
  45. package/skills/building-cpp/scripts/checking-environment.mjs +498 -0
  46. package/skills/building-cpp/steps/01-build.md +76 -0
  47. package/skills/building-cpp/steps/02-tooling.md +41 -0
  48. package/skills/building-cpp/steps/03-check.md +60 -0
  49. package/skills/developing-cpp/SKILL.md +42 -0
  50. package/skills/developing-cpp/examples/comments.md +231 -0
  51. package/skills/developing-cpp/examples/exceptions.md +134 -0
  52. package/skills/developing-cpp/examples/naming.md +157 -0
  53. package/skills/developing-cpp/examples/structure.md +79 -0
  54. package/skills/developing-cpp/references/comments.md +123 -0
  55. package/skills/developing-cpp/references/declaration-order.md +97 -0
  56. package/skills/developing-cpp/references/exceptions.md +79 -0
  57. package/skills/developing-cpp/references/glossary.md +88 -0
  58. package/skills/developing-cpp/references/google-cpp-style.md +109 -0
  59. package/skills/developing-cpp/references/language.md +119 -0
  60. package/skills/developing-cpp/references/layout.md +73 -0
  61. package/skills/developing-cpp/references/naming.md +62 -0
  62. package/skills/developing-cpp/references/performance.md +82 -0
  63. package/skills/developing-cpp/references/project-design.md +79 -0
  64. package/skills/developing-cpp/references/standard-library.md +100 -0
  65. package/skills/developing-cpp/references/types.md +147 -0
  66. package/skills/developing-cpp/steps/01-behavior.md +36 -0
  67. package/skills/developing-cpp/steps/02-boundary.md +40 -0
  68. package/skills/developing-cpp/steps/03-declaration.md +32 -0
  69. package/skills/developing-cpp/steps/04-implementation.md +33 -0
  70. package/templates/cpp-workflow-project/SKILL.md +49 -0
  71. package/templates/cpp-workflow-project/environment.json +5 -0
  72. package/templates/cpp-workflow-project/stages/stage-table.md +4 -0
@@ -0,0 +1,18 @@
1
+ cmake_minimum_required(VERSION 3.20)
2
+ project({{PROJECT_NAME}} VERSION 0.1.0 LANGUAGES CXX)
3
+
4
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
5
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
6
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
7
+
8
+ enable_testing()
9
+
10
+ add_subdirectory(greeting)
11
+
12
+ add_executable(app src/main.cpp)
13
+ target_compile_features(app PRIVATE cxx_std_20)
14
+ set_target_properties(app PROPERTIES CXX_EXTENSIONS OFF)
15
+ target_link_libraries(app PRIVATE greeting)
16
+ target_compile_options(app PRIVATE -Wall -Wextra -Werror)
17
+
18
+ add_test(NAME app_smoke COMMAND app)
@@ -0,0 +1,5 @@
1
+ add_library(greeting STATIC src/greeting.cpp)
2
+ target_include_directories(greeting PUBLIC include)
3
+ target_compile_features(greeting PUBLIC cxx_std_20)
4
+ set_target_properties(greeting PROPERTIES CXX_EXTENSIONS OFF)
5
+ target_compile_options(greeting PRIVATE -Wall -Wextra -Werror -Wold-style-cast -Wshadow)
@@ -0,0 +1,10 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <string_view>
5
+
6
+ namespace greeting {
7
+
8
+ [[nodiscard]] std::string MakeGreeting(std::string_view name);
9
+
10
+ } // namespace greeting
@@ -0,0 +1,13 @@
1
+ #include "greeting.h"
2
+
3
+ #include <format>
4
+ #include <string>
5
+ #include <string_view>
6
+
7
+ namespace greeting {
8
+
9
+ std::string MakeGreeting(std::string_view name) {
10
+ return std::format("Hello, {}!", name);
11
+ }
12
+
13
+ } // namespace greeting
@@ -0,0 +1,8 @@
1
+ #include <iostream>
2
+
3
+ #include "greeting.h"
4
+
5
+ int main() {
6
+ std::cout << greeting::MakeGreeting("C++20") << '\n';
7
+ return 0;
8
+ }
@@ -0,0 +1,150 @@
1
+ # 正反例:CMake
2
+
3
+ ## 最小可用形状
4
+
5
+ ```cmake
6
+ cmake_minimum_required(VERSION 3.20)
7
+ project(greeter VERSION 0.1.0 LANGUAGES CXX)
8
+
9
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
10
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
11
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
12
+
13
+ add_library(greeting STATIC greeting/src/greeting.cpp)
14
+ target_include_directories(greeting PUBLIC greeting/include)
15
+ target_compile_features(greeting PUBLIC cxx_std_20)
16
+ set_target_properties(greeting PROPERTIES CXX_EXTENSIONS OFF)
17
+ target_compile_options(greeting PRIVATE -Wall -Wextra -Werror)
18
+
19
+ add_executable(app src/main.cpp)
20
+ target_compile_features(app PRIVATE cxx_std_20)
21
+ set_target_properties(app PROPERTIES CXX_EXTENSIONS OFF)
22
+ target_link_libraries(app PRIVATE greeting)
23
+ ```
24
+
25
+ 程序只写 `#include "greeting.h"`;公共 include 根由库的 `PUBLIC` 传过来。
26
+
27
+ ## 全局 include
28
+
29
+ **差**:
30
+
31
+ ```cmake
32
+ include_directories(include greeting/include)
33
+ add_executable(app src/main.cpp greeting/src/greeting.cpp)
34
+ ```
35
+
36
+ 问题:所有 target 共享 include,边界消失;程序直接编译库源码,测试无法只链接库。
37
+
38
+ **好**:
39
+
40
+ ```cmake
41
+ target_include_directories(greeting PUBLIC greeting/include)
42
+ target_link_libraries(app PRIVATE greeting)
43
+ ```
44
+
45
+ ## GLOB
46
+
47
+ **差**:
48
+
49
+ ```cmake
50
+ file(GLOB SOURCES "src/*.cpp")
51
+ add_executable(app ${SOURCES})
52
+ ```
53
+
54
+ 新增文件不触发重新配置;不同机器上的文件集合可能不同。
55
+
56
+ **好**:
57
+
58
+ ```cmake
59
+ add_executable(app
60
+ src/main.cpp
61
+ src/task_list.cpp
62
+ src/task_parser.cpp
63
+ )
64
+ ```
65
+
66
+ 显式列表,新增文件时改 CMake;diff 能看出变化。
67
+
68
+ ## 把 `main()` 编进库
69
+
70
+ **差**:
71
+
72
+ ```cmake
73
+ add_library(core STATIC src/main.cpp src/core.cpp)
74
+ add_executable(app src/main.cpp) # 重复定义
75
+ ```
76
+
77
+ **好**:
78
+
79
+ ```cmake
80
+ add_library(core STATIC src/core.cpp)
81
+ add_executable(app src/main.cpp)
82
+ target_link_libraries(app PRIVATE core)
83
+ ```
84
+
85
+ 库不依赖 `main()`;测试链接库时不会碰到入口。
86
+
87
+ ## 编译数据库
88
+
89
+ **差**:
90
+
91
+ ```cmake
92
+ # 没开导出
93
+ ```
94
+
95
+ ```bash
96
+ clang-tidy src/main.cpp # 没有编译参数,头路径和标准都不对
97
+ ```
98
+
99
+ **好**:
100
+
101
+ ```cmake
102
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
103
+ ```
104
+
105
+ ```bash
106
+ cmake -S . -B build/clang -G Ninja -DCMAKE_CXX_COMPILER=clang++
107
+ rm -f build/compile_commands.json
108
+ ln -s clang/compile_commands.json build/compile_commands.json
109
+ clang-tidy -p build/clang src/main.cpp
110
+ ```
111
+
112
+ ## 共享库运行时路径
113
+
114
+ **差**:
115
+
116
+ ```bash
117
+ LD_LIBRARY_PATH=build/clang/lib ./build/clang/bin/app # 每次运行都要包一层
118
+ ```
119
+
120
+ **好**:
121
+
122
+ ```cmake
123
+ add_library(greeting SHARED greeting/src/greeting.cpp)
124
+ set_target_properties(greeting PROPERTIES
125
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
126
+
127
+ add_executable(app src/main.cpp)
128
+ target_link_libraries(app PRIVATE greeting)
129
+ if(APPLE)
130
+ set_target_properties(app PROPERTIES BUILD_RPATH "@loader_path/../lib")
131
+ else()
132
+ set_target_properties(app PROPERTIES BUILD_RPATH "$ORIGIN/../lib")
133
+ endif()
134
+ ```
135
+
136
+ 从 `build/<compiler>/bin/app` 直接启动即可找到同级 `../lib` 下的共享库;安装场景另配 RPATH。
137
+
138
+ ## 输出目录
139
+
140
+ **差**:可执行文件生成在源码根,`git status` 出现 `app`、`*.o`。
141
+
142
+ **好**:
143
+
144
+ ```cmake
145
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
146
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
147
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
148
+ ```
149
+
150
+ 构建产物全在 `build/<compiler>/` 下。
@@ -0,0 +1,125 @@
1
+ # 正反例:环境组合
2
+
3
+ ## 合法声明
4
+
5
+ ```json
6
+ {
7
+ "host": "windows",
8
+ "build_host": "wsl",
9
+ "compiler": "clang"
10
+ }
11
+ ```
12
+
13
+ 在 WSL 内执行 `running-build.sh clang`;构建目录 `build/clang`。
14
+
15
+ ```json
16
+ {
17
+ "host": "linux",
18
+ "build_host": "native",
19
+ "compiler": "gcc"
20
+ }
21
+ ```
22
+
23
+ 在 Linux 上执行 `running-build.sh gcc`;构建目录 `build/gcc`。
24
+
25
+ ## 非法声明
26
+
27
+ **轴为空**:
28
+
29
+ ```json
30
+ {
31
+ "host": "linux",
32
+ "build_host": "",
33
+ "compiler": "gcc"
34
+ }
35
+ ```
36
+
37
+ 声明校验以退出码 2 失败,不查找 `g++`。先让用户填 `build_host`。
38
+
39
+ **组合非法**:
40
+
41
+ ```json
42
+ {
43
+ "host": "linux",
44
+ "build_host": "wsl",
45
+ "compiler": "clang"
46
+ }
47
+ ```
48
+
49
+ WSL 只对 `host=windows` 合法;不要通过改 `host` 来绕过,先确认工程到底跑在哪。
50
+
51
+ **同时写两个编译器**:
52
+
53
+ ```json
54
+ {
55
+ "host": "linux",
56
+ "build_host": "native",
57
+ "compiler": ["clang", "gcc"]
58
+ }
59
+ ```
60
+
61
+ 一个 configure 只允许一个编译器;拆成两次声明或两个工程。
62
+
63
+ ## Windows 原生
64
+
65
+ ```json
66
+ {
67
+ "host": "windows",
68
+ "build_host": "native",
69
+ "compiler": "clang"
70
+ }
71
+ ```
72
+
73
+ 声明合法,但本版本没有 PowerShell 构建脚本。`--live` 输出类似:
74
+
75
+ ```text
76
+ 声明合法,但 Windows 原生构建缺少 POSIX 构建脚本;缺的是 shell,不是编译器。
77
+ ```
78
+
79
+ 不要把 `build_host` 改成 `wsl` 来「让它过」;要么补脚本,要么换到 WSL 并更新声明。
80
+
81
+ ## GCC 模式不比较 GCC 主版本
82
+
83
+ ```text
84
+ g++ 14.1.0
85
+ clang-format 18.1.8
86
+ clang-tidy 18.1.8
87
+ clangd 18.1.8
88
+ ```
89
+
90
+ 通过:检查器只要求 `g++` 是真的 GCC,`clang-format` / `clang-tidy` ≥ 16,`clangd` 可用。不要拿 GCC 的主版本去要求 Clang 工具,也不要因为版本号不同就换成一套不存在的 `gcc-format`。若 GCC 的标准库太旧、`<format>` 不可用,升级工具链,而不是改检查器。
91
+
92
+ ## macOS 的 `g++` 别名
93
+
94
+ ```json
95
+ {
96
+ "host": "macos",
97
+ "build_host": "native",
98
+ "compiler": "gcc"
99
+ }
100
+ ```
101
+
102
+ `/usr/bin/g++` 实际是 Apple clang 的别名;`--live` 应报告「声明的 g++ 实际是 Apple clang」。安装真正的 GCC(如 Homebrew `gcc`)并把 `g++` 指向它,或把声明改成 `compiler=clang`。
103
+
104
+ ## 版本不一致
105
+
106
+ ```text
107
+ clang++ 18.1.8
108
+ clang-format 16.0.6
109
+ clang-tidy 16.0.6
110
+ clangd 16.0.6
111
+ ```
112
+
113
+ clang 模式要求四者同主版本;这里 18 与 16 不一致,`--live` 失败。统一到同一 LLVM 发行版,不要只升级编译器。
114
+
115
+ ## 声明校验与活动校验
116
+
117
+ ```bash
118
+ # CI / Windows 开发机:只读声明,不需要工具链
119
+ node scripts/checking-environment.mjs --project .
120
+
121
+ # build host 上:核对构建宿主、PATH 和版本
122
+ node scripts/checking-environment.mjs --project . --live
123
+ ```
124
+
125
+ 不带 `--live` 时永远不探测 PATH;不要把活动校验塞进每次构建,构建脚本已经隐含了工具存在性。
@@ -0,0 +1,155 @@
1
+ # 正反例:工具配置
2
+
3
+ ## `query-driver` 放错位置
4
+
5
+ **差**:
6
+
7
+ ```yaml
8
+ # .clangd
9
+ CompileFlags:
10
+ CompilationDatabase: build/clang
11
+ Add:
12
+ - --query-driver=/usr/bin/clang++
13
+ ```
14
+
15
+ `--query-driver` 是 clangd 的命令行参数,不是 `.clangd` 的 YAML 键;写在这里不会生效。
16
+
17
+ **好**:
18
+
19
+ ```yaml
20
+ # .clangd
21
+ CompileFlags:
22
+ CompilationDatabase: build/clang
23
+ ```
24
+
25
+ ```jsonc
26
+ // .vscode/settings.json
27
+ {
28
+ "clangd.arguments": [
29
+ "--query-driver=/usr/bin/clang++",
30
+ "--header-insertion=never",
31
+ "--background-index"
32
+ ]
33
+ }
34
+ ```
35
+
36
+ ## 编译数据库指错目录
37
+
38
+ **差**:
39
+
40
+ ```yaml
41
+ CompileFlags:
42
+ CompilationDatabase: build/clang # 项目已切到 GCC,这里仍读 clang 的数据库
43
+ ```
44
+
45
+ **好**:
46
+
47
+ ```yaml
48
+ CompileFlags:
49
+ CompilationDatabase: build/gcc
50
+ ```
51
+
52
+ `.clangd` 的目录必须与 `environment.json` 的 `compiler` 一致;默认 clang 用 `build/clang`,切换 GCC 时改成 `build/gcc`,不要两套配置并存。
53
+
54
+ ## 配置文件堆策略头
55
+
56
+ **差**:
57
+
58
+ ```yaml
59
+ # 本项目遵循 Google C++ Style Guide,详见 docs/...
60
+ # 所有检查必须通过,禁止 NOLINT,禁止 ...
61
+ ColumnLimit: 100
62
+ ```
63
+
64
+ **好**:
65
+
66
+ ```yaml
67
+ # 100 列:模板和格式化串在 80 列下换行过碎。
68
+ ColumnLimit: 100
69
+ ```
70
+
71
+ 配置注释解释取值,不重复策略;策略在技能文档里。
72
+
73
+ ## 整族关闭检查
74
+
75
+ **差**:
76
+
77
+ ```yaml
78
+ Checks: >
79
+ -*,
80
+ bugprone-*
81
+ ```
82
+
83
+ 只留一族,其他全关,且没有理由。
84
+
85
+ **好**:
86
+
87
+ ```yaml
88
+ Checks: >
89
+ -*,
90
+ clang-analyzer-*,
91
+ bugprone-*,
92
+ cppcoreguidelines-*,
93
+ google-*,
94
+ modernize-*,
95
+ performance-*,
96
+ readability-*
97
+ CheckOptions:
98
+ # 团队用 100 列,tidy 的列宽判断跟随 clang-format。
99
+ readability-identifier-length.MinimumVariableNameLength: 2
100
+ ```
101
+
102
+ 保留主体;关闭项逐条写理由。
103
+
104
+ ## tidy 扫描系统头
105
+
106
+ **差**:
107
+
108
+ ```bash
109
+ clang-tidy -p build/clang --system-headers src/main.cpp
110
+ ```
111
+
112
+ 系统头也参与诊断,出现大量第三方告警。
113
+
114
+ **好**:
115
+
116
+ ```bash
117
+ clang-tidy -p build/clang --header-filter="^$(pwd -P)/(include|src)/" \
118
+ --warnings-as-errors='*' src/main.cpp
119
+ ```
120
+
121
+ `--header-filter` 只列项目顶层目录,避免把第三方头纳入;系统头默认排除。工程有别的顶层目录时按实际替换。
122
+
123
+ ## 构建脚本里自动格式化
124
+
125
+ **差**:
126
+
127
+ ```bash
128
+ clang-format -i src/*.cpp # 构建时悄悄改源码
129
+ ```
130
+
131
+ **好**:
132
+
133
+ ```bash
134
+ clang-format --dry-run --Werror "${sources[@]}" # 只检查
135
+ ```
136
+
137
+ 需要自动修复时单独运行 `clang-format -i`,由人确认 diff。
138
+
139
+ ## 版本混装
140
+
141
+ **差**:
142
+
143
+ ```text
144
+ clang++ 18, clang-format 17, clangd 16
145
+ ```
146
+
147
+ 格式化与诊断不同版本,CI 与本地结果不一致。
148
+
149
+ **好**:
150
+
151
+ ```text
152
+ clang++ 18.1.8, clang-format 18.1.8, clang-tidy 18.1.8, clangd 18.1.8
153
+ ```
154
+
155
+ 同主版本;`--live` 会核对。Apple Clang 与 Homebrew 工具不同版本时,仍按同一 LLVM 主版本要求处理,不要强行降级或改声明绕过。
@@ -0,0 +1,63 @@
1
+ # 构建脚本
2
+
3
+ `assets/templates/projects/common/running-build.sh` 是 POSIX build-host 脚本,适用于 Linux、macOS 和 Windows + WSL。Windows 原生组合(`build_host=native`)本版本没有 PowerShell 版本;这是已知缺口,不是编译器问题。
4
+
5
+ ## 用法
6
+
7
+ ```bash
8
+ ./running-build.sh clang
9
+ ./running-build.sh gcc
10
+ ```
11
+
12
+ - 参数是编译器名,只接受 `clang` / `gcc`;省略时默认 `clang`。
13
+ - 脚本以自身所在目录为工程根;把它放在工程根,从其他目录调用时会先 `cd` 到脚本目录。
14
+ - 构建目录由参数决定:`build/clang` 或 `build/gcc`;不要用环境变量临时改目录。
15
+ - 脚本不安装依赖、不下载工具、不改 PATH;缺工具时让命令失败,由 `building-cpp` 的通过检查分诊。
16
+
17
+ ## 结构
18
+
19
+ 1. **shebang + 文件头**:说明用途、支持的 build host、参数。
20
+ 2. **严格模式与目录**:`set -euo pipefail`;`cd "$(dirname "$0")"`;`readonly BUILD_DIR`、`readonly APP_NAME="app"`。
21
+ 3. **输出辅助**:`header()` 打印阶段名,`err()` 打印到 stderr;`trap ERR` 打印失败命令。
22
+ 4. **configure**:每次运行都重新 configure,不复用缓存;传 `-G Ninja`、`-DCMAKE_BUILD_TYPE=Debug`、`-DCMAKE_C_COMPILER`、`-DCMAKE_CXX_COMPILER`、`-DCMAKE_EXPORT_COMPILE_COMMANDS=ON`。C 与 C++ 使用同一套编译器;没有 C 语言的工程会忽略 C 编译器设置。
23
+ 5. **build**:`cmake --build "$BUILD_DIR"`。
24
+ 6. **编译数据库链接**:先 `rm -f build/compile_commands.json`,再 `ln -s "${COMPILER}/compile_commands.json" build/compile_commands.json`;不用 `ln -n`,它在 BSD/macOS 上不可移植。
25
+ 7. **format**:收集项目源码,`clang-format --dry-run --Werror`;没有源文件时跳过。
26
+ 8. **tidy**:`clang-tidy -p "$BUILD_DIR" --warnings-as-errors='*'` 扫描项目源文件;`--header-filter` 由脚本从项目根和顶层目录生成,绝对路径和相对路径都只放行项目自身头文件。不要用 clang-tidy 19 才加入的 `--exclude-header-filter`,最低支持版本是 16。
27
+ 9. **test**:`ctest --test-dir "$BUILD_DIR" --output-on-failure`;没有测试时 CTest 成功。
28
+ 10. **run**:`(cd "$BUILD_DIR/bin" && "./$APP_NAME")`;共享库的运行时路径由定构建的 CMake RPATH 负责,不在脚本里设全局 `LD_LIBRARY_PATH`。
29
+
30
+ 最后一行是 `main "$@"`;函数定义在 `main()` 之前,`set` / `readonly` 在最前。
31
+
32
+ ## 关键约束
33
+
34
+ - 只用 POSIX shell + Bash 数组;不要依赖 `mapfile`(macOS 自带 Bash 3.2 没有)。
35
+ - 路径含空格时全部加引号;`find -print0` 配 `read -d ''`。
36
+ - `set -u` 下空数组展开会报错;先判 `${#sources[@]}` 再传给工具。
37
+ - 不把 `clang-format -i` 放进脚本;检查阶段只读。
38
+ - 不在脚本里设全局 `LD_LIBRARY_PATH`;共享库的运行时路径由 CMake 的 RPATH 设置。
39
+ - 不 `sudo`、不 `apt install`、不 `pip install`。
40
+ - 失败时保留原始命令输出;不要在脚本里 `2>/dev/null` 吞掉诊断。
41
+ - 脚本自身用 `bash -n` 检查语法;文件权限保持可执行。
42
+
43
+ ## 失败分诊
44
+
45
+ | 输出 | 先看 | 回到 |
46
+ | --- | --- | --- |
47
+ | `CMake Error ... CXX compiler` | `environment.json`、`--live` | `building-cpp` 的定构建 / 通过检查 |
48
+ | `ninja: error: ... missing and no known rule` | 源文件是否在 CMake 中列出 | 定构建 |
49
+ | `fatal error: ... No such file` | `target_include_directories` | 定构建 |
50
+ | `undefined reference` | `target_link_libraries`、库 target 名 | 定构建 |
51
+ | `clang-format` 差异 | 源码排版 | 定工具配置 |
52
+ | `clang-tidy` 命名/类型诊断 | 声明或实现 | `developing-cpp` 的定声明 / 定实现 |
53
+ | `CTest` 失败 | 测试断言、行为句 | `developing-cpp` 的定行为 / 定实现 |
54
+ | 运行时报找不到 `.so` | RPATH / `LD_LIBRARY_PATH` | 定构建 |
55
+
56
+ ## 验收
57
+
58
+ - `bash -n running-build.sh` 通过。
59
+ - 在声明的 build host 上,`./running-build.sh clang` 与 `./running-build.sh gcc` 都能从 configure 走到 run。
60
+ - 从工程根直接 `./build/clang/bin/app` 能启动(共享库场景由 RPATH 保证)。
61
+ - 切换编译器后 `build/compile_commands.json` 指向新数据库。
62
+ - 调用者的 `LD_LIBRARY_PATH` 在脚本结束后不变。
63
+ - Windows 原生:没有脚本时明确报告缺口,不伪造通过。