胡飞
|
512957924d
|
fix(release): 修掉 macOS 独立产品打包名与 Windows 资源段两处发版失败
beta.4 的构建全部通过,但打包阶段失败,两处都不是编译问题:
1) macOS 独立产品:`Resolve platform matrix` 用 `tr ' ' ','` 把两个矩阵拼在
一起,`bundle_name` 里的空格被当成逗号,产物目录变成 `Navop,Shell.app`,
随后的 `tar` 找不到包。改用参数展开各去一层方括号,字节原样保留。
2) Windows 全部四个 job:`navop.exe` 没有 `.rsrc`,校验步骤报
「不可能携带内嵌清单」。产品拆分后资源嵌入留在 `crates/navop_app/build.rs`,
而它现在是库:`cargo:rustc-link-arg` 只作用于本包 targets,嵌出来的资源
到不了 `apps/navop*` 的 exe。改为三个二进制 crate 各自的 build.rs 调用
共享的 `resources/windows/embed_app_resources.rs`。
顺带把这两类回归纳入 `script/test-release-packaging.mjs`:拼接矩阵的脚本会被
真实执行并断言 14 条条目与带空格的 bundle_name;同时断言资源嵌入留在二进制
crate(`crates/navop_app/build.rs` 不得存在)。44 个打包测试全绿。
|
2026-11-02 22:03:26 +08:00 |
|
胡飞
|
46a5978443
|
refactor(product-split): main 目录归位 crates/navop_app,包名统一 navop_app
产品装配移出后 main 已只剩库,却仍占着仓库根目录、与 apps/* 并列,看起来像一个
产品。本次把它落回 crate 层:
- git mv main crates/navop_app;package name 由 main 改为 navop_app(与 lib 名
一致),删掉冗余的 [lib] 块;根 members 同步。
- 三个 app 改为直接相对路径依赖 navop_app = { path = "../../crates/navop_app" },
不进 workspace.dependencies(Cargo 不允许再关继承来的 default-features)。
- 26 处逃出 crate 根的 include_str! 各加一层 ../(resources/*、core/build.rs、
apps/* 与 crates/*_view 的 Cargo.toml、app_kit 源码);build.rs 的 icon/manifest
路径同步。
- env_file.rs 与 i18n_locale_keys_contract 的「工作区根」改为上两级;
cross-crate 源码断言(core/window_close、db_view、one_ui、windows_rdp_host)指向
新路径。
- locales/main.yml 保持原名:i18n 命名空间与全仓 t!() key 绑定,改名是另一件事。
- 发布链路同步:release_pr.py(MANIFEST_PATH、lock_app_version、报错文案)、
beta-release.sh 版本包名集合、release-tag.sh / ci.yml / release.yml /
.github/RELEASE.md / AGENTS.md / CLAUDE.md 等文档的路径与 -p navop_app。
- 顺带修两处未推送提交遗留的 CI 红线:app_kit::install 的
expected_binary_name cfg 过宽(macOS dead_code)、测试里多余的
is_supported_app_bundle import;release PR 测试夹具补齐四个 manifest;
windows_rdp_host 的 ALLOWED_FILES 断言对齐 release_pr.py 现状。
验证:cargo test -p navop_app(595 lib + 4 集成契约)、-p app_kit(149)、
one-ui/windows_rdp_host 契约、三个 app cargo build、cargo check --all-targets
全通过;script/tests 32 项、release-packaging 与 scripts/ai 的 node 测试全绿。
|
2026-11-01 00:52:04 +08:00 |
|
胡飞
|
fa6ca0d1b1
|
fix(windows): 宿主自嵌 Common-Controls v6 清单,修 v0.20.1 启动即死
v0.20.1 的 Windows 产物(zip / portable / MSI 里装的是同一个 navop.exe)启动即失败:
「navop.exe - 无法找到入口 / 无法定位程序输入点 TaskDialogIndirect 于动态链接库
…\AppData\Local\Temp\navop-update\staged-<pid>-<ms>\navop.exe 上」。加载器在 `main`
之前就以 STATUS_ENTRYPOINT_NOT_FOUND(0xC0000139) 退出,所以更新表现成「什么都没发生」。
根因不是缺 comctl32.dll,而是产物**没有任何应用程序清单**:
- gpui 的 Windows 层在 `PlatformWindow::prompt` 中静态导入 `comctl32!TaskDialogIndirect`
(实测 v0.20.1 的 navop.exe:IMPORT 表里有该符号、DELAY_IMPORT 目录为空 ⇒ load-time 导入);
- 该导出只存在于 Common-Controls v6 的 SxS 程序集,只有 exe 自己的清单声明了
`Microsoft.Windows.Common-Controls 6.0.0.0` 才会激活 v6;没有清单就挂 System32 里的
5.82(不导出该符号)⇒ 加载器失败;
- 实测 v0.20.1 的 navop.exe 全文件搜 `Common-Controls` / `<assembly` /
`requestedExecutionLevel` 零命中 ⇒ 清单确实没被嵌进去。
清单的责任方在 v0.20.1 变了:`gpui-fast 0.1.8` 的 build.rs 是
`embed_resource_unless_host_provides_it()`,而 gpui-kit 声明了
`windows-manifest-provided-by-host`(`cargo tree -e features -p main -i gpui-fast` 可核)。
Cargo 特性只做并集、下游关不掉 ⇒ 这份清单只能由宿主 navop 自己提供。
v0.20.0 走旧门面 `gpui-pre`,它是无条件 embed 的,所以此前没暴露。
- `resources/windows/navop.manifest.xml`(新增):宿主清单,与上游 Zed 的
`crates/gpui/resources/windows/gpui.manifest.xml` 对齐(asInvoker + supportedOS Win10 +
Common-Controls 6.0.0.0 + `dpiAware true/pm` / `dpiAwareness PerMonitorV2` /
`heapType SegmentHeap`)。DPI 与堆这一段刻意与 v0.20.0 保持一致:gpui 两代都**不**在运行时
调 `SetProcessDpiAwareness`(全仓 grep 无命中),清单是 DPI 感知的唯一来源,漏掉会退回
DPI-unaware(高 DPI 下整窗被系统位图拉伸)。文件不带 XML 声明:winresource 是把清单按 RC
字符串逐行写成 `" <line> "`,声明前出现空白不是合法的 XML prolog。
- `main/build.rs`:加 `set_version_info(VersionInfo::FILETYPE, 1)` +
`set_manifest(include_str!("../resources/windows/navop.manifest.xml"))`。前者不是可选项 ——
winresource 只在 `VersionInfo::FILETYPE` 存在时才写清单块(`winresource-0.1.31/lib.rs:578`),
漏了会**静默不嵌清单**。用 `set_manifest` 而非 `set_manifest_file`,避开 rc 的路径转义。
- `script/validate-windows-exe.mjs`(新增):PE 层门禁,解析节表定位 `.rsrc` 并在其原始区间内查
三条必需串,另外判别「静态导入 TaskDialogIndirect 却无清单」这一真实故障组合;失败退出码 1
并打印含 `0xC0000139` 的修法。判据**必须同时搜 ASCII 与 UTF-16LE**:实测 llvm-rc 对纯 ASCII
清单写的是 8 位,MSVC rc.exe 才写 UTF-16,只搜一种编码必漏。
- `.github/workflows/release.yml`:Windows 腿在 `Build release binary (Windows)` 之后、
`Package (Windows)` 之前插入 `Validate Windows executable manifest`。这段代码在 macOS/Linux 上
根本不参与编译,而「清单没嵌进去」在编译期没有任何信号,只能在真实产物上校验。
- `script/test-release-packaging.mjs`:加合成 PE fixture(`peFixtureWithResource`)与两个用例
—— 断言清单内容、`main/build.rs` 的三处调用、workflow 步骤的存在与顺序;以及门禁对
正样本 / 负样本 / 非 PE 三种输入的退出码与报错内容。
验证(本机为 macOS,无法编译 Windows target):
- `node --test script/test-release-packaging.mjs` = 33 passed / 0 failed
- `cfg(target_os = "windows")` 块在 macOS 上不参与编译,`cargo check` 给不了信号。因此建探针
工程把 `main/build.rs` **逐字复制、只删掉那行 `#[cfg]`**,配
`[build-dependencies] winresource = "0.1"` ⇒ 该块**编译通过**(`set_version_info` /
`set_manifest` 的签名与 `winresource 0.1.31` 一致)。
- 取 winresource 真实生成的 `resource.rc` 手工喂 `llvm-rc`:退出码 0,`.res` 资源目录读出
`VERSION 1 / ICON 1..6 / GROUP_ICON 1 / RT_MANIFEST 1(1120 字节)`—— 清单落在加载器唯一认的
「type 24 / id 1」位置。
- 把该 `.res` 当 `.rsrc` 负荷塞进合成 PE:门禁判 OK;对**真实 v0.20.1 的 navop.exe** 判 FAIL
(退出码 1,报错含 `TaskDialogIndirect` 与 `0xC0000139`)。
- 未在本机验证:MSVC rc.exe / link.exe 真实产物能否正常启动、DPI 表现如何(需 Windows)。
CI 的 `windows-2022` 腿会编译这段代码。
|
2026-10-13 19:54:41 +08:00 |
|