75 lines
3.2 KiB
Markdown
75 lines
3.2 KiB
Markdown
# Code Style
|
|
|
|
这个文档记录 agent 修改 Tianole 代码时必须遵守的代码组织和风格规则。
|
|
|
|
## 总原则
|
|
|
|
- 参考 Linux 的工程风格,但不机械照抄 Linux 的历史实现。
|
|
- 简化实现可以接受,写死架构边界、设备假设、内存布局和调用路径不接受。
|
|
- 文件按职责拆分,不按行数拆分。
|
|
- 入口文件只编排流程,不承载具体功能细节。
|
|
|
|
## Include 风格
|
|
|
|
- 公共头文件使用 `<...>`,例如 `<tianole/boot_info.h>`。
|
|
- 同目录私有头文件使用 `"..."`,例如 `"file.h"`。
|
|
- 不使用 `../foo.h` 这类相对 include。
|
|
- 如果一个头文件需要跨目录使用,先判断它是否应该成为公共接口。
|
|
- `include/tianole/` 放尽量架构无关的共享接口。
|
|
- `arch/<arch>/include/` 放架构公开接口。
|
|
|
|
## 文件组织
|
|
|
|
- 长文件不是问题,职责混乱才是问题。
|
|
- 一个文件可以较长,但必须代表一个清晰子系统、算法或驱动边界。
|
|
- 不为了降低行数拆出 `utils.c`、`helpers.c` 这类无边界文件。
|
|
- 按职责、生命周期、所有权和调用边界拆分。
|
|
- `kernel/main.c`、`boot/main.c` 这类入口文件应保持短,只串联阶段。
|
|
- `mm/` 是顶层内存管理子系统目录,不放在 `kernel/mm/` 下。
|
|
|
|
## 命名
|
|
|
|
- 内部 C API 不加 `tianole_` 前缀。
|
|
- 架构目录内部不要重复架构名前缀;例如 `arch/x86/kernel/` 内使用 `gdt_init()`,不要写成 `x86_gdt_init()`。
|
|
- 跨通用层暴露的架构入口使用 `arch_` 前缀,例如 `arch_traps_init()`。
|
|
- 描述硬件规格的文档文字可以写 `x86_64`,但代码文件名和内部符号不需要反复带 `x86`。
|
|
- 避免 `temp`、`tmp` 这类临时语义进入函数名、类型名和长期变量名。
|
|
- 一次性局部变量也应尽量使用具体含义命名。
|
|
- 名字应表达长期职责,不表达当前实现的临时状态。
|
|
|
|
## 注释
|
|
|
|
- 注释优先解释硬件约束、ABI 决策、内存所有权、并发语义和不明显的不变量。
|
|
- 不写重复描述简单代码行为的注释。
|
|
- 如果代码依赖硬件手册、启动协议、调用顺序或特殊寄存器状态,应写明约束。
|
|
- 如果一个实现是临时简化,应写清楚后续替换边界,而不是写成永久接口。
|
|
|
|
## C 格式
|
|
|
|
- 使用 `.clang-format` 作为当前格式化规则。
|
|
- 使用 tab 缩进。
|
|
- 函数左花括号另起一行。
|
|
- `if/for/while` 左花括号留在行尾。
|
|
- 文本文件使用 LF 行尾。
|
|
|
|
## 构建文件
|
|
|
|
- 根 `Makefile` 只做总控和通用规则。
|
|
- 架构配置放在 `arch/<arch>/Makefile`。
|
|
- 目录自己的源文件列表放在对应目录的 `Makefile`。
|
|
- 顶层子系统目录可以有自己的 `Makefile`,例如 `mm/Makefile`。
|
|
- 不新增独立 `mk/` 目录,除非后续有明确且无法避免的理由。
|
|
|
|
## 脚本组织
|
|
|
|
- `scripts/check.sh` 是本地和 CI 共用的检查入口,只做编排。
|
|
- 可独立执行的检查放在 `scripts/checks/`。
|
|
- 多个检查共享的函数放在 `scripts/lib/`。
|
|
- 不把所有检查逻辑持续堆进 `scripts/check.sh`。
|
|
|
|
## 验证
|
|
|
|
- 新增或大改 C/H 文件后运行 `clang-format`。
|
|
- 提交前至少运行 `scripts/check.sh`。
|
|
- 如果只是文档修改,至少运行 `git diff --check`。
|