@chengzhao-dev/dsh-cpp-workflow 0.2.0 → 0.3.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.
- package/README.en.md +7 -5
- package/README.md +7 -5
- package/lib/workspace.js +1 -56
- package/package.json +3 -2
- package/skills/building-cpp/SKILL.md +4 -2
- package/skills/building-cpp/assets/config/.clang-format +2 -0
- package/skills/building-cpp/assets/config/.clang-tidy +1 -0
- package/skills/building-cpp/assets/templates/projects/multi/CMakeLists.txt +2 -2
- package/skills/building-cpp/assets/templates/projects/shared-library/CMakeLists.txt +1 -1
- package/skills/building-cpp/assets/templates/projects/shared-library/greeting/CMakeLists.txt +1 -1
- package/skills/building-cpp/assets/templates/projects/single/CMakeLists.txt +1 -1
- package/skills/building-cpp/assets/templates/projects/static-library/CMakeLists.txt +1 -1
- package/skills/building-cpp/assets/templates/projects/static-library/greeting/CMakeLists.txt +1 -1
- package/skills/building-cpp/examples/cmake.md +15 -15
- package/skills/building-cpp/examples/tooling.md +3 -3
- package/skills/building-cpp/references/cmake.md +6 -6
- package/skills/building-cpp/references/encoding.md +49 -0
- package/skills/building-cpp/references/linking.md +6 -6
- package/skills/building-cpp/references/standards/c++23/README.md +1 -1
- package/skills/building-cpp/references/static-analysis.md +3 -3
- package/skills/building-cpp/scripts/checking-encoding.mjs +241 -0
- package/skills/building-cpp/steps/01-build.md +1 -1
- package/skills/building-cpp/steps/02-tooling.md +2 -2
- package/skills/building-cpp/steps/03-check.md +8 -6
- package/skills/developing-cpp/SKILL.md +19 -3
- package/skills/developing-cpp/examples/comments.md +161 -119
- package/skills/developing-cpp/examples/structure.md +4 -4
- package/skills/developing-cpp/references/comments.md +158 -69
- package/skills/developing-cpp/references/declaration-order.md +4 -2
- package/skills/developing-cpp/references/file-template.md +131 -0
- package/skills/developing-cpp/references/glossary.md +3 -3
- package/skills/developing-cpp/references/google-cpp-style.md +8 -8
- package/skills/developing-cpp/references/language.md +3 -3
- package/skills/developing-cpp/references/layout.md +21 -12
- package/skills/developing-cpp/references/naming.md +11 -2
- package/skills/developing-cpp/references/project-design.md +10 -1
- package/skills/developing-cpp/references/standard-library.md +1 -1
- package/skills/developing-cpp/scripts/checking-comments.mjs +316 -0
- package/skills/developing-cpp/steps/01-behavior.md +1 -1
- package/skills/developing-cpp/steps/02-boundary.md +5 -4
- package/skills/developing-cpp/steps/03-declaration.md +6 -6
- package/skills/developing-cpp/steps/04-implementation.md +3 -3
- /package/skills/building-cpp/assets/templates/projects/multi/src/{greeting.cc → greeting.cpp} +0 -0
- /package/skills/building-cpp/assets/templates/projects/multi/src/{main.cc → main.cpp} +0 -0
- /package/skills/building-cpp/assets/templates/projects/shared-library/greeting/src/{greeting.cc → greeting.cpp} +0 -0
- /package/skills/building-cpp/assets/templates/projects/shared-library/src/{main.cc → main.cpp} +0 -0
- /package/skills/building-cpp/assets/templates/projects/single/src/{main.cc → main.cpp} +0 -0
- /package/skills/building-cpp/assets/templates/projects/static-library/greeting/src/{greeting.cc → greeting.cpp} +0 -0
- /package/skills/building-cpp/assets/templates/projects/static-library/src/{main.cc → main.cpp} +0 -0
package/README.en.md
CHANGED
|
@@ -8,7 +8,7 @@ Two skills for C++11–C++23 source and build work; new projects default to C++2
|
|
|
8
8
|
|
|
9
9
|
| Skill | Covers | Open it when |
|
|
10
10
|
| --- | --- | --- |
|
|
11
|
-
| `developing-cpp` | Behavior, boundaries, declarations, implementation; naming, exceptions, and source comments in `.h` / `.cc` | The user names source code, or the work is a new project or whole-stage refactor |
|
|
11
|
+
| `developing-cpp` | Behavior, boundaries, declarations, implementation; naming, exceptions, and source comments in `.h` / `.cpp` / `.cc` | The user names source code, or the work is a new project or whole-stage refactor |
|
|
12
12
|
| `building-cpp` | Build setup, tool configuration, checks; CMake, Ninja, Clang config, build scripts, and environment combinations | The change touches build files, tool config, or the environment declaration, or the project is first connected to a build |
|
|
13
13
|
|
|
14
14
|
The exception material follows the C++ Core Guidelines' Error handling section and guides source and examples only during development; the plugin runtime never compiles or executes those rules. Both skills read the project skill `cpp-workflow-project` first. Without it, the workspace gate never exposes these names.
|
|
@@ -18,13 +18,13 @@ The exception material follows the C++ Core Guidelines' Error handling section a
|
|
|
18
18
|
Pinned npm install:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
dsh plugin --profile web add npm:@chengzhao-dev/dsh-cpp-workflow@0.
|
|
21
|
+
dsh plugin --profile web add npm:@chengzhao-dev/dsh-cpp-workflow@0.3.1
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
The matching Git tag:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
dsh plugin --profile web add github:chengzhao-dev/dsh-cpp-workflow#v0.
|
|
27
|
+
dsh plugin --profile web add github:chengzhao-dev/dsh-cpp-workflow#v0.3.1
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
The desktop app owns the `desktop` profile. If the command-line `add` is rejected, add the plugin in the app settings and use the same pinned npm version. A Git tag install uses the prebuilt `lib/` committed in the repository and runs no build on the target machine; the package has no install script that needs approval.
|
|
@@ -89,7 +89,9 @@ dsh-cpp-workflow/
|
|
|
89
89
|
└── icon.svg
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
The repository also keeps `src/`, `scripts/`, `tests/` and `docs/` for development and review; they are not published. The whitelist lives in [docs/plugin-layout.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/plugin-layout.md).
|
|
93
|
+
|
|
94
|
+
Maintenance notes: flow and gate in [docs/plugin-flow.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/plugin-flow.md), skill layers and data flow in [docs/architecture.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/architecture.md), trigger matrix in [docs/triggering.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/triggering.md), directory and npm whitelist in [docs/plugin-layout.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/plugin-layout.md), version rules in [docs/versioning.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/versioning.md).
|
|
93
95
|
|
|
94
96
|
## Local development
|
|
95
97
|
|
|
@@ -97,7 +99,7 @@ Requires Node.js 22 or newer.
|
|
|
97
99
|
|
|
98
100
|
```bash
|
|
99
101
|
npm ci
|
|
100
|
-
npm test # build, structural check, gate/environment/schema tests
|
|
102
|
+
npm test # build, structural check, gate/environment/schema/comment tests
|
|
101
103
|
npm run test:matrix # real build matrix: 4 templates x 5 standards
|
|
102
104
|
npm run pack:check # inspect the npm package contents
|
|
103
105
|
```
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
| 技能 | 管什么 | 什么时候打开 |
|
|
10
10
|
| --- | --- | --- |
|
|
11
|
-
| `developing-cpp` | 定行为、定边界、定声明、定实现;`.h` / `.cc` 的命名、异常和源码注释 | 用户点名源码,或需要新建/整段重构源码 |
|
|
11
|
+
| `developing-cpp` | 定行为、定边界、定声明、定实现;`.h` / `.cpp` / `.cc` 的命名、异常和源码注释 | 用户点名源码,或需要新建/整段重构源码 |
|
|
12
12
|
| `building-cpp` | 定构建、定工具配置、通过检查;CMake、Ninja、Clang 配置、构建脚本和环境组合 | 改动落在构建文件、工具配置或环境声明上,或第一次接构建 |
|
|
13
13
|
|
|
14
14
|
异常条文采用 C++ Core Guidelines 的 Error handling,只在开发阶段指导源码和示例;插件运行时不编译、不执行这些规则。两个技能都先读项目技能 `cpp-workflow-project`。没有项目技能时,门禁不会放出这两个名字。
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
npm 安装钉死版本:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
dsh plugin --profile web add npm:@chengzhao-dev/dsh-cpp-workflow@0.
|
|
21
|
+
dsh plugin --profile web add npm:@chengzhao-dev/dsh-cpp-workflow@0.3.1
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
同版本的 Git 标签:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
dsh plugin --profile web add github:chengzhao-dev/dsh-cpp-workflow#v0.
|
|
27
|
+
dsh plugin --profile web add github:chengzhao-dev/dsh-cpp-workflow#v0.3.1
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
桌面应用独占 `desktop` profile。命令行 `add` 被拒绝时,在应用设置里添加插件,地址填同一个 npm 版本。Git 标签安装使用仓库内已构建的 `lib/`,不在目标机器上重新构建;包内也不含需要授权执行的安装脚本。
|
|
@@ -89,7 +89,9 @@ dsh-cpp-workflow/
|
|
|
89
89
|
└── icon.svg
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
仓库另有 `src/`、`scripts/`、`tests/` 与 `docs/`,只服务开发与评审,不进包;白名单见 [docs/plugin-layout.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/plugin-layout.md)。
|
|
93
|
+
|
|
94
|
+
边界与门禁的维护说明在 [docs/plugin-flow.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/plugin-flow.md),技能的层次与数据流在 [docs/architecture.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/architecture.md),触发矩阵在 [docs/triggering.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/triggering.md),目录和进包白名单在 [docs/plugin-layout.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/plugin-layout.md),版本规则在 [docs/versioning.md](https://github.com/chengzhao-dev/dsh-cpp-workflow/blob/main/docs/versioning.md)。
|
|
93
95
|
|
|
94
96
|
## 本地开发
|
|
95
97
|
|
|
@@ -97,7 +99,7 @@ dsh-cpp-workflow/
|
|
|
97
99
|
|
|
98
100
|
```bash
|
|
99
101
|
npm ci
|
|
100
|
-
npm test # 构建、结构检查、门禁/环境/schema
|
|
102
|
+
npm test # 构建、结构检查、门禁/环境/schema/注释测试
|
|
101
103
|
npm run test:matrix # 四套模板 × 五档标准的真实构建矩阵
|
|
102
104
|
npm run pack:check # 核对 npm 包内容
|
|
103
105
|
```
|
package/lib/workspace.js
CHANGED
|
@@ -6,12 +6,10 @@
|
|
|
6
6
|
// freshly copied template still sees the workflow. The git root is the
|
|
7
7
|
// repository boundary: marker lookup ignores sibling directories and never
|
|
8
8
|
// searches above the root.
|
|
9
|
-
import { access
|
|
9
|
+
import { access } from 'node:fs/promises';
|
|
10
10
|
import path from 'node:path';
|
|
11
11
|
export const PROJECT_SKILL = path.join('.agents', 'skills', 'cpp-workflow-project', 'SKILL.md');
|
|
12
12
|
export const MAX_ASCENT = 64;
|
|
13
|
-
export const MAX_SCAN_DEPTH = 12;
|
|
14
|
-
export const MAX_SCAN_ENTRIES = 4000;
|
|
15
13
|
const SKIPPED_DIRS = new Set([
|
|
16
14
|
'.git',
|
|
17
15
|
'node_modules',
|
|
@@ -22,16 +20,6 @@ const SKIPPED_DIRS = new Set([
|
|
|
22
20
|
'temp',
|
|
23
21
|
'.cache',
|
|
24
22
|
]);
|
|
25
|
-
export const CPP_SOURCE_EXTENSIONS = new Set([
|
|
26
|
-
'.c',
|
|
27
|
-
'.cc',
|
|
28
|
-
'.cpp',
|
|
29
|
-
'.cxx',
|
|
30
|
-
'.h',
|
|
31
|
-
'.hh',
|
|
32
|
-
'.hpp',
|
|
33
|
-
'.hxx',
|
|
34
|
-
]);
|
|
35
23
|
export const CPP_BUILD_FILES = new Set(['CMakeLists.txt']);
|
|
36
24
|
async function exists(target) {
|
|
37
25
|
try {
|
|
@@ -107,49 +95,6 @@ export async function findProjectSkill(cwd, gitRoot) {
|
|
|
107
95
|
export async function hasProjectSkill(cwd, gitRoot) {
|
|
108
96
|
return (await findProjectSkill(cwd, gitRoot)) !== undefined;
|
|
109
97
|
}
|
|
110
|
-
/**
|
|
111
|
-
* True when `root` contains at least one first-party `CMakeLists.txt` or C++
|
|
112
|
-
* source/header. Generated, dependency, template and build trees are skipped.
|
|
113
|
-
* The scan is bounded to 12 levels and 4000 directory entries.
|
|
114
|
-
*/
|
|
115
|
-
export async function hasCppProject(root) {
|
|
116
|
-
let seen = 0;
|
|
117
|
-
const queue = [{ dir: root, depth: 0 }];
|
|
118
|
-
while (queue.length > 0) {
|
|
119
|
-
const current = queue.shift();
|
|
120
|
-
if (!current)
|
|
121
|
-
break;
|
|
122
|
-
let entries;
|
|
123
|
-
try {
|
|
124
|
-
entries = await readdir(current.dir, { withFileTypes: true });
|
|
125
|
-
}
|
|
126
|
-
catch {
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
for (const entry of entries) {
|
|
130
|
-
seen += 1;
|
|
131
|
-
if (seen > MAX_SCAN_ENTRIES)
|
|
132
|
-
return false;
|
|
133
|
-
if (entry.isSymbolicLink())
|
|
134
|
-
continue;
|
|
135
|
-
if (entry.isDirectory()) {
|
|
136
|
-
if (current.depth >= MAX_SCAN_DEPTH)
|
|
137
|
-
continue;
|
|
138
|
-
if (SKIPPED_DIRS.has(entry.name))
|
|
139
|
-
continue;
|
|
140
|
-
queue.push({ dir: path.join(current.dir, entry.name), depth: current.depth + 1 });
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
if (!entry.isFile())
|
|
144
|
-
continue;
|
|
145
|
-
if (CPP_BUILD_FILES.has(entry.name))
|
|
146
|
-
return true;
|
|
147
|
-
if (CPP_SOURCE_EXTENSIONS.has(path.extname(entry.name).toLowerCase()))
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return false;
|
|
152
|
-
}
|
|
153
98
|
/**
|
|
154
99
|
* Session gate. The project skill must sit between `cwd` and the git root
|
|
155
100
|
* (inclusive). First-party C++ or CMake evidence is deliberately not required:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chengzhao-dev/dsh-cpp-workflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "C++11–C++23 工程流程技能包:源码四步与构建三步,按项目声明的环境组合校验 · C++11–C++23 workflow skills for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"icon": "./icon.svg",
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsc -p tsconfig.json",
|
|
45
|
-
"test": "npm run build && node scripts/checking-skill-links.mjs && node --test tests/*.test.mjs",
|
|
45
|
+
"test": "npm run build && node scripts/checking-skill-links.mjs && node skills/building-cpp/scripts/checking-encoding.mjs --quiet && node --test tests/*.test.mjs",
|
|
46
|
+
"check:encoding": "node skills/building-cpp/scripts/checking-encoding.mjs",
|
|
46
47
|
"test:matrix": "bash scripts/checking-standard-matrix.sh",
|
|
47
48
|
"pack:check": "npm pack --dry-run"
|
|
48
49
|
},
|
|
@@ -13,6 +13,8 @@ metadata:
|
|
|
13
13
|
|
|
14
14
|
编译失败先分因:诊断指向函数体,回 `developing-cpp` 的定实现;诊断指向声明或类型,回定声明;诊断是找不到头、链接失败、没有编译数据库或工具不在 PATH,留在本技能的定构建或定工具配置。
|
|
15
15
|
|
|
16
|
+
源码和构建文件用 UTF-8 无 BOM、检出 LF;`.bat` / `.cmd` 用 CRLF;`.clang-format` 写 `LineEnding: LF`。MSVC 原生构建优先加 `/utf-8`,不要靠 BOM 过关。完整规则见 `references/encoding.md`,检查脚本是 `scripts/checking-encoding.mjs`,机器规则以仓库根 `.gitattributes` 与 `.editorconfig` 为准。
|
|
17
|
+
|
|
16
18
|
存在项目技能 `cpp-workflow-project` 时先读它的 `SKILL.md`、`environment.json` 和 `stages/stage-table.md`。三个环境轴为空、`standard` 非法或组合非法时停在定构建,不猜 WSL、Clang 或构建目录;`windows` + `native` 直接拒绝,提示「本版本不能在 Windows 原生壳里构建」,不要给出补 PowerShell 的路线。环境组合空着时源码四步仍可做,只是不能构建。
|
|
17
19
|
|
|
18
20
|
## 两种走法
|
|
@@ -30,9 +32,9 @@ metadata:
|
|
|
30
32
|
| --- | --- | --- | --- |
|
|
31
33
|
| 1 | 定构建 | `steps/01-build.md` | 一次配置一个编译器,Ninja,target-based CMake,编译数据库 |
|
|
32
34
|
| 2 | 定工具配置 | `steps/02-tooling.md` | 格式化、静态检查、clangd 各管一段,互不越界 |
|
|
33
|
-
| 3 | 通过检查 | `steps/03-check.md` |
|
|
35
|
+
| 3 | 通过检查 | `steps/03-check.md` | 按编码 → 声明校验 → 活动校验 → 项目入口的次序跑,前一步失败就停 |
|
|
34
36
|
|
|
35
|
-
每步只打开同号的一个步骤文件。判不准才打开 `examples/` 里与该步对应的案例;`references/`
|
|
37
|
+
每步只打开同号的一个步骤文件。判不准才打开 `examples/` 里与该步对应的案例;`references/` 保存完整条文,只在排错、整目录重构,或步骤里明确指向某一条文时按需打开。链接、rpath 与产物布局读 `references/linking.md`;警告选项、GoogleTest 与 rpath 的 CMake 片段在 `assets/cmake/`,由 `references/cmake.md` 指路。
|
|
36
38
|
|
|
37
39
|
## 完成判据
|
|
38
40
|
|
|
@@ -7,8 +7,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
|
|
7
7
|
enable_testing()
|
|
8
8
|
|
|
9
9
|
add_executable(app
|
|
10
|
-
src/main.
|
|
11
|
-
src/greeting.
|
|
10
|
+
src/main.cpp
|
|
11
|
+
src/greeting.cpp
|
|
12
12
|
)
|
|
13
13
|
target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
14
14
|
target_compile_features(app PRIVATE cxx_std_23)
|
|
@@ -9,7 +9,7 @@ enable_testing()
|
|
|
9
9
|
|
|
10
10
|
add_subdirectory(greeting)
|
|
11
11
|
|
|
12
|
-
add_executable(app src/main.
|
|
12
|
+
add_executable(app src/main.cpp)
|
|
13
13
|
target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
14
14
|
target_compile_features(app PRIVATE cxx_std_23)
|
|
15
15
|
set_target_properties(app PROPERTIES
|
|
@@ -9,7 +9,7 @@ enable_testing()
|
|
|
9
9
|
|
|
10
10
|
add_subdirectory(greeting)
|
|
11
11
|
|
|
12
|
-
add_executable(app src/main.
|
|
12
|
+
add_executable(app src/main.cpp)
|
|
13
13
|
target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
14
14
|
target_compile_features(app PRIVATE cxx_std_23)
|
|
15
15
|
set_target_properties(app PROPERTIES
|
|
@@ -10,13 +10,13 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
10
10
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
|
11
11
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
|
12
12
|
|
|
13
|
-
add_library(greeting STATIC greeting/src/greeting.
|
|
13
|
+
add_library(greeting STATIC greeting/src/greeting.cpp)
|
|
14
14
|
target_include_directories(greeting PUBLIC greeting/include)
|
|
15
15
|
target_compile_features(greeting PUBLIC cxx_std_23)
|
|
16
16
|
set_target_properties(greeting PROPERTIES CXX_EXTENSIONS OFF)
|
|
17
17
|
target_compile_options(greeting PRIVATE -Wall -Wextra -Werror)
|
|
18
18
|
|
|
19
|
-
add_executable(app src/main.
|
|
19
|
+
add_executable(app src/main.cpp)
|
|
20
20
|
target_compile_features(app PRIVATE cxx_std_23)
|
|
21
21
|
set_target_properties(app PROPERTIES CXX_EXTENSIONS OFF)
|
|
22
22
|
target_link_libraries(app PRIVATE greeting)
|
|
@@ -30,7 +30,7 @@ target_link_libraries(app PRIVATE greeting)
|
|
|
30
30
|
|
|
31
31
|
```cmake
|
|
32
32
|
include_directories(include greeting/include)
|
|
33
|
-
add_executable(app src/main.
|
|
33
|
+
add_executable(app src/main.cpp greeting/src/greeting.cpp)
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
问题:所有 target 共享 include,边界消失;程序直接编译库源码,测试无法只链接库。
|
|
@@ -47,7 +47,7 @@ target_link_libraries(app PRIVATE greeting)
|
|
|
47
47
|
**差**:
|
|
48
48
|
|
|
49
49
|
```cmake
|
|
50
|
-
file(GLOB SOURCES "src/*.
|
|
50
|
+
file(GLOB SOURCES "src/*.cpp")
|
|
51
51
|
add_executable(app ${SOURCES})
|
|
52
52
|
```
|
|
53
53
|
|
|
@@ -57,9 +57,9 @@ add_executable(app ${SOURCES})
|
|
|
57
57
|
|
|
58
58
|
```cmake
|
|
59
59
|
add_executable(app
|
|
60
|
-
src/main.
|
|
61
|
-
src/task_list.
|
|
62
|
-
src/task_parser.
|
|
60
|
+
src/main.cpp
|
|
61
|
+
src/task_list.cpp
|
|
62
|
+
src/task_parser.cpp
|
|
63
63
|
)
|
|
64
64
|
```
|
|
65
65
|
|
|
@@ -70,15 +70,15 @@ add_executable(app
|
|
|
70
70
|
**差**:
|
|
71
71
|
|
|
72
72
|
```cmake
|
|
73
|
-
add_library(core STATIC src/main.
|
|
74
|
-
add_executable(app src/main.
|
|
73
|
+
add_library(core STATIC src/main.cpp src/core.cpp)
|
|
74
|
+
add_executable(app src/main.cpp) # 重复定义
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
**好**:
|
|
78
78
|
|
|
79
79
|
```cmake
|
|
80
|
-
add_library(core STATIC src/core.
|
|
81
|
-
add_executable(app src/main.
|
|
80
|
+
add_library(core STATIC src/core.cpp)
|
|
81
|
+
add_executable(app src/main.cpp)
|
|
82
82
|
target_link_libraries(app PRIVATE core)
|
|
83
83
|
```
|
|
84
84
|
|
|
@@ -93,7 +93,7 @@ target_link_libraries(app PRIVATE core)
|
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
```bash
|
|
96
|
-
clang-tidy src/main.
|
|
96
|
+
clang-tidy src/main.cpp # 没有编译参数,头路径和标准都不对
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
**好**:
|
|
@@ -106,7 +106,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
106
106
|
cmake -S . -B build/clang -G Ninja -DCMAKE_CXX_COMPILER=clang++
|
|
107
107
|
rm -f build/compile_commands.json
|
|
108
108
|
ln -s clang/compile_commands.json build/compile_commands.json
|
|
109
|
-
clang-tidy -p build/clang src/main.
|
|
109
|
+
clang-tidy -p build/clang src/main.cpp
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
## 共享库运行时路径
|
|
@@ -120,11 +120,11 @@ LD_LIBRARY_PATH=build/clang/lib ./build/clang/bin/app # 每次运行都要包
|
|
|
120
120
|
**好**:
|
|
121
121
|
|
|
122
122
|
```cmake
|
|
123
|
-
add_library(greeting SHARED greeting/src/greeting.
|
|
123
|
+
add_library(greeting SHARED greeting/src/greeting.cpp)
|
|
124
124
|
set_target_properties(greeting PROPERTIES
|
|
125
125
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
|
126
126
|
|
|
127
|
-
add_executable(app src/main.
|
|
127
|
+
add_executable(app src/main.cpp)
|
|
128
128
|
target_link_libraries(app PRIVATE greeting)
|
|
129
129
|
if(APPLE)
|
|
130
130
|
set_target_properties(app PROPERTIES BUILD_RPATH "@loader_path/../lib")
|
|
@@ -121,7 +121,7 @@ Checks: >
|
|
|
121
121
|
**差**:
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
|
-
clang-tidy -p build/clang --system-headers src/main.
|
|
124
|
+
clang-tidy -p build/clang --system-headers src/main.cpp
|
|
125
125
|
```
|
|
126
126
|
|
|
127
127
|
系统头也参与诊断,出现大量第三方告警。
|
|
@@ -130,7 +130,7 @@ clang-tidy -p build/clang --system-headers src/main.cc
|
|
|
130
130
|
|
|
131
131
|
```bash
|
|
132
132
|
clang-tidy -p build/clang --header-filter="^$(pwd -P)/(include|src)/" \
|
|
133
|
-
--warnings-as-errors='*' src/main.
|
|
133
|
+
--warnings-as-errors='*' src/main.cpp
|
|
134
134
|
```
|
|
135
135
|
|
|
136
136
|
`--header-filter` 只列项目顶层目录,避免把第三方头纳入;系统头默认排除。工程有别的顶层目录时按实际替换。
|
|
@@ -140,7 +140,7 @@ clang-tidy -p build/clang --header-filter="^$(pwd -P)/(include|src)/" \
|
|
|
140
140
|
**差**:
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
|
-
clang-format -i src/*.
|
|
143
|
+
clang-format -i src/*.cpp # 构建时悄悄改源码
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
**好**:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CMake
|
|
2
2
|
|
|
3
|
-
目标:一个编译器、Ninja、target-based 规则、可用的编译数据库。下面是最小形状和常见边界;模板在 `assets/templates/projects
|
|
3
|
+
目标:一个编译器、Ninja、target-based 规则、可用的编译数据库。下面是最小形状和常见边界;模板在 `assets/templates/projects/`,可复用的 CMake 片段在 `assets/cmake/`:`applying-warnings.cmake` 管警告选项,`fetching-googletest.cmake` 取测试框架,`setting-rpath.cmake` 设运行时库路径。
|
|
4
4
|
|
|
5
5
|
## 排版
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ project({{PROJECT_NAME}} VERSION 0.1.0 LANGUAGES CXX)
|
|
|
19
19
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
20
20
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
|
21
21
|
|
|
22
|
-
add_executable(app src/main.
|
|
22
|
+
add_executable(app src/main.cpp)
|
|
23
23
|
target_compile_features(app PRIVATE cxx_std_23)
|
|
24
24
|
set_target_properties(app PROPERTIES
|
|
25
25
|
CXX_STANDARD 23
|
|
@@ -42,7 +42,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
|
|
42
42
|
|
|
43
43
|
add_subdirectory(greeting)
|
|
44
44
|
|
|
45
|
-
add_executable(app src/main.
|
|
45
|
+
add_executable(app src/main.cpp)
|
|
46
46
|
target_compile_features(app PRIVATE cxx_std_23)
|
|
47
47
|
set_target_properties(app PROPERTIES
|
|
48
48
|
CXX_STANDARD 23
|
|
@@ -55,7 +55,7 @@ target_compile_options(app PRIVATE -Wall -Wextra -Werror)
|
|
|
55
55
|
|
|
56
56
|
```cmake
|
|
57
57
|
# greeting/CMakeLists.txt
|
|
58
|
-
add_library(greeting STATIC src/greeting.
|
|
58
|
+
add_library(greeting STATIC src/greeting.cpp)
|
|
59
59
|
target_include_directories(greeting PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)
|
|
60
60
|
target_compile_features(greeting PUBLIC cxx_std_23)
|
|
61
61
|
set_target_properties(greeting PROPERTIES
|
|
@@ -168,7 +168,7 @@ FetchContent_MakeAvailable(googletest)
|
|
|
168
168
|
|
|
169
169
|
| 模板 | 何时用 | 关键文件 |
|
|
170
170
|
| --- | --- | --- |
|
|
171
|
-
| `single` | 一个 `main.
|
|
171
|
+
| `single` | 一个 `main.cpp`,辅助函数很少 | `CMakeLists.txt`, `src/main.cpp` |
|
|
172
172
|
| `multi` | 多个源文件,一个程序 | `CMakeLists.txt`, `include/`, `src/` |
|
|
173
173
|
| `static-library` | 库需要被测试或第二个程序链接 | 根 + `greeting/` 子目录 |
|
|
174
174
|
| `shared-library` | 需要运行时加载/替换 | 同上,`SHARED` + RPATH |
|
|
@@ -178,7 +178,7 @@ FetchContent_MakeAvailable(googletest)
|
|
|
178
178
|
## 反模式
|
|
179
179
|
|
|
180
180
|
- 全局 `include_directories(include)`:所有 target 共享,边界消失。
|
|
181
|
-
- `file(GLOB sources "src/*.
|
|
181
|
+
- `file(GLOB sources "src/*.cpp")`:新增文件不触发重新配置。
|
|
182
182
|
- 把库和 `main()` 编进同一个 target:测试无法只链接库。
|
|
183
183
|
- 在源码目录生成 `compile_commands.json` 或可执行文件。
|
|
184
184
|
- 同时设 `CMAKE_CXX_COMPILER` 和 `CXX` 环境变量,互相覆盖。
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 编码与行尾
|
|
2
|
+
|
|
3
|
+
默认组合是 UTF-8 无 BOM、LF。机器规则以仓库根 `.gitattributes` 与 `.editorconfig` 为准,本文件只记决定、MSVC 例外与检查方法。
|
|
4
|
+
|
|
5
|
+
## 规则
|
|
6
|
+
|
|
7
|
+
- 文本文件用 UTF-8,不带 BOM。JSON 按 RFC 8259;YAML 按 YAML 1.2.2;不要 GBK、UTF-16 或 Latin-1。
|
|
8
|
+
- 所有文本文件用 LF,包括 `.sh`、Python、C++、Markdown、YAML、CMake 和配置文件。
|
|
9
|
+
- `.sh` 必须 LF:内核会把 shebang 末尾的 CR 当作解释器路径的一部分,导致 `bad interpreter`。
|
|
10
|
+
- `.bat` / `.cmd` 必须 CRLF:`cmd.exe` 对纯 LF 批处理不稳定。
|
|
11
|
+
- 每个文本文件末尾一个换行;文件中间不混用 LF 和 CRLF。
|
|
12
|
+
- 二进制文件(字体、图片)不转码,按 `binary` 处理。
|
|
13
|
+
|
|
14
|
+
## MSVC 原生
|
|
15
|
+
|
|
16
|
+
MSVC 默认按 BOM 判断源码编码。源码没有 BOM 时,它按当前用户代码页解释,除非显式传入 `/utf-8` 或 `/source-charset:utf-8`。因此 BOM 不是 MSVC 的硬要求。
|
|
17
|
+
|
|
18
|
+
- 首选做法是加编译选项:在目标上写 `target_compile_options(<target> PRIVATE $<$<CXX_COMPILER_ID:MSVC>:/utf-8>)`,源码继续 UTF-8 无 BOM、LF。
|
|
19
|
+
- 只有在无法改编译选项时,才把 MSVC 编译的 C/C++ 源文件保存为 UTF-8 BOM。BOM 只允许出现在这类源文件里。
|
|
20
|
+
- `.sh`、`.bat`、`.cmd`、`.json`、`.yml`、`.gitattributes`、`.editorconfig` 和 CMake 文件不要加 BOM。
|
|
21
|
+
- MSVC 接受 LF 源码;CRLF 不是必需项。只有 `.bat` / `.cmd` 固定 CRLF。
|
|
22
|
+
- WSL 与 Linux 构建按默认组合,不要把源码转成 CRLF 来迁就 Windows。
|
|
23
|
+
|
|
24
|
+
## 工具
|
|
25
|
+
|
|
26
|
+
- `.gitattributes` 决定 Git 入库和检出;它覆盖贡献者自己的 `core.autocrlf`。
|
|
27
|
+
- `.editorconfig` 决定编辑器保存;`charset` 与 `end_of_line` 必须和 `.gitattributes` 同一档。
|
|
28
|
+
- `.clang-format` 写 `LineEnding: LF`,避免格式化把行尾改回 CRLF。
|
|
29
|
+
|
|
30
|
+
## 检查
|
|
31
|
+
|
|
32
|
+
在仓库根运行:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
node "<skill-dir>/scripts/checking-encoding.mjs" --profile portable
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- `portable`(默认)要求所有文本文件 UTF-8 无 BOM、LF、末尾换行。
|
|
39
|
+
- `msvc` 只放宽 MSVC 编译的 C/C++ 源文件:允许 UTF-8 BOM 与 CRLF;Markdown、配置与脚本仍按 `portable` 检查。
|
|
40
|
+
- 退出码:0 无问题,1 有问题,2 参数或 Git 错误。加 `--json` 输出机器可读结果。
|
|
41
|
+
|
|
42
|
+
再跑 `git diff --check`,确认没有空白错误。不要用 `git add --renormalize` 把行尾改动混进功能改动;确需规范化时单独提交并说明。
|
|
43
|
+
|
|
44
|
+
## 依据
|
|
45
|
+
|
|
46
|
+
- MSVC `/utf-8`:<https://learn.microsoft.com/en-us/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-170>
|
|
47
|
+
- MSVC `/source-charset`:<https://learn.microsoft.com/en-us/cpp/build/reference/source-charset-set-source-character-set?view=msvc-170>
|
|
48
|
+
- Unicode UTF-8 BOM FAQ:<https://www.unicode.org/faq/utf_bom.html>
|
|
49
|
+
- Git `.gitattributes`:<https://git-scm.com/docs/gitattributes>
|
|
@@ -15,25 +15,25 @@
|
|
|
15
15
|
- 链接:把多个目标文件和库合并,解析符号引用。`undefined reference` 在这一步失败。
|
|
16
16
|
- 加载:程序启动时由动态加载器找到共享库;`error while loading shared libraries` 在这一步失败。
|
|
17
17
|
|
|
18
|
-
`g++ -c file.
|
|
18
|
+
`g++ -c file.cpp` 只编译不链接;`g++ file.o -o app` 只链接。`-E` 只看预处理,`-S` 只看汇编。
|
|
19
19
|
|
|
20
20
|
## 头文件、声明与定义
|
|
21
21
|
|
|
22
22
|
- `#include` 是文本替换,不是模块导入;头文件只放声明、`inline` 定义、模板和 `constexpr` 定义。
|
|
23
|
-
- 普通函数的定义放 `.
|
|
24
|
-
- 类定义放头文件;成员函数在类外定义时写 `ClassName::`,定义放 `.
|
|
23
|
+
- 普通函数的定义放 `.cpp`;在头文件里写非 `inline` 函数定义,多个翻译单元包含时会重复定义。
|
|
24
|
+
- 类定义放头文件;成员函数在类外定义时写 `ClassName::`,定义放 `.cpp`。
|
|
25
25
|
- 只用到声明时不要包含完整定义;前置声明可以减少编译依赖,但不能替代需要完整类型的场景(继承、成员对象、按值返回)。
|
|
26
|
-
- 每个头文件自包含:单独编译一个只包含该头文件的 `.
|
|
26
|
+
- 每个头文件自包含:单独编译一个只包含该头文件的 `.cpp` 应通过。用路径式 `#define` 守卫防止重复包含,不用 `#pragma once`。
|
|
27
27
|
|
|
28
28
|
## `undefined reference` 分诊
|
|
29
29
|
|
|
30
30
|
| 现象 | 常见原因 | 修法 |
|
|
31
31
|
| --- | --- | --- |
|
|
32
|
-
| 链接器说某个成员函数未定义 | 声明了但没写定义,或 `.
|
|
32
|
+
| 链接器说某个成员函数未定义 | 声明了但没写定义,或 `.cpp` 没加入 target | 补定义,或把源文件加入 `target_sources` |
|
|
33
33
|
| 只有某个平台失败 | 条件编译把定义排除了 | 检查宏和平台分支,保证每个平台都有定义 |
|
|
34
34
|
| 第三方库符号缺失 | 没链接库,或库顺序不对 | `target_link_libraries` 加库;CMake 会处理顺序 |
|
|
35
35
|
| C++ 符号被当成 C 符号 | 头文件缺少 `extern \"C\"` | C 接口头加 `extern \"C\"`,C++ 调用方也可见 |
|
|
36
|
-
| 模板成员未定义 | 模板定义在 `.
|
|
36
|
+
| 模板成员未定义 | 模板定义在 `.cpp`,实例化点看不到 | 模板定义移到头文件,或显式实例化 |
|
|
37
37
|
| 静态库中的目标文件没被拉入 | 链接器只取被引用符号所在的目标文件 | 确认符号确实被引用,或改用对象库/共享库 |
|
|
38
38
|
|
|
39
39
|
先看链接器报的完整符号名和来源文件,不要只看第一行。
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
## 降档/升级
|
|
45
45
|
|
|
46
|
-
从 C++23 降到 C++20 见 [C++20 档案](../c++20/README.md)。升级到 C++26 前先确认 CMake 3.25+、编译器/标准库支持、clang-format 的 `c++26` 枚举;新增目录流程见[标准索引](../README.md#新增标准)。
|
|
46
|
+
从 C++23 降到 C++20 见 [C++20 档案](../c++20/README.md)。升级到 C++26 前先确认 CMake 3.25+、编译器/标准库支持、clang-format 的 `c++26` 枚举;新增目录流程见 [标准索引](../README.md#新增标准)。
|
|
47
47
|
|
|
48
48
|
## 验证
|
|
49
49
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
## clang-format
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
clang-format --dry-run --Werror src/*.
|
|
8
|
+
clang-format --dry-run --Werror src/*.cpp include/*.h tests/*.cpp
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
- 检查用 `--dry-run --Werror`;需要自动修复时单独跑 `clang-format -i`,不要在构建脚本里悄悄改源码。
|
|
@@ -21,7 +21,7 @@ clang-format --dry-run --Werror src/*.cc include/*.h tests/*.cc
|
|
|
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/*.cpp apps/*.cpp tests/*.cpp
|
|
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`;默认集合是 `google
|
|
33
|
+
- 配置在工程根 `.clang-tidy`;默认集合是 `google-*`、`portability-avoid-pragma-once` 加 `readability-identifier-naming`(第二条去掉 `#pragma once`,与路径式守卫一致)。关闭某条时逐条写理由,不整族关闭;命名规则只配项目确实统一的项,不设 `FunctionCase`。
|
|
34
34
|
- 没有编译数据库时先回到 `building-cpp` 的定构建生成;不要用 `--` 手工拼编译参数绕过。
|
|
35
35
|
- `clang-tidy` 的诊断可能指向头文件;修头文件里的声明或实现,不要只改调用点。
|
|
36
36
|
|