From a6013c7d22bbf7ecb611e4431b857749c7276b3f Mon Sep 17 00:00:00 2001 From: AskaEth Date: Sun, 1 Nov 2026 12:58:40 +0800 Subject: [PATCH] =?UTF-8?q?fix(ci/release):=20M50=20=E2=80=94=E2=80=94=20W?= =?UTF-8?q?indows=20=E6=A7=BD=E4=BD=8D=20dumpbin=20=E5=AE=9A=E4=BD=8D?= =?UTF-8?q?=E9=93=BE=E6=94=B9=E4=B8=89=E7=BA=A7=EF=BC=88vswhere=20?= =?UTF-8?q?=E2=86=92=20find=20=E2=86=92=20PATH=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v0.1.0 首跑(run 41273841717)windows-x64 在「Windows 单文件自检」挂 `找不到 dumpbin,无法校验导入表(静态 CRT 门禁不降级)`。两个独立根因: - `command -v dumpbin` 在 windows-latest 上不成立:VS 环境未预置进 PATH。 - 兜底 glob 深度错了一级:写的是 `/<年>/VC/Tools/...`,真实布局是 `/<年>/<版次>/VC/Tools/...`(2022/Enterprise、2022/BuildTools), 所以即便 PATH 失守、glob 也不可能命中。 - 且只扫了 64 位 `Program Files` 根,Build Tools 落在 `Program Files (x86)` 根。 改成三级定位链,全不命中才 fail(门禁语义一字未动:工具缺失仍 exit 1、 导入表出现 VCRUNTIME/MSVCP/MSVCR/ucrtbase 仍 exit 1,文案不变): 1. vswhere —— VS 官方定位器,安装器自身路径固定,与 VS 版本/版次/布局无关: `.../Installer/vswhere.exe -latest -products '*' -find `。 模式先试反斜杠(官方文档形式)、再试正斜杠,输出统一折成正斜杠后再执行。 2. find 兜底 —— 两个 VS 根(64 位 + x86)按路径模式扫,`-maxdepth 11` 留一级余量,不再依赖固定层数的 glob。 3. PATH —— 最后才试,PATH 最不可控。 另加一行 `dumpbin: <路径>(定位自 <层级>)`,下次真机挂掉能直接看出命中哪一级。 同文件其余步骤不依赖 VS 环境(已逐条核对),无需收敛。 验证(本机无 VS): - 抽出 run 块 `bash -n` 通过;13 条 stub 用例全绿:无工具→fail 文案不变且不写 dependents.txt、vswhere 反斜杠/正斜杠两个模式、两处 VS 根 find 兜底、PATH 兜底、 动态 CRT 仍 fail-closed、vswhere 优先于 PATH、vswhere 输出的反斜杠路径归一化后可执行。 - 未改写的原始 run 块在本机实跑:干净 exit 1 + 原文案,不误命中、不崩。 - yaml 解析 + 23 条结构断言全过(矩阵四槽位、触发条件、门禁 grep/文案/exit 原样); 文件 276 行 ≤ 400。 - git-bash 行为实证:`.exe` 的 `-x` 为真、非可执行文件为假、`find` 接受含空格的 `C:/Program Files` 根。 真机验证由 merge 后 retag 重跑流水线完成。 --- .github/workflows/release.yml | 44 +++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 05f2b72..b12c566 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -83,9 +83,48 @@ jobs: set -euo pipefail # +crt-static 是否真的生效,只看导入表:出现 VCRUNTIME/MSVCP/msvcr/ucrtbase 说明还得装 # 可再发行包,那就不是"单文件"了,直接 fail。 - DUMPBIN=$(command -v dumpbin || true) + # + # dumpbin 定位链(三级,全不命中才 fail —— 门禁不降级,只是把"猜路径"换成官方定位): + # ① vswhere:VS 官方定位器,安装器自身路径固定,与 VS 版本/版次/安装布局无关; + # ② find 兜底:Program Files 与 Program Files (x86) 两个 VS 根都扫(Build Tools 落在 x86 根); + # ③ PATH:镜像若已把工具链预置进 PATH 则直接可用。 + # PATH 排最后是刻意的:PATH 最不可控,官方定位器优先。 + VSWHERE="C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe" + DUMPBIN="" + VIA="" + if [ -x "$VSWHERE" ]; then + # -find 的模式优先用反斜杠(vswhere 官方文档即此形式),再试正斜杠以规避分隔符差异。 + for pattern in 'VC\Tools\MSVC\*\bin\Hostx64\x64\dumpbin.exe' \ + 'VC/Tools/MSVC/*/bin/Hostx64/x64/dumpbin.exe'; do + hit=$("$VSWHERE" -latest -products '*' -find "$pattern" 2>/dev/null | head -n1 || true) + if [ -n "$hit" ]; then + DUMPBIN=${hit//\\//} + VIA="vswhere" + break + fi + done + fi if [ -z "$DUMPBIN" ]; then - DUMPBIN=$(ls -d "C:/Program Files/Microsoft Visual Studio/"*/VC/Tools/MSVC/*/bin/Hostx64/x64/dumpbin.exe 2>/dev/null | head -n1 || true) + # 镜像里的 VS 根形如 <年>/<版次>(2022/Enterprise、2022/BuildTools……), + # 固定层数的 glob 会在 <年>/<版次> 这两级踩空,所以按路径模式扫。 + for root in "C:/Program Files/Microsoft Visual Studio" \ + "C:/Program Files (x86)/Microsoft Visual Studio"; do + [ -d "$root" ] || continue + hit=$(find "$root" -maxdepth 11 -type f \ + -path '*/VC/Tools/MSVC/*/bin/Hostx64/x64/dumpbin.exe' 2>/dev/null | head -n1 || true) + if [ -n "$hit" ]; then + DUMPBIN=$hit + VIA="find: $root" + break + fi + done + fi + if [ -z "$DUMPBIN" ]; then + hit=$(command -v dumpbin || true) + if [ -n "$hit" ]; then + DUMPBIN=$hit + VIA="PATH" + fi fi # 工具缺失同样 fail:windows-latest 自带 VS 工具链,基本找得到; # "找不到就跳过"等于让这道门禁在最需要它的时候静默失效。 @@ -93,6 +132,7 @@ jobs: echo "::error::找不到 dumpbin,无法校验导入表(静态 CRT 门禁不降级)" exit 1 fi + echo "dumpbin: $DUMPBIN(定位自 $VIA)" "$DUMPBIN" -nologo -dependents target/release/unlucky-launcher.exe | tee dependents.txt if grep -Eiq 'VCRUNTIME|MSVCP|MSVCR|ucrtbase\.dll' dependents.txt; then echo "::error::静态 CRT 未生效:exe 仍动态依赖 VC++ 可再发行包"