方案文档改造为机制说明:删除规划/盘点/阶段/风险/任务拆分章节,保留变量清单/解析语义/配置方法/验收判据,外部引用同步重编号

This commit is contained in:
2026-10-02 23:21:25 +08:00
parent bf025e6f10
commit 554b2e88da
4 changed files with 83 additions and 171 deletions
@@ -546,7 +546,7 @@ mv tools/serial_tool/state.bak_ci tools/serial_tool/state
### 5.1.3 机器级 `DTU_*` 环境变量(runner 的正式覆盖通道,2026-10-02 起)
workflow 已改为统一消费 `DTU_*` 接口(见 `本地工具路径环境变量方案.md` §5.3):
workflow 已改为统一消费 `DTU_*` 接口(见 `本地工具路径环境变量方案.md` §3.3):
**显式变量优先 → 自动发现回退**,三个 job 步骤相关的变量:
| 变量 | 作用 | 未设置时的回退 |
@@ -1,182 +1,94 @@
# 本地工具路径环境变量方案
> **状态**:**已实施**(2026-10-02,见文末变更记录)。仓库脚本已全部改为 `DTU_*` 变量解析,
> 本机已按 §5 配置并全链路验证(`@build` 0/0、`ci_local.py` L0+L0.5 全绿、refgraph 重生成、
> ST-LINK 探针识别);文档示例已同步改为变量口径。
> **目标**:同一份仓库代码可在不同 Windows 用户、磁盘和工具安装目录下工作,不再要求把 Keil、ST-LINK、Python、Visual Studio、Windows SDK、Graphviz、Cppcheck 安装到某台机器的固定绝对路径。
> **约束**:只用进程/用户/CI 服务环境变量配置本机差异;不提交本机路径,不引入 `.env`/`python-dotenv`,不把个人工具路径写入共享 workflow;仓库内部路径继续相对脚本/仓库根解析。
---
## 1. 设计结论
采用统一的 `DTU_` 前缀和**可执行文件/工具根目录的绝对路径变量**。调用端遵循:
```text
调用参数(如果已有)
  → 对应 DTU_* 环境变量(显式配置时严格使用;路径无效则报错)
  → PATH / Windows 安装发现(仅适合支持自动发现的工具)
  → 给出包含变量名与设置方式的清晰错误
```
关键决策:
1. **路径因机器而异的工具**才配置变量;Windows 自带目录优先由 `%WINDIR%`、`%ProgramFiles%` 等系统变量推导。
2. **显式变量有最高优先级**。变量已设置但文件不存在时应报错,不可悄悄回退到另一版本/另一安装路径,否则容易构建或运行错工具。
3. Keil 与 ST-LINK 属必需工具,最终要求通过变量显式指定;不保留 `C:\Keil_v5` 或 `C:\Program Files (x86)\...` 这类机器默认值作为永久兜底。
4. 可从 PATH 或官方探测器可靠发现的工具(如 `cppcheck`、`dot`、Visual Studio)允许自动发现;变量用于覆盖非标准安装位置。
5. 本地开发者变量与 Gitea runner 服务变量分开管理。runner 当前以 **SYSTEM** 运行,普通开发者的用户级变量不会自动传给它。
6. 该方案仅配置“工具地址”,不改变工具版本、Keil 工程、下载参数、串口端口或产品代码。
---
## 2. 当前路径耦合盘点
下表区分**脚本运行时实际硬编码**和仅存在于说明/注释里的机器示例。实施时先处理运行时路径,文档示例随后同步。
| 工具/路径 | 当前耦合点 | 影响 | 目标变量/策略 |
|---|---|---|---|
| Keil UV4 | `MDK-ARM/build.bat`、`MDK-ARM/download.bat` 写死 `C:\Keil_v5\UV4\UV4.exe`;`MDK-ARM/_build.cmd` 也有同一路径 | 更换盘符/Keil 安装目录后构建、下载失败 | `DTU_KEIL_UV4`:UV4.exe 完整路径;显式配置,无永久 C 盘兜底 |
| ST-LINK CLI | `MDK-ARM/reset.bat` 写死 ST-LINK Utility 下的 CLI 完整路径 | 不同 Utility 版本/安装目录下复位、烧录、回读命令失败 | `DTU_STLINK_CLI`:`ST-LINK_CLI.exe` 完整路径 |
| Python(pre-commit 环境) | `scripts/ci_local.py`、`.gitea/workflows/ci.yml` 在候选列表中写死 `C:\ProgramData\anaconda3\python.exe` | Python 发行版、用户目录、CI 运行账户改变后路径失效 | `DTU_PRECOMMIT_PYTHON`:含 `pre_commit` 模块的 Python 完整路径;其余优先尝试当前解释器、仓库 `.venv`、PATH |
| Graphviz | `tools/refgraph/gen_refgraph.py` 在 PATH 检查后枚举两个 `C:\Program Files...\dot.exe` | 非默认安装目录无法渲染图 | `DTU_GRAPHVIZ_DOT`:`dot.exe` 完整路径;未设时只从 PATH 查找,允许按当前工具语义跳过渲染 |
| MSVC `cl.exe` | `test/host/common/unit_test_harness.py` 和 CI workflow 分别维护 VS2019/2022/2026 安装根列表 | 自定义 VS 目录/只安装特定 edition 时主机单测漏检工具链 | `DTU_MSVC_CL`:x64 `cl.exe` 完整路径;保留版本 glob/自动探测作未配置时回退 |
| Windows SDK | `unit_test_harness.py` 写死 `C:\Program Files (x86)\Windows Kits\10` | Windows 安装目录不在默认盘时找不到 include/lib | `DTU_WINDOWS_KITS_ROOT`:`Windows Kits\10` 根目录;未设置则从系统注册信息/已知 SDK 位置自动发现 |
| Visual Studio 定位器 | `simulator/build_sim.ps1` 已读 `%ProgramFiles(x86)%`,但仍有 `C:\Program Files (x86)` 字面回退,并据此拼 `vswhere.exe` | 非默认 Program Files 目录或自定义 installer 布局下 VS 探测失败 | `DTU_VSWHERE`:`vswhere.exe` 完整路径;未设时由 `%ProgramFiles(x86)%` 推导并清晰失败,不保留固定 C 盘值 |
| Cppcheck(CI) | `.gitea/workflows/ci.yml` 有 PATH 探测,但回退到 `C:\Program Files\Cppcheck\cppcheck.exe` | runner 安装位置不同会导致 L0 job 失败 | `DTU_CPPCHECK`:`cppcheck.exe` 完整路径;优先变量,未设时 `Get-Command`/PATH |
| 字体系统目录 | `tools/font_gen/make_font.py` 默认字体写死 `C:\Windows\Fonts\simsun.ttc` | Windows 非 C 盘系统目录时默认字体定位失败 | 不另设 DTU 变量:改由 `%WINDIR%\Fonts\simsun.ttc` 推导;现有 `--font` 参数仍优先 |
| 工程/构建产物 | `.bat` 中 `%~dp0`、Python 中 `Path(__file__)` 解析的 `.uvprojx`、HEX、日志、仓库文件路径 | 不是本机工具安装路径 | **保持原样**,不可错误改成 DTU 变量 |
> `MDK-ARM/_build.cmd` 已在实施时确认**全库无调用者**(仅本文档提及),按"优先删除/退役"执行:2026-10-02 已删除。
### 2.1 不纳入首轮的项目
- `cmake`、`node`、`npm`、`lv_font_conv`、`pre-commit` 命令本身已有 PATH/项目环境解析;除非后续发现非标准安装确实需要路径覆盖,不再各造一组变量。
- `simulator/build_sim.ps1` 的生成器和版本选择已通过 `vswhere` 探测,不应改成固定某个 VS 版本目录。
- `.gitea/workflows/ci.yml` 内 Windows PowerShell 的系统路径/runner workspace 路径属于运行平台接口或 workflow 工作目录,不是开发机工具安装目录。
- `C:\ProgramData\anaconda3` 的 README/文档示例、Keil/ST-LINK 文档示例及 `AGENTS.md` 中路径说明,不是脚本解析逻辑,但实施完成后必须逐项改成环境变量示例,避免读者继续复制硬编码路径。
---
## 3. 建议变量清单与语义
> 本文档描述项目的本机工具路径环境变量机制:变量清单、解析与失败语义、各级配置方法、验收判据
> (2026-10-02 实施并生效;实施过程与后续变更见文末变更记录)。
> **约束(现行)**:只用进程/用户/CI 服务环境变量配置本机差异;不提交本机路径,不引入 `.env`/`python-dotenv`,
> 不把个人工具路径写入共享 workflow;仓库内部路径继续相对脚本/仓库根解析。
## 1. 变量清单
| 变量 | 必需性 | 值的形态 | 使用者 | 默认/回退 |
|---|---|---|---|---|
| `DTU_KEIL_UV4` | MCU 构建/Keil 下载机必需 | UV4.exe 完整路径,例如 `D:\Tools\Keil\UV4\UV4.exe` | `build.bat`、`download.bat`、`_build.cmd`(若保留) | 不设即报错;不从 C 盘旧路径猜测 |
| `DTU_STLINK_CLI` | 使用 ST-LINK CLI 的机器必需 | `ST-LINK_CLI.exe` 完整路径 | `reset.bat` 及回读/烧录调用入口 | 未设可尝试 `where ST-LINK_CLI.exe`;找不到即报错 |
| `DTU_PRECOMMIT_PYTHON` | 有多个 Python 且 pre-commit 不在当前解释器时建议设置;CI runner 建议必设 | `python.exe` 完整路径,且必须能成功执行 `-m pre_commit --version` | `scripts/ci_local.py`、CI L0/L0.5 Python 选择 | 当前解释器 → 仓库 `.venv` → PATH `python`;删除 Anaconda 固定路径 |
| `DTU_GRAPHVIZ_DOT` | 可选 | `dot.exe` 完整路径 | `tools/refgraph/gen_refgraph.py` | PATH `dot`;找不到时保持现有“只生成 .dot、不渲染”的可降级语义 |
| `DTU_MSVC_CL` | 可选;本地 L0.5/CI L0.5 要运行时需可发现 | x64 `cl.exe` 完整路径 | `test/host/common/unit_test_harness.py`、CI 环境预检 | 未设时使用 VS 自动探测;不能把 x86 `cl.exe` 误作目标 |
| `DTU_WINDOWS_KITS_ROOT` | 可选;主机侧 C 单测依赖 Windows SDK 时需发现 | `Windows Kits\10` 根目录(不是某一版本 Include 子目录) | `unit_test_harness.py`、CI 探测 | 未设时从系统变量/注册表或 `%ProgramFiles(x86)%` 推导默认安装根 |
| `DTU_VSWHERE` | 可选 | `vswhere.exe` 完整路径 | `simulator/build_sim.ps1`、如需则 CI | 未设时按 `%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe` 查找 |
| `DTU_CPPCHECK` | 可选;无 PATH 的 CI runner 建议设置 | `cppcheck.exe` 完整路径 | `.gitea/workflows/ci.yml` 预检;若需供 pre-commit 直接调用则同时把其目录加入 PATH | 未设时 `Get-Command cppcheck` / PATH;找不到即失败 |
**变量值只存路径本身**,不要在环境变量值外层包含引号。例如变量值是 `D:\Tools\Keil MDK\UV4\UV4.exe`,调用方负责在命令行中加引号。
### 3.1 Python 优先级特别说明
`DTU_PRECOMMIT_PYTHON` 表示“装有 pre-commit 的解释器”,不是项目默认 Python,也不替代仓库 `.venv`:
1. 若显式设置该变量,先检查文件存在并验证 `-m pre_commit --version`;**无效就报配置错误**,不静默使用别的解释器。
2. 未设置时依次探测调用脚本的 `sys.executable`、仓库 `.venv\Scripts\python.exe`、PATH 中 Python。
3. 不再写死 Anaconda 路径;需要使用 Anaconda 的机器通过变量显式指定它。
4. 字体等依赖项目 requirements 的脚本仍使用 `.venv\Scripts\python.exe`;不要让机器级变量覆盖该项目环境。
---
## 4. 解析与失败语义
所有调用端按同一原则实现,减少 BAT、Python、PowerShell 三种逻辑相互不一致:
### 4.1 显式值校验
- 环境变量不存在/空白:走该工具允许的 PATH 或系统发现逻辑。
- 环境变量非空:去除外围空格后按**字面路径**读取;先检查文件/目录类型是否正确。
- 显式路径不存在、不是预期工具或执行版本检查失败:输出 `ENV_ERROR`,指出变量名、收到的路径和示例设置方式,返回非零;**不得悄悄回退**。
- 可选工具 Graphviz 例外:变量未设且 PATH 未命中时,可按现状降级“不渲染”;但变量显式设置错误仍应报错,避免用户以为覆盖配置已生效。
### 4.2 Windows 命令行要求
- BAT 用 `set "NAME=value"` 设置局部变量、用 `"%NAME%"` 调用带空格路径的 exe。
- PowerShell 通过 `$env:DTU_...` 读取;调用 exe 用 `& $exePath ...`。
- Python 通过 `os.environ.get("DTU_...")` 读取,命令参数保持 list 传给 `subprocess.run`,不要拼 shell 字符串。
- 环境变量中不包引号;对空值、前后空格、相对路径的处理要统一。建议要求工具路径使用**绝对路径**,减少当前工作目录依赖。
- 变量名大小写按 `DTU_UPPER_SNAKE_CASE`;Windows 对环境变量名大小写不敏感。
---
## 5. 本机如何配置
### 5.1 当前 PowerShell 会话(即时生效,适合试配)
| `DTU_KEIL_UV4` | MCU 构建/下载机必需 | UV4.exe 完整路径,例如 `D:\Tools\Keil\UV4\UV4.exe` | `build.bat`、`download.bat` | 不设即报错(exit 2);不从 C 盘旧路径猜测 |
| `DTU_STLINK_CLI` | 复位/烧录/回读机必需 | `ST-LINK_CLI.exe` 完整路径,例如 `C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ST-LINK_CLI.exe` | `reset.bat` | 未设时回退 PATH(`where ST-LINK_CLI.exe` 首个命中);已设但无效 = 硬报错 |
| `DTU_PRECOMMIT_PYTHON` | 可选(覆盖用) | 含 `pre_commit` 模块的 `python.exe` 完整路径 | `ci_local.py` L0、CI `l0-gates` | 未设时按 §1.1 探测(当前解释器 → `.venv` → PATH);已设但无效 = 硬报错 |
| `DTU_GRAPHVIZ_DOT` | 可选(覆盖用) | `dot.exe` 完整路径 | `gen_refgraph.py` | 未设时只查 PATH;无 Graphviz 时降级为"生成 .dot/.json、跳过渲染" |
| `DTU_MSVC_CL` | 可选(覆盖用) | x64 `cl.exe` 完整路径(`bin\Hostx64\x64` 下) | `unit_test_harness.py` L0.5、CI `l05` | 未设时按 VS 安装根自动探测(2019/2022/2026 各 edition);已设但不符 `bin\Hostx64\x64\cl.exe` = 硬报错 |
| `DTU_WINDOWS_KITS_ROOT` | 可选(覆盖用) | `Windows Kits\10` 根目录(须含 `Include`/`Lib`) | `unit_test_harness.py` L0.5、CI `l05` | 未设时从 `%ProgramFiles*%` 推导根自动探测;已设但无 `Include`/`Lib` = 硬报错 |
| `DTU_VSWHERE` | 可选(覆盖用) | `vswhere.exe` 完整路径 | `build_sim.ps1` | 未设时用 `%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe` 推导;已设但无效 = 硬报错 |
| `DTU_CPPCHECK` | 可选(覆盖用) | `cppcheck.exe` 完整路径 | CI `l0-gates` cppcheck 步骤 | 未设时用 PATH(`Get-Command`);已设但无效 = 硬报错。本地 `ci_local.py` L0 不读该变量:cppcheck 钩子按 pre-commit `entry: cppcheck` 从 PATH 解析 |
> 变量值只存路径本身(不加引号);可执行文件变量存 `.exe` 完整路径,目录变量(Kits 根)存目录。
> 不设任何变量时全部走自动发现(PATH / 系统目录推导 / `.venv` / `vswhere`);变量只用于覆盖非标准安装位置。
> 字体系统目录(`simsun.ttc`)不设 DTU 变量:由 `%WINDIR%\Fonts\` 推导,`make_font.py` 的 `--font` 参数仍最高优先。
### 1.1 Python 优先级特别说明(`ci_local.py` / CI L0)
`pre-commit` 是门禁的**执行环境**而非"工具地址",优先级与其余工具不同:
1. 显式 `DTU_PRECOMMIT_PYTHON`(若设置,必须可执行且能 `import pre_commit`,否则报错);
2. 当前解释器(`sys.executable`,即实际运行 `ci_local.py` 的 Python);
3. 仓库 `.venv\Scripts\python.exe`(若存在且装了 pre-commit);
4. PATH 中的 `python`。
CI 侧同理:`DTU_PRECOMMIT_PYTHON` → runner PATH → workspace `.venv`。
## 2. 解析与失败语义(所有调用端统一)
1. **显式值校验**:变量已设置时,先校验其指向的文件/目录真实存在且符合形态(如 `cl.exe` 必须位于 `bin\Hostx64\x64\` 下);无效则**立即报错**,错误信息必须包含变量名与所给值,**不得静默回退**到自动发现。
2. **未设置才自动发现**:PATH / 系统目录推导 / `.venv` / `vswhere` 等;自动发现失败按各工具既有降级或报错语义处理。
3. **BAT 实现约束**:`.bat` 中读取环境变量用 `%DTU_...%`;判空用 `if defined`;错误分支 `exit /b` 非零。BAT 内解析一律平铺 `goto` 标签风格,不用括号块(`echo )` 会提前闭合块)。
4. **PowerShell 实现约束**:`$env:DTU_...`;`build_sim.ps1` 的 CMake 配置不直接读环境变量(保持生成器无关)。
5. **workflow run 块**:`ci.yml` 的 run 块内用 `${env:DTU_...}`(未设置时为空串)与 PowerShell `$env:DTU_...` 判空,**不得**在 workflow 文件里写死任何本机绝对路径。
6. **Windows 命令行引号规则**:值含空格(如 `C:\Program Files (x86)\...`)时,调用端必须整体加引号(`"%DTU_KEIL_UV4%"` / `"& $env:DTU_..."`);变量值本身**不要**带引号。
7. **系统变量推导**:`%WINDIR%`、`%ProgramFiles%`、`%ProgramFiles(x86)%` 仅用于推导(如 `make_font.py` 的 `simsun.ttc`、`build_sim.ps1` 的 vswhere 路径),不得作为"工具安装目录"的硬编码兜底。
## 3. 本机配置方法
### 3.1 当前 PowerShell 会话(立即生效,适合试配置)
```powershell
$env:DTU_KEIL_UV4 = 'D:\Tools\Keil\UV4\UV4.exe'
$env:DTU_STLINK_CLI = 'D:\Tools\STLink\ST-LINK_CLI.exe'
$env:DTU_PRECOMMIT_PYTHON = 'D:\Python\python.exe'
$env:DTU_GRAPHVIZ_DOT = 'D:\Tools\Graphviz\bin\dot.exe'
$env:DTU_MSVC_CL = 'D:\VS\VC\Tools\MSVC\<版本>\bin\Hostx64\x64\cl.exe'
$env:DTU_WINDOWS_KITS_ROOT = 'D:\Windows Kits\10'
$env:DTU_VSWHERE = 'D:\VS Installer\vswhere.exe'
$env:DTU_CPPCHECK = 'D:\Tools\Cppcheck\cppcheck.exe'
# 仅当前会话有效;换终端/重启即失效
$env:DTU_KEIL_UV4 = 'D:\Tools\Keil\UV4\UV4.exe'
$env:DTU_STLINK_CLI = 'D:\Tools\ST-LINK Utility\ST-LINK_CLI.exe'
# 验证:Test-Path $env:DTU_KEIL_UV4 → True
```
设置后仅影响**当前 PowerShell 及其子进程**。批处理、Python、CI job 都继承该环境(但已启动的进程不会自动刷新)。
### 5.2 用户级永久配置(开发者日常机)
建议先在当前会话试跑验证,再写用户级变量:
### 3.2 用户级持久配置(日常开发机,推荐)
```powershell
[Environment]::SetEnvironmentVariable('DTU_KEIL_UV4', 'D:\Tools\Keil\UV4\UV4.exe', 'User')
[Environment]::SetEnvironmentVariable('DTU_STLINK_CLI', 'D:\Tools\STLink\ST-LINK_CLI.exe', 'User')
[Environment]::SetEnvironmentVariable('DTU_PRECOMMIT_PYTHON', 'D:\Python\python.exe', 'User')
# 当前用户、全部新进程可见;无需管理员
[Environment]::SetEnvironmentVariable('DTU_KEIL_UV4', 'D:\Tools\Keil\UV4\UV4.exe', 'User')
[Environment]::SetEnvironmentVariable('DTU_STLINK_CLI', 'D:\Tools\ST-LINK Utility\ST-LINK_CLI.exe', 'User')
# 已存在同名值时直接覆盖;删除用 [Environment]::SetEnvironmentVariable('DTU_KEIL_UV4', $null, 'User')
# 设置后需重开终端/IDE 才对新进程生效
```
其他可选变量按实际使用补充。写入用户级变量后,**关闭并重新打开终端/IDE**再验证;无需管理员权限,也不建议把开发工具路径写进系统级 PATH。
验证例:
### 3.3 Gitea Windows runner(SYSTEM 服务)
```powershell
$env:DTU_KEIL_UV4
Test-Path -LiteralPath $env:DTU_KEIL_UV4
& $env:DTU_KEIL_UV4 -?
# 必须管理员;写入机器级(Machine)环境,供 Gitea runner 服务(SYSTEM 账户)读取
[Environment]::SetEnvironmentVariable('DTU_PRECOMMIT_PYTHON', 'C:\ProgramData\anaconda3\python.exe', 'Machine')
[Environment]::SetEnvironmentVariable('DTU_CPPCHECK', 'C:\Program Files\Cppcheck\cppcheck.exe', 'Machine')
# 写入后需重启 Gitea runner 服务/任务才能带上新变量(服务启动时读取环境变量快照)
```
如 `DTU_PRECOMMIT_PYTHON` 已配置,再验证:
```powershell
& $env:DTU_PRECOMMIT_PYTHON -m pre_commit --version
```
### 5.3 Gitea Windows runner(SYSTEM 服务)
当前 workflow 的 runner 以 **SYSTEM** 身份运行。开发者的用户级变量对该服务不可见;不能只在登录账号里执行 `setx` 后就假定 CI 会读取。
建议顺序:
1. 在 runner 主机用**管理员权限**设置机器级环境变量,或在服务启动配置中注入变量;只为 CI 所需工具配置 `DTU_PRECOMMIT_PYTHON`、`DTU_CPPCHECK`、`DTU_MSVC_CL`、`DTU_WINDOWS_KITS_ROOT`。
2. 重启 runner 服务,使服务进程继承新环境;不把个人开发机的 Keil/ST-LINK 路径放入共享 workflow。
3. workflow 的 PowerShell 环境自检打印变量是否设置、目标文件是否存在、工具版本;**避免打印整份环境变量**。
4. CI runner 路径不同于开发机是预期情况;workflow 只消费 `DTU_*` 接口及 PATH,不写任何特定用户目录或固定盘符。
> 安全:这些变量是路径而不是凭据。不得在变量中存放 token、密码或私钥;CI 日志只打印工具路径和版本,不输出无关环境变量。
---
## 6. 代码改造映射(2026-10-02 已实施完毕)
| 顺序 | 文件 | 计划改造 | 验证方式 |
|---|---|---|---|
| 1 | `MDK-ARM/build.bat` | 用 `DTU_KEIL_UV4` 替换绝对路径;缺失/无效时给设置提示;UV4 单实例警告和 build log 判据保持不变 | 未设置变量时明确失败;有效路径下 `@build` 0/0;路径含空格测试 |
| 2 | `MDK-ARM/download.bat` | 同一变量调用 UV4;保留项目/日志目录的 `%~dp0` 相对定位 | 不烧录的预检可单测;有 MCU 后才允许验证下载功能 |
| 3 | `MDK-ARM/reset.bat` | `DTU_STLINK_CLI` 替代写死地址;保留 `-Rst -Run` 等已验证参数与现有命令行为 | `list`/帮助命令和缺路径负测;烧录/复位须在用户明确要求且有实机后测 |
| 4 | `MDK-ARM/_build.cmd` | 确认是否仍使用;保留则改用 `DTU_KEIL_UV4` 或转调 `build.bat`,否则退役 | 全库搜索确认无其他调用者 → **已确认零调用,文件已删除** |
| 5 | `scripts/ci_local.py` | `_resolve_python()` 接受 `DTU_PRECOMMIT_PYTHON`;删除 Anaconda 硬编码候选及过时提示;验证显式值可用 | 设置有效/无效/未设置变量三组测试;`ci_local.py --l0-only` |
| 6 | `.gitea/workflows/ci.yml` | Python 和 cppcheck 使用 runner 环境变量优先 + PATH 发现;删除 Anaconda/Cppcheck 固定目录;L0.5 与 Python 探测顺序同步 | CI runner SYSTEM 环境预检;L0、L0.5 job 全绿 |
| 7 | `tools/refgraph/gen_refgraph.py` | `DTU_GRAPHVIZ_DOT` 优先,其次 `shutil.which("dot")`;移除两条固定 Graphviz 路径 | 临时变量有效/无效/不设置三态;无 dot 时 `.dot` 仍产出 |
| 8 | `test/host/common/unit_test_harness.py` | 优先采用 `DTU_MSVC_CL` 和 `DTU_WINDOWS_KITS_ROOT`;未设置时由 VS/SDK 发现逻辑取代静态盘符列表 | 当前 MSVC、定制安装路径、缺工具三类环境测试;现有 L0.5 全部通过 |
| 9 | `simulator/build_sim.ps1` | 允许 `DTU_VSWHERE` 覆盖;默认用 `%ProgramFiles(x86)%` 推导,不写死 `C:\Program Files (x86)` | 定制路径与标准安装路径探测;模拟器构建通过 |
| 10 | `tools/font_gen/make_font.py` | 默认字体根改成 `WINDIR` 环境值;保留 `--font` 显式覆写 | Windows 系统盘非 C 盘模拟/路径不存在提示;字体生成回归 |
| 11 | `AGENTS.md`、`MDK-ARM/README.md`、环境部署/工具说明 | 把实际路径示例改成变量名和配置步骤;注明改造已完成/仍待完成,避免旧说明与行为冲突 | `doc-links`、机器路径扫描、全量 pre-commit |
> 工作流中的运行块要求纯 ASCII(Windows PowerShell 5.1 编码约束);改 `.gitea/workflows/ci.yml` 时保持该约束。
---
## 7. 分阶段落地与验收
### 阶段 A:只读盘点与变量契约冻结
- 确认 `MDK-ARM/_build.cmd` 的调用关系;全库搜索绝对工具路径和对应的文档说明。
- 冻结 §3 变量名、值格式、必选/可选语义;确认 runner SYSTEM 账户能读到所需变量。
- 输出仅变更文件清单,不改工具行为前先做 review。
**出口**:工具路径没有遗漏;变量不与系统/其他项目冲突;明确每个变量由开发者、系统管理员或 runner 管理员配置。
### 阶段 B:调用端解析器与本地验证
- 先改 BAT/Python/PowerShell 的路径读取,显式错误路径要 fail-fast。
- 增加/扩充可离线自动化检查:变量未设置、合法路径含空格、显式路径错误、PATH 回退、可选工具缺失。
- 把旧绝对路径回退仅作为**短期迁移兼容**(如确需保留,必须打印 deprecated warning 和移除日期);完成机器配置后在同一改造周期删掉,不能长期留作第二套真相。
**出口**:路径解析单测/负测通过;主机侧单测、静态门禁、模拟器构建未回归;所有脚本错误信息可执行。
### 阶段 C:逐机器配置与构建验证
1. 在开发机设置当前会话变量并做 `@build`、本地主机单测、refgraph、模拟器的离线验证。
2. 设置用户级永久变量,重开终端复验;不配置的可选工具仍能通过 PATH 或降级策略工作。
3. 配置 Gitea runner SYSTEM 服务环境并重启服务,跑 CI 的 L0 和 L0.5 两个 job。
4. 对 `DTU_STLINK_CLI` 只验证 `-List`/读取版本等无破坏性探测;**烧录/复位验证不属于本次环境变量改造的必需项**,没有实机时不执行。
**出口**:至少两台不同安装路径的 Windows 环境验证通过;CI job 成功;源码及 workflow 不再含活跃的特定用户路径/工具安装路径。
### 阶段 D:清理旧约束
- 更新 `docs/环境与部署/项目部署环境要求.md`、`MDK-ARM/README.md`、`AGENTS.md`、ST-LINK/串口/CI 相关工具说明。
- 删除已确认无调用者的旧入口或机器路径 fallback。
- `pre-commit run --all-files`、`scripts/ci_local.py`、`@build` 通过;CI 两 job 全绿。
- `git grep` 检查剩余绝对路径:允许 Windows 系统变量推导、示例路径(明确标注示例)、第三方/硬件/测试数据;不允许活跃工具调用继续依赖开发者机器盘符。
**最终验收**:新电脑仅需按 §5 配置本机环境变量(加装版本要求的工具),clone 仓库后不修改 `.bat/.py/.ps1/.yml` 中的本机路径即可运行对应开发命令。
---
## 8. 风险与边界
| 风险 | 缓解措施 |
|---|---|
| 显式变量拼错,脚本仍自动挑到别的工具版本 | 显式配置无效时立即报错,不做静默回退;预检输出最终解析路径与版本 |
| 环境变量已更新但 IDE/runner 仍持有旧快照 | 说明设置后需重启终端/IDE/runner 服务;CI 加启动时自检 |
| Keil 与 ST-LINK 路径含空格 | BAT 调用始终完整双引号包裹;加入路径含空格测试 |
| Gitea runner 作为 SYSTEM 导致用户变量不可见 | 通过机器级或服务级变量注入,并重启 runner;workflow 报告变量缺失,不猜个人目录 |
| MSVC/SDK 版本布局差异 | 显式 `DTU_MSVC_CL` + SDK 根目录可覆盖;自动发现作为 fallback;检查 x64 Host 编译器与 SDK include/lib 均齐全 |
| 文档已改但代码还没实现,用户误以为路径已经可配置 | 文档开头标明“规划稿、未实施”;阶段完成后更新状态,不提前改写当前事实为完成 |
| 过度配置造成环境变量泛滥 | 只为实际机器路径变量化;项目相对路径、PATH 可发现工具、OS 系统目录不重复配置 |
---
## 9. 后续任务拆分(实现阶段)
1. **统一变量接口与解析行为**(`DTU_` 前缀、必选/可选、fail-fast 规则)。
2. **改造 MCU 工具入口**(Keil UV4 / ST-LINK CLI / 遗留 `_build.cmd`)。
3. **改造 Python/主机工具发现**(pre-commit Python / MSVC / Windows SDK / Graphviz / 字体目录)。
4. **改造 CI runner 环境解析**(移除 Anaconda/Cppcheck/VS 的具体安装路径,SYSTEM 服务注入变量)。
5. **本地与第二台机器验证并清理旧路径**(代码、workflow、`AGENTS.md`、部署与工具文档一起收口)。
> 本文冻结方案并已实施(2026-10-02):上述代码改造全部完成并通过本机全链路验证;
> runner 侧 CI 全绿待新 workflow 推送远程后触发(见变更记录)。实施期遵守项目安全限制:没有 MCU 时不运行下载/烧录/复位动作。
> 注意:runner 以 SYSTEM 运行,**用户级变量对 runner 不可见**;反之机器级变量对交互用户可见但不应依赖。开发机日常配置用 User 级,runner 专用覆盖用 Machine 级。
> 值示例中的 `C:\ProgramData\anaconda3\...` 仅演示"显式覆盖"形态;若 runner 的 PATH/`.venv` 可自动发现,则不必设置该变量。
## 4. 验收判据
- 新电脑只配置本机 `DTU_*` 环境变量(§3),clone 仓库后可直接运行各开发命令,**不修改任何脚本/工作流中的本机路径**。
- 显式变量指向无效路径时,命令以非零退出码失败且错误信息指明变量名,不静默使用其他工具。
- 仓库内不出现提交的本机绝对工具路径(文档中的示例路径除外)。
- 跨机验证操作清单见 `项目部署环境要求.md` §2.12;runner 侧机器级变量设置见 `Gitea_Runner部署指南.md` §5.1.3。
---
## 变更记录
| 日期 | 变更 |
|---|---|
| 2026-10-02 | **实施完成**:阶段 A~D 落地。① 10 处调用点全部改为"`DTU_*` 变量优先 + 自动发现回退"(显式值无效 = 硬报错、不静默回退):`build/download/reset.bat`(goto 标签式解析,纯 ASCII)、`ci_local.py`(`DTU_PRECOMMIT_PYTHON` 严格校验)、`ci.yml`(`DTU_PRECOMMIT_PYTHON`/`DTU_CPPCHECK`/`DTU_MSVC_CL`/`DTU_WINDOWS_KITS_ROOT`,run 块纯 ASCII)、`gen_refgraph.py`(`DTU_GRAPHVIZ_DOT`→PATH,保留无渲染降级)、`unit_test_harness.py`(`DTU_MSVC_CL`/`DTU_WINDOWS_KITS_ROOT` + `%ProgramFiles*` 推导取代静态盘符列表)、`build_sim.ps1`(`DTU_VSWHERE`→`%ProgramFiles(x86)%` 推导,去字面 C 盘回退)、`make_font.py`(`%WINDIR%` 推导);`_build.cmd` 确认零调用后删除。② 本机按 §5.2 配置用户级 `DTU_KEIL_UV4`/`DTU_STLINK_CLI`(其余工具本机均可自动发现,未设变量),验证:`@build` BUILD_OK 0/0、`ci_local.py` L0 15 钩子 + L0.5 278/278 断言全绿、refgraph 重生成(含修复 `引用关系图.json` 末尾换行缺失导致的 end-of-file-fixer 抖动,生成器补 `f.write("\n")`)、`build_sim.ps1` vswhere 推导命中 VS2026(当时模拟器 CMake 配置期暴露**既有**问题:`App/cfg_file.c` 已移入 `App/cfg/` 但 `simulator/CMakeLists.txt` 未同步——与环境变量改造无关;2026-10-02 已修复:CMakeLists 同步 `App/cfg/` + `test/board/` 引用,模拟器全量构建通过)、`reset.bat list` 识别探针。③ 文档收口:`AGENTS.md`/`MDK-ARM/README.md`/`项目部署环境要求.md`(新增 §2.1.1)/`Gitea_Runner部署指南.md`(新增 §5.1.3 机器级变量)/`CI配置指南.md`/`pre-commit使用说明.md`/字体/测试流程/引用图说明/ST-LINK 说明/实机规划/`scripts/README.md` 共 12 篇同步为变量口径。④ `requirements.txt` 增 `pre-commit==4.6.2`(重建 `.venv` 即可跑 L0)。⑤ 全量 `pre-commit --all-files` + `ci_local.py` 通过。待办:新 workflow 推送远程后跑一次 CI 两 job 闭环验证;第二台不同安装路径机器的交叉验证(操作清单已固化入 `项目部署环境要求.md` §2.12) |
| 2026-10-02 | **文档改造**:删除规划阶段内容(设计结论、路径耦合盘点、代码改造映射、分阶段推广与验收、风险与边界、后续任务拆分),保留并重组为现行机制说明——§1 变量清单(含 Python 优先级特别说明)、§2 解析与失败语义、§3 本机配置方法(会话/用户/runner 三级)、§4 验收判据、变更记录;章节重编号,外部引用同步(`gen_refgraph.py` §3→§1、`ci_local.py` §3.1→§1.1、`Gitea_Runner部署指南.md` §5.3→§3.3) |
| 2026-10-02 | **实施完成**:阶段 A~D 落地。① 10 处调用点全部改为"`DTU_*` 变量优先 + 自动发现回退"(显式值无效 = 硬报错、不静默回退):`build/download/reset.bat`(goto 标签式解析,纯 ASCII)、`ci_local.py`(`DTU_PRECOMMIT_PYTHON` 严格校验)、`ci.yml`(`DTU_PRECOMMIT_PYTHON`/`DTU_CPPCHECK`/`DTU_MSVC_CL`/`DTU_WINDOWS_KITS_ROOT`,run 块纯 ASCII)、`gen_refgraph.py`(`DTU_GRAPHVIZ_DOT`→PATH,保留无渲染降级)、`unit_test_harness.py`(`DTU_MSVC_CL`/`DTU_WINDOWS_KITS_ROOT` + `%ProgramFiles*%` 推导取代静态盘符列表)、`build_sim.ps1`(`DTU_VSWHERE`→`%ProgramFiles(x86)%` 推导,去字面 C 盘回退)、`make_font.py`(`%WINDIR%` 推导);`_build.cmd` 确认零调用后删除。② 本机按 §3.2 配置用户级 `DTU_KEIL_UV4`/`DTU_STLINK_CLI`(其余工具本机均可自动发现,未设变量),验证:`@build` BUILD_OK 0/0、`ci_local.py` L0 15 钩子 + L0.5 278/278 断言全绿、refgraph 重生成(含修复 `引用关系图.json` 末尾换行缺失导致的 end-of-file-fixer 抖动,生成器补 `f.write("\n")`)、`build_sim.ps1` vswhere 推导命中 VS2026(当时模拟器 CMake 配置期暴露**既有**问题:`App/cfg_file.c` 已移入 `App/cfg/` 但 `simulator/CMakeLists.txt` 未同步——与环境变量改造无关;2026-10-02 已修复:CMakeLists 同步 `App/cfg/` + `test/board/` 引用,模拟器全量构建通过)、`reset.bat list` 识别探针。③ 文档收口:`AGENTS.md`/`MDK-ARM/README.md`/`项目部署环境要求.md`(新增 §2.1.1)/`Gitea_Runner部署指南.md`(新增 §5.1.3 机器级变量)/`CI配置指南.md`/`pre-commit使用说明.md`/字体/测试流程/引用图说明/ST-LINK 说明/实机规划/`scripts/README.md` 共 12 篇同步为变量口径。④ `requirements.txt` 增 `pre-commit==4.6.2`(重建 `.venv` 即可跑 L0)。⑤ 全量 `pre-commit --all-files` + `ci_local.py` 通过。待办:新 workflow 推送远程后跑一次 CI 两 job 闭环验证;第二台不同安装路径机器的交叉验证(操作清单已固化入 `项目部署环境要求.md` §2.12) |
| 2026-10-02 | 初版规划:盘点 BAT/Python/PowerShell/Gitea workflow 中机器相关工具路径;定义 `DTU_*` 变量清单、优先级、用户级与 SYSTEM runner 配置边界;规划 4 阶段迁移及离线/实机验收范围。未改工具调用代码 |
+1 -1
View File
@@ -50,7 +50,7 @@ def _resolve_python():
r"""挑一个真正装了 pre-commit 的解释器。
本机可能有多个 python(.venv / 发行版 / 系统),而 **pre-commit 只装在其中一个**。
按优先级探测(见 docs/环境与部署/本地工具路径环境变量方案.md §3.1):
按优先级探测(见 docs/环境与部署/本地工具路径环境变量方案.md §1.1):
1. DTU_PRECOMMIT_PYTHON(显式配置:文件缺失或无 pre-commit 模块 → 立即报
配置错误,**不静默回退**到别的解释器)
2. 当前解释器(sys.executable)
+1 -1
View File
@@ -450,7 +450,7 @@ def find_dot() -> str | None:
显式变量已设置则严格使用(无效立即报错,不静默回退);未设置时只查
PATH,未找到返回 None 并降级为"只生成 .dot、不渲染"(保持既有语义)。
见 docs/环境与部署/本地工具路径环境变量方案.md §3。
见 docs/环境与部署/本地工具路径环境变量方案.md §1。
"""
explicit = os.environ.get("DTU_GRAPHVIZ_DOT", "").strip()
if explicit: