fix(release): M140 r1 复审三条 p2 —— vswhere -find 单值、根因措辞、SDK 双根
P2-1(真缺陷):`-find` 是单值参数,老写法 `... "${find_args[@]}"` 一次传 4 个
`-find`,官方定位器只认其中一个(复现:last-wins 下取到 Hostx64),
所以 round-1 新加的「ARM64 优先 → Hostarm64」在 vswhere 分支上从未执行。
改成每个 pattern 各起一次定位器,不赌取值规则;注释同步为真话。
P2-2(措辞):README §4 不再声称 v0.2.1 那次是「x64 镜像缺库」——windows-2025
镜像清单里 VC.Tools.ARM64 与 SDK 26100 都在,根因未定论,更像自检的路径探测;
§7.4 的 dumpbin 门禁补一句覆盖 windows-latest 与 windows-11-arm 两个镜像。
P2-3(放宽):arm64 库体检的 SDK 侧也改成两个安装根(Program Files (x86) 与
Program Files),把「路径猜错 → fail-closed 误报」这个正是本次事故的形态再降一档。
行数:release.yml 400 / README 400(均 ≤400);PUBLISH_SLOTS 未动。
This commit is contained in:
1 parent
b27e86c65b
commit
5678683561
2 files changed
+26
-25
No files matched your search
@@ -60,9 +60,8 @@ jobs:
|
||||
python3 - "$ALL_SLOTS" >> "$GITHUB_OUTPUT" <<'PY'
|
||||
import json, sys
|
||||
# 槽位表(唯一真相源)。mode:"ci" = 默认在 CI 里构建;"probe" = 未验证,仅 all_slots=true 时构建。
|
||||
# **没有一个槽位交叉编译**(M140):每槽都在**自己的架构**上原生构建,故不设 `target` 键、产物一律
|
||||
# 在 target/release。哪天再加交叉槽位,把 `target` 键、`build_dir=target/<triple>/release` 与
|
||||
# 「`rustup target add` + cargo 的 `--target`」两处一起加回来(现在它们已随最后一个交叉槽位删掉)。
|
||||
# **没有交叉槽位**(M140):每槽在自己的架构上原生构建,故无 `target` 键、产物一律在 target/release。
|
||||
# 要加回交叉槽位:`target` 键 + `build_dir=target/<triple>/release` + `rustup target add` 与 cargo 的 `--target`。
|
||||
SLOTS = [
|
||||
# Windows x64:MSVC + 静态 CRT(+crt-static)→ exe 不依赖 VC++ 可再发行包,双击即用的单文件。
|
||||
dict(slot="windows-x64", os="windows-latest", build_dir="target/release", rustflags="-C target-feature=+crt-static", mode="ci"),
|
||||
@@ -110,31 +109,30 @@ jobs:
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# (M140)windows-arm64 跑在**原生** `windows-11-arm` 上,所以本步查的是"这台机器上的 ARM64 库齐不齐":
|
||||
# `+crt-static` 要 VC 的 `lib/arm64/libcmt.lib`,链接要 SDK 的 `um/arm64/kernel32.lib`。
|
||||
# 门禁不降级(缺了就 fail),但**失败必须能自己定位**:把实际探测到的根目录 / lib 目录全打出来
|
||||
# ——原来只报"缺失",2026-11-06 第一次真跑就卡在这里,而单看日志无法判断是镜像没装还是探测写错了。
|
||||
# 两个探测还都改宽容了:VS 两个根都扫;SDK 不再只认 `tail -n1` 挑出的那一个版本,全部版本里找。
|
||||
# (M140)windows-arm64 跑在**原生** `windows-11-arm` 上,本步查"这台机器上的 ARM64 库齐不齐":
|
||||
# `+crt-static` 要 VC 的 `lib/arm64/libcmt.lib`,链接要 SDK 的 `um/arm64/kernel32.lib`。门禁不降级
|
||||
# (缺了就 fail),但失败必须能自己定位:把探测到的根目录 / lib 目录全打出来——原来只报"缺失",
|
||||
# 2026-11-06 首次真跑就卡在这里而看不出原因。宽容化:VS 与 SDK **各扫两个安装根**,SDK 全版本找。
|
||||
- name: Windows ARM64 工具链体检
|
||||
if: matrix.slot == 'windows-arm64'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
vs_roots=("C:/Program Files/Microsoft Visual Studio" "C:/Program Files (x86)/Microsoft Visual Studio")
|
||||
sdk_root="C:/Program Files (x86)/Windows Kits/10/Lib"
|
||||
# SDK 同样两个根:老安装器落在 `(x86)`,别只猜一个 —— 猜错路径就是这次事故的形态(fail-closed 误报)。
|
||||
sdk_roots=("C:/Program Files (x86)/Windows Kits/10/Lib" "C:/Program Files/Windows Kits/10/Lib")
|
||||
echo "── 探测的根目录 ──"
|
||||
for r in "${vs_roots[@]}"; do
|
||||
for r in "${vs_roots[@]}" "${sdk_roots[@]}"; do
|
||||
if [ -d "$r" ]; then echo " 有 $r"; else echo " 无 $r"; fi
|
||||
done
|
||||
if [ -d "$sdk_root" ]; then echo " 有 $sdk_root"; else echo " 无 $sdk_root"; fi
|
||||
vc_dirs=$(find "${vs_roots[@]}" -maxdepth 9 -type d -path '*/VC/Tools/MSVC/*/lib/arm64' 2>/dev/null || true)
|
||||
echo "── VC 的 arm64 lib 目录(*/VC/Tools/MSVC/*/lib/arm64)──"
|
||||
echo "${vc_dirs:- <无>}"
|
||||
sdk_dirs=$(find "$sdk_root" -maxdepth 3 -type d -path '*/um/arm64' 2>/dev/null || true)
|
||||
sdk_dirs=$(find "${sdk_roots[@]}" -maxdepth 3 -type d -path '*/um/arm64' 2>/dev/null || true)
|
||||
echo "── SDK 的 um/arm64 目录 ──"
|
||||
echo "${sdk_dirs:- <无>}"
|
||||
vc_lib=$(find "${vs_roots[@]}" -maxdepth 11 -type f -path '*/VC/Tools/MSVC/*/lib/arm64/libcmt.lib' 2>/dev/null | head -n1 || true)
|
||||
sdk_lib=$(find "$sdk_root" -maxdepth 4 -type f -path '*/um/arm64/kernel32.lib' 2>/dev/null | head -n1 || true)
|
||||
sdk_lib=$(find "${sdk_roots[@]}" -maxdepth 4 -type f -path '*/um/arm64/kernel32.lib' 2>/dev/null | head -n1 || true)
|
||||
echo "libcmt.lib: ${vc_lib:-<缺失>}"
|
||||
echo "kernel32.lib: ${sdk_lib:-<缺失>}"
|
||||
if [ -z "$vc_lib" ] || [ -z "$sdk_lib" ]; then
|
||||
@@ -169,8 +167,7 @@ jobs:
|
||||
# ① vswhere(VS 官方定位器,安装器路径固定)② find 兜底(两个 VS 根都扫,Build Tools 在
|
||||
# x86 根)③ PATH(镜像预置则直接可用;排最后是刻意的:PATH 最不可控,官方定位器优先)。
|
||||
# dumpbin 在 MSVC 的**宿主**工具目录里:x64 runner 是 `Hostx64/x64`,arm64 runner(M140)是
|
||||
# `Hostarm64/arm64`(x64 那族作为兜底,ARM64 Windows 靠模拟层跑得起来)。反向不成立 ——
|
||||
# 在 x64 runner 上挑 `Hostarm64` 只会拿到跑不起来的 arm64 二进制,所以按 RUNNER_ARCH 选。
|
||||
# `Hostarm64/arm64`(x64 那族兜底,靠模拟层能跑);反向不行——x64 上挑 Hostarm64 是跑不起来的二进制。
|
||||
pats=('VC/Tools/MSVC/*/bin/Hostx64/x64/dumpbin.exe')
|
||||
if [ "${RUNNER_ARCH:-X64}" = "ARM64" ]; then
|
||||
pats=('VC/Tools/MSVC/*/bin/Hostarm64/arm64/dumpbin.exe' "${pats[@]}")
|
||||
@@ -179,11 +176,15 @@ jobs:
|
||||
DUMPBIN=""
|
||||
VIA=""
|
||||
if [ -x "$VSWHERE" ]; then
|
||||
# -find 的模式先用反斜杠(vswhere 官方文档即此形式),再试正斜杠以规避分隔符差异。
|
||||
find_args=()
|
||||
for p in "${pats[@]}"; do find_args+=(-find "${p//\//\\}" -find "$p"); done
|
||||
hit=$("$VSWHERE" -latest -products '*' "${find_args[@]}" 2>/dev/null | head -n1 || true)
|
||||
if [ -n "$hit" ]; then DUMPBIN=${hit//\\//}; VIA="vswhere"; fi
|
||||
# `-find` 是**单值**参数:一次传多个 pattern 只有一个生效(3.x 取最后一个 —— 老写法里 Hostarm64
|
||||
# 因此永远轮不到)。所以每个 pattern 各起一次定位器,不赌它取哪个。
|
||||
# 反斜杠形态优先(vswhere 官方文档即此形式),再试正斜杠以规避分隔符差异。
|
||||
for p in "${pats[@]}"; do
|
||||
for pat in "${p//\//\\}" "$p"; do
|
||||
hit=$("$VSWHERE" -latest -products '*' -find "$pat" 2>/dev/null | head -n1 || true)
|
||||
if [ -n "$hit" ]; then DUMPBIN=${hit//\\//}; VIA="vswhere"; break 2; fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
if [ -z "$DUMPBIN" ]; then
|
||||
# VS 根形如 <年>/<版次>(2022/Enterprise、2022/BuildTools……),固定层数的 glob 会踩空,按模式扫。
|
||||
|
||||
+5
-5
@@ -135,10 +135,10 @@ Windows 为什么用 MSVC 静态 CRT 而不是本机这套 GNU 工具链:两
|
||||
产物形态与门禁跟 x64 一模一样(裸 exe + 静态 CRT + dumpbin 导入表硬门禁),差别只在**怎么编**:
|
||||
**M140 起在原生 `windows-11-arm` 上编**(GitHub 文档 2026 的 Standard runners 表明列该标签:4C/16G、
|
||||
公开仓库免费),产物落在 `target/release`(`matrix.build_dir` 注入,脚本不硬编码路径)。原路线是在
|
||||
`windows-latest` 上交叉编译到 `aarch64-pc-windows-msvc`,但**CI 上从未成功过一次**(v0.2.1 首次真跑即
|
||||
红在「ARM64 工具链体检」:x64 镜像上探不到 VC/SDK 的 ARM64 库),"双 Windows 共用一套镜像"的惯性理由
|
||||
因此不再成立。原生的附赠好处:宿主=产物架构,`ull --version` 冒烟**真跑**;M50 的 dumpbin 定位链补了
|
||||
`Hostarm64/arm64` 分支,并按 `RUNNER_ARCH` 只挑本机能执行的那族(x64 上不会挑到跑不起来的 arm64 二进制)。
|
||||
`windows-latest` 上交叉编译到 `aarch64-pc-windows-msvc`,但**CI 上从未成功过一次**(v0.2.1 首次真跑即红在
|
||||
「ARM64 工具链体检」)。那次**根因未定论**:`windows-2025` 镜像清单里 `VC.Tools.ARM64` 与 SDK 26100 都在,
|
||||
更像自检自己的路径探测有问题;无论哪种,交叉都多一层"在 x64 宿主上猜 ARM64 库路径"。原生的附赠好处:
|
||||
宿主=产物架构,`ull --version` 冒烟**真跑**;dumpbin 链补了 `Hostarm64/arm64` 分支并按 `RUNNER_ARCH` 选族。
|
||||
|
||||
运行时依赖与 x64 同表(UCRT 是 Win11 ARM 的系统组件,`+crt-static` 静态链 CRT,不需要可再发行包)。
|
||||
游戏侧如实说:**启动器原生运行**;Temurin 没有 windows-aarch64 产物,Microsoft OpenJDK 有该
|
||||
@@ -282,7 +282,7 @@ uxtheme/uiautomationcore/opengl32/ws2_32/bcrypt/bcryptprimitives/ntdll` + 一组
|
||||
`libgcc_s_*.dll` 之类 MinGW 运行时 —— 即"拷走一个 exe 就能跑"(Win10+ 自带 UCRT)。
|
||||
CI 的 MSVC `+crt-static` 产物同理(静态 CRT);`release.yml` 里用 `dumpbin -dependents` 把这条变成硬门禁,
|
||||
两侧都 fail、没有降级分支:**出现 VCRUNTIME/MSVCP/ucrtbase 就 fail**,**找不到 dumpbin 同样 fail**
|
||||
(`windows-latest` 自带 VS 工具链,基本找得到;"找不到就跳过"等于让门禁在最需要它的时候失效)。
|
||||
(`windows-latest` 与 `windows-11-arm` 两个镜像都自带 VS 工具链,基本找得到;跳过等于让门禁在最需要它时失效)。
|
||||
总之不允许"悄悄要用户装可再发行包"。
|
||||
注意:本机只装了 GNU 工具链,MSVC 那个槽位的产物本身**没有在本机验证过**,由 CI 首跑验证。
|
||||
|
||||
|
||||
Reference in new issue
Block a user