chore(workspace): M118 —— crates/app 退出默认构建,发布改打 iced bin(Slint 版停发)
M118(D26):Slint 退役树 `crates/app` 不再进 workspace。目录与源码原样保留(不删一个文件), 只是配置上不再可编。 - 根 Cargo.toml:`[workspace] exclude = ["crates/app"]`。摘掉的是整棵 slint 1.18 + usvg 0.48 依赖树(本机单路冷编 ≈14 分钟;并行超配时表现为 rustc 退 1 且零诊断,见踩坑记录 p2 T7)。 Cargo.lock 由 cargo 自己重算:8639 → 6343 行(-2389/+93),`name = "slint"` 1→0、 `name = "i-slint` 11→0、`name = "slint-build"` 1→0。锁必须一起提交:旧锁配 `--locked` 会直接 `cannot update the lock file`(release.yml 与 ci.yml 的冒烟都带 `--locked`)。 - ci.yml:clippy/test/build 的 `--workspace` 自然不再覆盖 unlucky-app;runtime-smoke(Linux 与 macOS 探针)打的是 Slint 版 `--bin unlucky-launcher`,该 bin 已不存在 → 换成 iced 版 `unlucky-launcher-iced`(它的 cli.rs 照抄 Slint 版口径,`--data-dir` 仍被接受)。 - release.yml:**Slint 版停发**。旧写法 `--bin unlucky-launcher` 打的是 crates/app 的 bin, 也就是说流水线一直在发 Slint 版;改为 `--bin unlucky-launcher-iced --bin ull`,Windows 导入表自检的 EXE 指向构建产物 `unlucky-launcher-iced.exe`。对外产物文件名不变。 - make_artifacts.py:拆成 `LAUNCHER_BIN = "unlucky-launcher-iced"`(找产物)与 `LAUNCHER_ASSET = "unlucky-launcher"`(落盘名),tar 内文件名/权限随之按对外名走。 - guards.yml / README(中英)/ packaging/README.md:逐条写明排除后的覆盖口径,历史实现段落 全部保留并加限定语(不提供构建方式,也不暗示自救)。 门禁:fmt exit 0;clippy --workspace --all-targets -j 4 -- -D warnings exit 0(44.6s); check --workspace --all-targets exit 0(5m20s,slint 命中 0 行);cargo deny check exit 0。
This commit is contained in:
1 parent
3f228ae092
commit
cf8c6912ec
9 files changed
+230
-2430
No files matched your search
@@ -3,6 +3,12 @@ name: CI
|
||||
# 主干门禁:fmt / clippy / test / build 双平台矩阵。
|
||||
# 架构守门(core 零 UI、文件 ≤400 行、依赖许可)见 guards.yml。
|
||||
# 平台基线 Win10+(标准工具链产物),平台矩阵见 AGENTS.md §7。
|
||||
#
|
||||
# M118(D26):根 Cargo.toml 已 `exclude = ["crates/app"]`(Slint 退役树,源码原样保留)。
|
||||
# 所以本文件里所有 `--workspace` 都**不再**覆盖 `unlucky-app`:CI 不再编 slint 1.18 + usvg 0.48
|
||||
# 那棵依赖树(本机单路冷编 ≈14 分钟;并行超配时表现为 `rustc` 退 1 且零诊断,
|
||||
# 见 DevDocs/00-踩坑记录-p2.md T7)。历史实现只作源码参考,**没有构建方式**(见 README:
|
||||
# 它的 manifest 整份是 workspace 继承写法,离开 workspace 后连解析都过不了)。
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -38,7 +44,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Linux 图形栈构建依赖(winit / femtovg 编译期需要)
|
||||
- name: Linux 图形栈构建依赖(winit / wgpu 编译期需要)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
@@ -49,6 +55,8 @@ jobs:
|
||||
with:
|
||||
components: clippy
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
# `--workspace` 现在是 8 个 crate,不含 `unlucky-app`(M118 的 workspace exclude),
|
||||
# 所以这条命令不会拉起 slint / usvg / i-slint-*。
|
||||
- run: cargo clippy --workspace --all-targets -- -D warnings
|
||||
|
||||
test:
|
||||
@@ -69,6 +77,9 @@ jobs:
|
||||
libwayland-dev libxcb1-dev
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
# 同 clippy:`--workspace` 不含 `unlucky-app`(M118),Slint 退役树不再被 `--all-targets` 拉起。
|
||||
# 也因此**不要**再写 `--exclude unlucky-app`:它已不是成员,那面旗子只会打一条
|
||||
# `excluded package(s) … not found in workspace` 的警告然后空转(实测 exit 0,不报错)。
|
||||
- run: cargo test --workspace --all-targets
|
||||
|
||||
build:
|
||||
@@ -89,14 +100,19 @@ jobs:
|
||||
libwayland-dev libxcb1-dev
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
# 同上:`--workspace` 不含 `unlucky-app`(M118)。被摘掉的正是 release 档
|
||||
# (lto=fat + codegen-units=1)最贵的那棵 slint + usvg 树。
|
||||
- run: cargo build --workspace --release
|
||||
|
||||
# 运行时冒烟(M62):Linux 上**真渲染一帧**,补上「能编译 ≠ 能跑」的空白。
|
||||
# 上面四个 job 都只证明代码编得过、测得过,从不创建真实图形窗口;本 job 在 Xvfb 虚拟显示里
|
||||
# 启动 GUI 进程,让 Slint 软件渲染器把当前场景渲进内存像素缓冲并编码成 PNG,再对**像素本身**
|
||||
# 启动 GUI 进程,让软件渲染器把当前场景渲进内存像素缓冲并编码成 PNG,再对**像素本身**
|
||||
# 断言(不是只看退出码:窗口起来了但一帧空白同样是「退出码 0」)。
|
||||
# 诚实边界:证明「Linux 上真能跑出非空白的一帧」,**不**证明视觉正确——视觉靠人眼看 artifact。
|
||||
# 本 job 绑死 Slint Window::take_snapshot;迁 iced 后必须提供等价的离屏截图通道,否则本 job 静默退化成「能起进程」。
|
||||
# M118(D26):这里原本绑死 Slint 的 `Window::take_snapshot`,打的是 Slint 版 bin
|
||||
# `unlucky-launcher`;`crates/app` 退出 workspace 后那个 bin 不再存在,改用 iced 版
|
||||
# `unlucky-launcher-iced` 自带的 `--screenshot` 通道(`crates/app-iced/src/shot/`)。
|
||||
# 命令行参数刻意不动:iced 的 `cli.rs` 就是照 Slint 版的口径写的,`--data-dir` 也仍被接受(忽略)。
|
||||
runtime-smoke:
|
||||
name: runtime smoke (ubuntu x64, xvfb)
|
||||
runs-on: ubuntu-latest
|
||||
@@ -116,13 +132,14 @@ jobs:
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
# 用 debug 而不是 release:本 job 验的是「运行时渲染通路能通」,不是优化后二进制的行为;
|
||||
# release 的 lto="fat" + codegen-units=1 会把这一步拖到十几分钟却不带来额外证据。
|
||||
- run: cargo build --bin unlucky-launcher --locked
|
||||
# M118:bin 从 Slint 版 `unlucky-launcher` 换成 iced 版(见上方 job 注释)。
|
||||
- run: cargo build --bin unlucky-launcher-iced --locked
|
||||
- name: 在 Xvfb 里跑一帧并截图(退出码非 0 即失败)
|
||||
run: |
|
||||
set -o pipefail # 当前没有管道(死行),保留是为将来加管道时先有失败传播
|
||||
mkdir -p "$RUNNER_TEMP/smoke/data"
|
||||
xvfb-run -a --server-args="-screen 0 1280x1024x24" \
|
||||
target/debug/unlucky-launcher --software-renderer \
|
||||
target/debug/unlucky-launcher-iced --software-renderer \
|
||||
--screenshot "$RUNNER_TEMP/smoke/runtime-smoke.png" \
|
||||
--data-dir "$RUNNER_TEMP/smoke/data"
|
||||
- name: 断言 PNG 存在且非空白(尺寸 / 唯一色数 / 亮度σ / 强边缘占比)
|
||||
@@ -137,10 +154,11 @@ jobs:
|
||||
|
||||
# macOS 槽位探针(M62):**默认不在 PR 上跑**,只有手动 dispatch 才触发。
|
||||
# 之所以是探针而不是常驻槽位:官方 macOS runner 处于 LaunchDaemon 上下文,没有登录的
|
||||
# WindowServer 会话,Slint 的 winit backend 创建窗口大概率直接失败;而 worker 禁 push,
|
||||
# WindowServer 会话,GUI 的 winit backend 创建窗口大概率直接失败;而 worker 禁 push,
|
||||
# 本机也没有 macOS,这条路径**尚无任何实测证据**——不拿未验证的 job 卡住主干门禁。
|
||||
# 首跑结论决定去留:绿 → 去掉 if/continue-on-error 升为常驻槽位;红 → 按 D26 归入 iced
|
||||
# 重写后再规划,并把错误原文贴进 progress 文档(不静默删 job、不吞失败原因)。
|
||||
# M118:bin 与 Linux 那条一样,从 Slint 版换成 iced 版(`unlucky-launcher-iced`)。
|
||||
runtime-smoke-macos:
|
||||
name: runtime smoke (macos arm64, probe)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
@@ -153,12 +171,12 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo build --bin unlucky-launcher --locked
|
||||
- run: cargo build --bin unlucky-launcher-iced --locked
|
||||
- name: 尝试截图(macOS 没有 X 服务器,直接跑;失败即为结论)
|
||||
run: |
|
||||
set -o pipefail # 当前没有管道(死行),保留是为将来加管道时先有失败传播
|
||||
mkdir -p "$RUNNER_TEMP/smoke/data"
|
||||
target/debug/unlucky-launcher --software-renderer \
|
||||
target/debug/unlucky-launcher-iced --software-renderer \
|
||||
--screenshot "$RUNNER_TEMP/smoke/runtime-smoke.png" \
|
||||
--data-dir "$RUNNER_TEMP/smoke/data"
|
||||
- name: 断言 PNG 存在且非空白
|
||||
|
||||
@@ -7,6 +7,16 @@ name: Guards
|
||||
# 4. file-size —— 全仓代码/文档单文件 ≤400 行(用户硬约束)
|
||||
# 5. licenses —— cargo-deny:许可证白名单 + GPL 依赖拦截 + 供应链来源校验
|
||||
# 6. unsafe-scope —— 全仓 `allow(unsafe_code)` 的文件集合必须恰好只有一个(D36 / M91)
|
||||
#
|
||||
# M118(D26):根 Cargo.toml 已 `exclude = ["crates/app"]`(Slint 退役树)。逐条核对过本文件,
|
||||
# **没有**任何一条守卫以 `--workspace` 为前提,所以排除不会让它们空转:
|
||||
# ① core-no-ui / presenter-no-ui / design-zero-dep —— 「manifest 文本 + `cargo tree -p <crate>`」
|
||||
# 口径,被守的 crate 仍是 workspace 成员,依赖树与排除前逐行一致;
|
||||
# ② file-size / unsafe-scope —— 走 `git ls-files` / `git grep`,与构建图无关,**仍然覆盖
|
||||
# `crates/app/**`**(源码还在仓库里,就还得守它的行数与 unsafe 落点);
|
||||
# ③ licenses —— 唯一走 workspace 依赖图的守卫。排除后 Slint 那棵树不再进图(实测 `cargo deny
|
||||
# list` 里 `slint*` / `i-slint-*` 为 0 个),这与「不再随任何产物发布」一致;代价是它的许可证
|
||||
# 不再被本门禁审 —— 真要重新纳入发布,得先把它加回 workspace,门禁随之恢复。
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -48,6 +58,9 @@ jobs:
|
||||
|
||||
# presenter 是 Slint 版(crates/app)与 iced 版(crates/app-iced)共用的唯一业务层(D26)。
|
||||
# 一旦 slint/iced/winit 被拉进来,分层就废了,而编译与单测仍会全绿 —— 所以必须由 CI 守。
|
||||
# M118 之后 Slint 版已被 workspace `exclude`,但本条**照样守得住**:它查的是 presenter 自己的
|
||||
# manifest 与 `cargo tree -p unlucky-presenter`,与「谁在消费 presenter」无关;依赖树里一旦出现
|
||||
# slint/iced/winit 仍会当场红。名单里的 slint 继续留着,就是为了防「把 UI 依赖偷偷塞进宿主层」。
|
||||
# 与 core-no-ui 同样是「依赖表 + cargo tree」双查,名单保持一致;脚本刻意复制而非抽公共脚本,
|
||||
# 理由是 CI 守门脚本自身挂掉的排查成本远高于这几行重复。
|
||||
presenter-no-ui:
|
||||
@@ -356,4 +369,9 @@ jobs:
|
||||
- uses: EmbarkStudios/cargo-deny-action@v2
|
||||
with:
|
||||
# 只跑许可/禁用/来源三类,advisories 由后续安全轮次单独接管
|
||||
# M118:cargo-deny 走 **workspace 依赖图**,`crates/app` 被 exclude 后 Slint 那棵树不再进图
|
||||
# (实测 `cargo deny list` 里 `slint*` / `i-slint-*` 命中 0 个),所以本门禁不再审 Slint 的
|
||||
# RF-2.0 许可 —— 与「它不再随任何产物发布」一致。这不是回退:`deny.toml` 里为 Slint 留的
|
||||
# allow 条目**故意没删**(删它得先确认没有别的路径重新引入),当前等于一条死条目。
|
||||
# 若将来把 `crates/app` 加回 workspace,本门禁的覆盖会自动恢复。
|
||||
command: check licenses bans sources
|
||||
@@ -132,6 +132,13 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# M118(D26):**Slint 版停发**。旧写法 `--bin unlucky-launcher` 打的是 `crates/app`
|
||||
# (Slint 退役树)的 bin —— 也就是说这条流水线一直在发 Slint 版二进制,而 D26 早已把
|
||||
# iced 定为产品 UI。现在 GUI 来源只有 `unlucky-launcher-iced`;`crates/app` 也已在根
|
||||
# Cargo.toml 被 `exclude`,不参与任何 workspace 构建(它连 `--manifest-path` 都编不了)。
|
||||
# 对外产物文件名**不变**(`unlucky-launcher-<ver>-<slot>.*`):改名发生在
|
||||
# `packaging/make_artifacts.py` 内部(`LAUNCHER_BIN` 找 iced 产物、落盘用对外名),
|
||||
# 下载链接 / SHA256SUMS / README 都不用跟着漂。
|
||||
- name: cargo build --release --locked
|
||||
shell: bash
|
||||
env:
|
||||
@@ -143,14 +150,16 @@ jobs:
|
||||
if [ -n "$TARGET" ]; then
|
||||
target_args+=(--target "$TARGET")
|
||||
fi
|
||||
cargo build --release --locked "${target_args[@]}" --bin unlucky-launcher --bin ull
|
||||
cargo build --release --locked "${target_args[@]}" --bin unlucky-launcher-iced --bin ull
|
||||
|
||||
- name: Windows 单文件自检(导入表不得出现 VC++ 可再发行 DLL)
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
env:
|
||||
# 跨槽位的关键点:产物在 target/<triple>/release 而不是 target/release。
|
||||
EXE: ${{ matrix.build_dir }}/unlucky-launcher.exe
|
||||
# M118:校验的是**构建产物**(iced bin 的原始文件名)。对外名 `unlucky-launcher`
|
||||
# 由 packaging/make_artifacts.py 在落盘时才换上,那一步之后才存在。
|
||||
EXE: ${{ matrix.build_dir }}/unlucky-launcher-iced.exe
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# +crt-static 是否真的生效,只看导入表:出现 VCRUNTIME/MSVCP/msvcr/ucrtbase 说明还得装
|
||||
|
||||
Generated
+64
-2360
File diff suppressed because it is too large.
Load diff
+11
-2
@@ -4,13 +4,13 @@ members = [
|
||||
"crates/core",
|
||||
"crates/agent",
|
||||
# M85(D26):UI 框架无关的宿主层。Slint 版(crates/app)与 iced 版(crates/app-iced)
|
||||
# 共用它;Slint 退役后只剩 iced 依赖,本 crate 不受影响。
|
||||
# 共用它;Slint 退役(M118 起 `crates/app` 已不是 workspace 成员)后只剩 iced 依赖,本 crate 不受影响。
|
||||
"crates/presenter",
|
||||
"crates/app",
|
||||
"crates/cli",
|
||||
"crates/design",
|
||||
# P4(D26 iced 重写)第一步:与 Slint 版 `crates/app` 并存的新 UI crate。
|
||||
# bin 名 `unlucky-launcher-iced`,翻牌时才改名(见 DevDocs/SubAgentsTalk/app-iced-骨架与翻牌.md)。
|
||||
# M118 起它是发布矩阵里**唯一**的 GUI 来源:发布了 Slint 版的那个 bin 名属于被排除的 `crates/app`。
|
||||
"crates/app-iced",
|
||||
# M87(D40 第 2 层):配色取色的解码适配层。**唯一**允许引入 `image` 类依赖的地方,
|
||||
# 使 `crates/design` 能继续宣称「零第三方依赖」。
|
||||
@@ -19,6 +19,15 @@ members = [
|
||||
# 壳层(iced 版现在,别的壳将来)与 presenter 都依赖它,所以它不能认任何一个渲染框架。
|
||||
"crates/i18n",
|
||||
]
|
||||
# M118(D26):`crates/app` 是 Slint 退役树 —— UI 已迁到 iced,目录与源码**原样保留**作历史
|
||||
# 参考(另一份参考资产见 DevDocs/ops/slint-reference/),但不再进默认构建与发布矩阵。摘出去的
|
||||
# 是整棵 slint 1.18 + usvg 0.48 依赖树:本机单路冷编 ≈14 分钟,而 CI 的 `--workspace` 每次都会
|
||||
# 编它,既拖长反馈,又会在并行超配时随机 OOM(见 DevDocs/00-踩坑记录-p2.md T7)。
|
||||
# 排除 ≠ 删除,但**它确实不再可编**:该 manifest 整份都是 `*.workspace = true` 继承写法,
|
||||
# 一旦不是 workspace 成员,继承无源、manifest 解析即失败(实测:
|
||||
# `cargo metadata --manifest-path crates/app/Cargo.toml` → "error inheriting `edition` …")。
|
||||
# 要读这一版实现请直接读源码,别再尝试构建它。
|
||||
exclude = ["crates/app"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.0"
|
||||
|
||||
@@ -15,8 +15,10 @@ attached to other agent tooling as an MCP server.
|
||||
- **Single-file native binary**: the launcher itself needs no JVM, no WebView and no sidecar
|
||||
runtime. The JDK a game needs is downloaded and managed per instance, not as a launcher
|
||||
dependency.
|
||||
- **Two UI stacks during the rewrite**: the released UI is Slint (Royalty-Free 2.0); the
|
||||
next-generation UI is iced 0.14 + Material 3 Expressive and is still being written (see Status).
|
||||
- **One UI stack in the build**: the UI is iced 0.14 + Material 3 Expressive. The earlier Slint
|
||||
implementation (`crates/app`) is kept as source-only history: it is excluded from the cargo
|
||||
workspace, so the workspace never builds, tests or ships it. v0.1.0 — the only tagged release so
|
||||
far — still carries a Slint build (see Status).
|
||||
- **CPU software-rendering fallback**: `--software-renderer` keeps the interface rendering
|
||||
normally on machines with no usable GPU or with broken drivers.
|
||||
- **AI agent + MCP**: chat, setting edits and crash diagnosis inside the launcher; `ull agent
|
||||
@@ -34,7 +36,14 @@ attached to other agent tooling as an MCP server.
|
||||
|
||||
Two tracks. They are not the same product yet, so read the headings before downloading anything.
|
||||
|
||||
### Track A — released: v0.1.0, Slint UI (this is what you can download today)
|
||||
### Track A — historical: v0.1.0, Slint UI (the only tagged release so far)
|
||||
|
||||
> **Historical implementation — no longer in the default build or the release matrix.** The Slint
|
||||
> tree (`crates/app`) is kept in the repository as source-only reference: it is excluded from the
|
||||
> cargo workspace, so `cargo build` / `cargo test` / `cargo clippy` never touch it and no artifact is
|
||||
> built from it. Read the source if you want to see how that UI was put together; do not expect to
|
||||
> build it. The list below is kept because it records what the v0.1.0 assets actually contain —
|
||||
> since v0.1.0 the pipeline builds the iced binary and ships it under the same public asset names.
|
||||
|
||||
- **GitHub Releases `v0.1.0`** (2026-11-01, flagged pre-release): single-file assets for Windows
|
||||
x64 (a bare `.exe`), Linux x64 and macOS (arm64 and x64) `.tar.gz`. Every release also carries
|
||||
@@ -67,16 +76,18 @@ Two tracks. They are not the same product yet, so read the headings before downl
|
||||
with automatic fallback, and the screenshot/diff channel the visual reviews use).
|
||||
- **Not done**: the component library (buttons, dialogs, lists, menus, search, and the rest of the
|
||||
M3 set), page migration, and the i18n pass. Every page in the iced binary is a placeholder.
|
||||
- **Slint stays until the flip**: `crates/app` remains the reference implementation until the iced
|
||||
build passes equivalence acceptance; only then is `unlucky-launcher-iced` renamed to
|
||||
`unlucky-launcher` and the Slint crate retired.
|
||||
- **Slint is retired from the build, kept as reference**: `crates/app` is no longer a workspace member
|
||||
(M118) — the source stays for historical reference only: not compiled, not tested, not shipped, and
|
||||
no longer buildable as a workspace member. What is left of the flip is the *rename*: until the iced
|
||||
build passes equivalence acceptance its binary is still called `unlucky-launcher-iced`, while the
|
||||
release pipeline already ships it under the public `unlucky-launcher` asset name.
|
||||
|
||||
Binaries in the workspace, so you can tell them apart:
|
||||
Binaries you may run into, so you can tell them apart:
|
||||
|
||||
| Binary | Crate | State |
|
||||
|--------|-------|-------|
|
||||
| `unlucky-launcher` | `crates/app` (Slint) | released in v0.1.0; still the usable GUI; also runs every CLI subcommand |
|
||||
| `unlucky-launcher-iced` | `crates/app-iced` (iced 0.14) | under construction; skeleton only, not shipped; same subcommand dispatch |
|
||||
| `unlucky-launcher-iced` | `crates/app-iced` (iced 0.14) | the only GUI binary the workspace builds; the release pipeline stages it under the public name `unlucky-launcher`; same subcommand dispatch |
|
||||
| `unlucky-launcher` | `crates/app` (Slint) | **historical**: that crate is excluded from the workspace, so this binary is no longer built or shipped; the v0.1.0 assets are the last Slint builds |
|
||||
| `ull` | `crates/cli` | the zero-UI build of the same command set, shipped as its own asset |
|
||||
|
||||
`unlucky-launcher` and `ull` are not duplicates. The GUI binary needs the graphics stack when it
|
||||
@@ -122,8 +133,9 @@ Unlucky-Launcher (cargo workspace)
|
||||
├── crates/agent # AI agent: ToolSpec registry + built-in client + MCP server (one core, two shapes)
|
||||
├── crates/design # design tokens: real HCT color / type / shape / spacing / elevation / motion / icons
|
||||
│ # / component metrics — zero UI dependencies, no third-party crates
|
||||
├── crates/app # Slint UI (bin `unlucky-launcher`): the released GUI, kept until equivalence acceptance
|
||||
├── crates/app-iced # next-generation iced UI (bin `unlucky-launcher-iced`): under construction
|
||||
├── crates/app # HISTORICAL Slint UI (bin `unlucky-launcher`): excluded from the workspace,
|
||||
│ # source-only reference — never built, tested or shipped any more
|
||||
├── crates/app-iced # the iced UI (bin `unlucky-launcher-iced`): the only GUI the workspace builds
|
||||
├── crates/cli # CLI (bin `ull`): headless, zero UI
|
||||
└── packaging # single-file artifact matrix and release scripts
|
||||
```
|
||||
@@ -149,7 +161,7 @@ Prerequisites:
|
||||
`rustfmt` and `clippy` components)
|
||||
- Windows: MSVC toolchain (what CI uses) or MinGW-w64 (`x86_64-pc-windows-gnu`)
|
||||
- Linux: `libxkbcommon-dev libfontconfig1-dev libgl1-mesa-dev libegl1-mesa-dev libwayland-dev
|
||||
libxcb1-dev` — needed by both UI stacks (Slint's winit + femtovg, iced's winit + wgpu/tiny-skia)
|
||||
libxcb1-dev` — winit + wgpu/tiny-skia ask for these at build time (the Slint build also needed femtovg)
|
||||
|
||||
```bash
|
||||
cargo fmt --all --check # formatting
|
||||
@@ -158,24 +170,29 @@ cargo test --workspace # tests
|
||||
cargo build --release # binaries land in target/release/
|
||||
```
|
||||
|
||||
`--workspace` covers the eight members in the module map. `crates/app` is excluded at the workspace
|
||||
level (M118), so none of these commands compiles the Slint tree — and there is no build command for
|
||||
it: that crate is kept as source-only reference and can no longer be built as a workspace member.
|
||||
|
||||
What the build produces:
|
||||
|
||||
- `unlucky-launcher` — the Slint UI (the released one). It is also the CLI: the same binary answers
|
||||
every subcommand listed above.
|
||||
- `unlucky-launcher-iced` — the iced UI skeleton. The name is temporary: it can only become
|
||||
`unlucky-launcher` at the flip, because two crates in one workspace cannot emit the same binary
|
||||
name into the same target directory. Same subcommand dispatch.
|
||||
- `unlucky-launcher-iced` — the GUI (iced). It is also the CLI: the same binary answers every
|
||||
subcommand listed above. The name is temporary — it becomes `unlucky-launcher` at the flip. The
|
||||
release artifacts already carry the public name: the pipeline builds this bin and
|
||||
`packaging/make_artifacts.py` stages it as `unlucky-launcher[.exe]`, so download links never change.
|
||||
- `unlucky-launcher` — **historical**: no workspace build produces this binary any more; it belonged
|
||||
to `crates/app`, which is excluded. The v0.1.0 assets are the last builds under this name.
|
||||
- `ull` — the CLI as a standalone, UI-free binary. Same command set, no graphics stack, smaller, and
|
||||
the right artifact for a machine that has no display at all.
|
||||
|
||||
Rendering switches:
|
||||
|
||||
- `unlucky-launcher --software-renderer` (equivalent to `SLINT_BACKEND=winit-software`) forces the
|
||||
CPU path on the Slint build
|
||||
- `unlucky-launcher-iced --software-renderer` forces tiny-skia (`ICED_BACKEND=tiny-skia`);
|
||||
`--screenshot <png>` writes one frame and exits, which is the acceptance channel
|
||||
- Both stacks fall back to the CPU path when no usable adapter is there: the Slint build through its
|
||||
own renderer fallback chain, the iced build through its explicit probe
|
||||
`--screenshot <png>` writes one frame and exits, which is the acceptance channel CI's headless
|
||||
smoke job uses
|
||||
- With no usable adapter the iced build's explicit probe falls back to the CPU path on its own
|
||||
- **Historical** (v0.1.0's Slint build still takes it): `unlucky-launcher --software-renderer`, i.e.
|
||||
`SLINT_BACKEND=winit-software`, forced the CPU renderer of that build through its own fallback chain
|
||||
|
||||
Dependency license check (optional locally, required in CI):
|
||||
`cargo deny check licenses bans sources`.
|
||||
@@ -214,8 +231,10 @@ Minimum baseline: **Windows 10**; Windows 8.1 / 8 / 7 are not supported.
|
||||
[NOTICE](NOTICE).
|
||||
- **Slint** (<https://slint.dev>), Royalty-Free 2.0: obligation for the Slint build that v0.1.0
|
||||
ships — an `AboutSlint` widget on the about page (still outstanding) and, until it lands, the
|
||||
NOTICE file, this section and a "Made with Slint" note on the release page. The obligation is
|
||||
kept for as long as a Slint-linked binary ships.
|
||||
NOTICE file, this section and a "Made with Slint" note on the release page. The obligation follows
|
||||
a **Slint-linked binary**: it applies to the v0.1.0 assets (and to any later build that links Slint
|
||||
again), not to new iced builds — `crates/app` is excluded from the workspace, so the pipeline no
|
||||
longer produces a Slint-linked binary.
|
||||
- **iced** (<https://github.com/iced-rs/iced>), MIT: the framework of the next-generation UI,
|
||||
together with `winit` and, through it, `wgpu` / `tiny-skia` (Apache-2.0 / MIT).
|
||||
- **Google Material Color Utilities** (Apache-2.0): the color tokens in `crates/design` are a Rust
|
||||
|
||||
+37
-20
@@ -13,8 +13,9 @@ Unlucky Launcher(ULL)是一个用 Rust 写的免费开源 Minecraft: Java
|
||||
|
||||
- **单文件原生二进制**:启动器本体不需要 JVM、不需要 WebView、不带旁挂运行时。游戏要的 JDK 由
|
||||
启动器按实例下载管理,不是启动器的依赖。
|
||||
- **重写期两套 UI 并存**:已发布版本是 Slint(Royalty-Free 2.0);下一代 UI 是 iced 0.14 +
|
||||
Material 3 Expressive,目前仍在写(见「当前状态」)。
|
||||
- **默认构建里只有一套 UI**:UI 是 iced 0.14 + Material 3 Expressive。早先的 Slint 实现
|
||||
(`crates/app`)作为**历史参考**保留源码:已被 workspace `exclude`,默认构建不编、测试不跑、
|
||||
发布不发。唯一已发布的 tag `v0.1.0` 发的仍是 Slint 版(见「当前状态」)。
|
||||
- **CPU 软渲染兜底**:`--software-renderer` 让没有可用 GPU 或驱动有问题的老机也能正常显示界面。
|
||||
- **AI Agent + MCP**:启动器内可对话、改设置、读崩溃诊断;`ull agent serve` 把同一个内核以 MCP
|
||||
server 形态(stdio 或 Streamable HTTP)开放给外部 Agent 工具。
|
||||
@@ -29,7 +30,13 @@ Unlucky Launcher(ULL)是一个用 Rust 写的免费开源 Minecraft: Java
|
||||
|
||||
两条轨道,还不是同一个东西——看小标题再决定下载什么。
|
||||
|
||||
### 轨道 A —— 已发布:v0.1.0,Slint 版(现在能下载的就是它)
|
||||
### 轨道 A —— 历史:v0.1.0,Slint 版(目前唯一的 tag)
|
||||
|
||||
> **历史实现——已不在默认构建与发布矩阵内。** Slint 那棵树(`crates/app`)作为源码参考留在仓库里:
|
||||
> 已被 cargo workspace `exclude`,所以 `cargo build` / `cargo test` / `cargo clippy` 都不会碰它,
|
||||
> 也没有任何产物从它构建。想了解那一版 UI 怎么写的就直接读源码——**不要再尝试构建它**(它的 manifest
|
||||
> 整份是 workspace 继承写法,离开 workspace 后连解析都过不了)。下面这段原文保留,因为它记录的是
|
||||
> `v0.1.0` 资产里到底装了什么;从 `v0.1.0` 之后,流水线构建的是 iced 版,对外文件名不变。
|
||||
|
||||
- **GitHub Releases `v0.1.0`**(2026-11-01,标记为 pre-release):单文件产物覆盖 Windows x64(裸
|
||||
`.exe`)、Linux x64、macOS(arm64 与 x64)`.tar.gz`。每个 Release 另挂 `SHA256SUMS.txt` 与
|
||||
@@ -59,15 +66,16 @@ Unlucky Launcher(ULL)是一个用 Rust 写的免费开源 Minecraft: Java
|
||||
对比通道)。
|
||||
- **没完成**:组件库(按钮、对话框、列表、菜单、搜索栏,以及 M3 其余组件)、页面搬迁、i18n 文案。
|
||||
iced 版里现在每一个页面都是占位。
|
||||
- **Slint 版在翻牌前不退场**:`crates/app` 作为参考实现保留,直到 iced 版通过等价验收;那时才把
|
||||
`unlucky-launcher-iced` 改名成 `unlucky-launcher`,并让 Slint 版退役。
|
||||
- **Slint 版已退出构建,只留源码作参考**:`crates/app` 不再是 workspace 成员(M118)——源码留作历史
|
||||
参考,不编译、不测试、不发布,也不再有可用的构建方式。翻牌只剩**改名**这一步:在 iced 版通过等价
|
||||
验收前,它的 bin 还叫 `unlucky-launcher-iced`;发布流水线已经把它按对外名 `unlucky-launcher` 打出去。
|
||||
|
||||
工作区里的三个 bin,先认清楚:
|
||||
可能会遇到的 bin,先认清楚:
|
||||
|
||||
| 二进制 | crate | 状态 |
|
||||
|--------|-------|------|
|
||||
| `unlucky-launcher` | `crates/app`(Slint) | v0.1.0 已发布,仍是当前能用的图形界面;同时支持全部 CLI 子命令 |
|
||||
| `unlucky-launcher-iced` | `crates/app-iced`(iced 0.14) | 施工中,仅骨架,不随发布包分发;子命令分发同款 |
|
||||
| `unlucky-launcher-iced` | `crates/app-iced`(iced 0.14) | workspace 里**唯一**的 GUI bin;发布流水线把它按对外名 `unlucky-launcher` 落盘;子命令分发同款 |
|
||||
| `unlucky-launcher` | `crates/app`(Slint) | **历史**:该 crate 已被 workspace `exclude`,这个 bin 不再被构建或分发;`v0.1.0` 的资产是最后一批 Slint 版 |
|
||||
| `ull` | `crates/cli` | 同一套命令的零 UI 构建,作为独立资产随发布分发 |
|
||||
|
||||
`unlucky-launcher` 与 `ull` 不是重复品:开窗时 GUI 二进制要用图形栈(X11 / Wayland / GL 走
|
||||
@@ -109,8 +117,9 @@ Unlucky-Launcher (cargo workspace)
|
||||
├── crates/agent # AI Agent:ToolSpec 注册表 + 内置客户端 + MCP server(双形态共用一个内核)
|
||||
├── crates/design # 设计令牌:真 HCT 色彩 / 排版 / 形状 / 间距 / 高程 / 动效 / 图标 / 组件度量
|
||||
│ # —— 零 UI 依赖、零第三方 crate
|
||||
├── crates/app # Slint UI(bin `unlucky-launcher`):已发布的图形界面,保留到等价验收通过
|
||||
├── crates/app-iced # 下一代 iced UI(bin `unlucky-launcher-iced`):施工中
|
||||
├── crates/app # 历史 Slint UI(bin `unlucky-launcher`):已被 workspace `exclude`,
|
||||
│ # 仅作源码参考——不再被构建 / 测试 / 发布
|
||||
├── crates/app-iced # iced UI(bin `unlucky-launcher-iced`):workspace 里唯一的 GUI bin
|
||||
├── crates/cli # CLI(bin `ull`):headless,零 UI
|
||||
└── packaging # 单文件产物矩阵与发布脚本
|
||||
```
|
||||
@@ -135,28 +144,34 @@ Unlucky-Launcher (cargo workspace)
|
||||
- Rust stable(`rust-toolchain.toml` 会自动选工具链;门禁还需要 `rustfmt` / `clippy` 组件)
|
||||
- Windows:MSVC 工具链(CI 用这套)或 MinGW-w64(`x86_64-pc-windows-gnu`)
|
||||
- Linux:`libxkbcommon-dev libfontconfig1-dev libgl1-mesa-dev libegl1-mesa-dev libwayland-dev
|
||||
libxcb1-dev`——两套 UI 都要用(Slint 的 winit + femtovg,iced 的 winit + wgpu/tiny-skia)
|
||||
libxcb1-dev`——winit + wgpu/tiny-skia 编译期要用(Slint 版当年还要 femtovg)
|
||||
|
||||
```bash
|
||||
cargo fmt --all --check # 格式
|
||||
cargo clippy --workspace --all-targets -- -D warnings # 静态检查(零 warning 门禁)
|
||||
cargo test --workspace # 测试
|
||||
cargo build --release # 三个 bin 都落在 target/release/
|
||||
cargo build --release # bin 落在 target/release/
|
||||
```
|
||||
|
||||
编出来的三个 bin:
|
||||
`--workspace` 就是模块地图里那八个成员:`crates/app` 已在 workspace 层被排除(M118),上面这些命令
|
||||
都不会编 Slint 那棵树——而且**它没有构建方式**:该 crate 只作源码参考,作为 workspace 成员已不可编。
|
||||
|
||||
- `unlucky-launcher`——Slint 版(已发布的那个)。它同时也是 CLI:同一个二进制认上面列的全部子命令。
|
||||
- `unlucky-launcher-iced`——iced 版骨架。名字是临时的:只有翻牌时才能改成 `unlucky-launcher`,
|
||||
因为同一个工作区里两个 crate 不能往同一个 target 目录里产出同名 bin。子命令分发同款。
|
||||
编出来的 bin:
|
||||
|
||||
- `unlucky-launcher-iced`——GUI(iced)。它同时也是 CLI:同一个二进制认上面列的全部子命令。名字是
|
||||
临时的,翻牌时才改成 `unlucky-launcher`;发布产物**已经**用对外名:流水线编这个 bin,
|
||||
`packaging/make_artifacts.py` 落盘时改成 `unlucky-launcher[.exe]`,所以下载链接不用变。
|
||||
- `unlucky-launcher`——**历史**:workspace 构建已不产出它(它属于被排除的 `crates/app`)。
|
||||
`v0.1.0` 的资产是最后一批用这个名字发出去的构建。
|
||||
- `ull`——CLI 的独立无 UI 构建:同一套命令、不链接图形栈、体积更小,给完全没有显示设备的机器用。
|
||||
|
||||
渲染开关:
|
||||
|
||||
- `unlucky-launcher --software-renderer`(等价于 `SLINT_BACKEND=winit-software`)强制 Slint 版走 CPU
|
||||
- `unlucky-launcher-iced --software-renderer` 强制 tiny-skia(`ICED_BACKEND=tiny-skia`);
|
||||
`--screenshot <png>` 出一帧图后退出,这是验收通道
|
||||
- 两套栈在没有可用适配器时都会退到 CPU:Slint 版走它自己的渲染器回退链,iced 版走显式探测
|
||||
`--screenshot <png>` 出一帧图后退出,这是 CI 无头冒烟 job 用的验收通道
|
||||
- 没有可用适配器时,iced 版靠显式后端探测自己退到 CPU
|
||||
- **历史**(`v0.1.0` 的 Slint 版仍认这条):`unlucky-launcher --software-renderer`,即
|
||||
`SLINT_BACKEND=winit-software`,让那一版走它自己的渲染器回退链
|
||||
|
||||
依赖许可检查(本地可选,CI 必跑):`cargo deny check licenses bans sources`。
|
||||
|
||||
@@ -188,7 +203,9 @@ cargo build --release # 三个 bin 都落在 ta
|
||||
- **本项目**:Apache License 2.0,见 [LICENSE](LICENSE);第三方声明见 [NOTICE](NOTICE)。
|
||||
- **Slint**(<https://slint.dev>),Royalty-Free 2.0:v0.1.0 发布的正是 Slint 版,这项义务继续有效
|
||||
——关于页放 `AboutSlint` 部件(尚未落地),在此之前由 NOTICE、本节与发布页的「Made with Slint」
|
||||
说明承担告知义务。只要还有链接 Slint 的产物在发,这条义务就保留。
|
||||
说明承担告知义务。义务跟着**链接了 Slint 的产物**走:已发布的 `v0.1.0` 资产(以及将来任何重新链接
|
||||
Slint 的构建)适用;`crates/app` 已被 workspace `exclude`,流水线不再产出链接 Slint 的二进制,
|
||||
所以新的 iced 版产物不适用这一条。
|
||||
- **iced**(<https://github.com/iced-rs/iced>),MIT:下一代 UI 的框架;与它同栈的 `winit`、以及经它
|
||||
引入的 `wgpu` / `tiny-skia`(Apache-2.0 / MIT)。
|
||||
- **Google Material Color Utilities**(Apache-2.0):`crates/design` 的色彩令牌是它 HCT /
|
||||
|
||||
+11
-11
@@ -25,8 +25,8 @@
|
||||
- 归档解压后是**一个顶层目录** `unlucky-launcher-<ver>-<槽位>/`,用户不会解压出一堆散文件。
|
||||
- **`ull` 是并列的裸资产,不塞进 tar.gz**:headless 用户要的就是「下一个小文件直接跑」;归档里放
|
||||
LICENSE/NOTICE/README.md 是许可义务,而这三份本来就作为并列 Release 资产分发,裸 `ull` 不缺条款。
|
||||
- `unlucky-launcher` 本体也认全部 CLI 子命令(M82),`ull` 不是第二个界面,而是**不链接图形栈**的
|
||||
同一套命令(差异见 §4 与 §7.4)——两者都不是重复品。
|
||||
- `unlucky-launcher` 本体也认全部 CLI 子命令(M82),`ull` 不是第二个界面,而是**不链接图形栈**的同一套命令(差异见 §4 与 §7.4),两者不是重复品。
|
||||
M118:GUI 的**构建产物**名是 `unlucky-launcher-iced`(`crates/app` 已被 workspace `exclude`,不再产出 `unlucky-launcher`);对外文件名仍是 `unlucky-launcher`,改名在 `make_artifacts.py` 落盘时(`LAUNCHER_BIN` 找产物 / `LAUNCHER_ASSET` 定对外名),所以下载链接 / `SHA256SUMS` / 本文矩阵不变。
|
||||
- `<ver>` 不带前导 `v`(tag 是 `v0.1.0`,文件名是 `0.1.0`)——由脚本统一裁剪。
|
||||
- UNIX 归档内 `mtime`/`uid`/`gid` 归零、权限固定(二进制 0755、文本 0644),
|
||||
同源构建的 sha256 不受打包时刻影响。
|
||||
@@ -51,7 +51,7 @@
|
||||
### 本地(当前平台)
|
||||
|
||||
```bash
|
||||
cargo build --release --locked # 产出 target/release/{unlucky-launcher,ull,unlucky-launcher-iced}
|
||||
cargo build --release --locked # 产出 target/release/{unlucky-launcher-iced,ull}(M118:Slint 版不再进 workspace)
|
||||
cargo build --profile fast --bins # 只是想快点看到画面/跑测试:快档(§6),产物在 target/fast/
|
||||
python packaging/make_artifacts.py --out dist # 产物落在 dist/,含 SHA256SUMS.txt
|
||||
python packaging/make_artifacts.py --version v0.1.0 # 顺带校验版本一致性
|
||||
@@ -67,7 +67,7 @@ macOS x64),其它组合直接报错退出——不在矩阵里的平台不
|
||||
```bash
|
||||
rustup target add aarch64-pc-windows-msvc
|
||||
cargo build --release --locked --target aarch64-pc-windows-msvc \
|
||||
--bin unlucky-launcher --bin ull # 不用 --bins:发布矩阵只发 GUI + ull,iced 不进产物
|
||||
--bin unlucky-launcher-iced --bin ull # 不用 --bins:矩阵只发 GUI + ull;GUI 的构建产物名是 iced 的 bin(M118)
|
||||
python packaging/make_artifacts.py --slot windows-arm64 \
|
||||
--build-dir target/aarch64-pc-windows-msvc/release --out dist
|
||||
```
|
||||
@@ -181,7 +181,7 @@ macOS 产物是**裸二进制**而非 `.app` bundle:符合单文件承诺,
|
||||
|
||||
## 5. 软渲染兜底(无 GPU / 老驱动 / 远程桌面)
|
||||
|
||||
Slint 默认 `renderer-femtovg`(GL)。两条兜底路径,效果等价,任选其一:
|
||||
M118(D26):以下是**历史实现(Slint 版,默认 `renderer-femtovg`/GL)**的兜底路径,已不在默认构建与发布矩阵内(`crates/app` 被 workspace `exclude`,源码仅作参考、不编译)。现役 GUI 是 iced 版:`unlucky-launcher-iced --software-renderer`(= `ICED_BACKEND=tiny-skia`)走 tiny-skia 光栅化。v0.1.0 的产物仍认下面两条:
|
||||
|
||||
```bash
|
||||
unlucky-launcher --software-renderer # 启动参数(本仓库解析后设 SLINT_BACKEND)
|
||||
@@ -190,9 +190,8 @@ SLINT_BACKEND=winit-software unlucky-launcher # 环境变量(Slint
|
||||
|
||||
- 参数解析在 `crates/app/src/main.rs` 的 `apply_renderer_flag()`,只认完全相等的 `--software-renderer`。
|
||||
- 软渲染是 CPU 光栅化,无 GPU 也能出图;代价是动画与大窗口重绘更慢(Metro 纯色界面影响有限)。
|
||||
- 验收/无交互桌面场景另有进程内截图通道:`--screenshot <png>`(见 `crates/app/src/screenshot.rs`),
|
||||
它同样能在软渲染下工作,是 CI 与远程机唯一可靠的"真出图"证据。
|
||||
- 发布冒烟(本机实跑,见 §7)就是用 `--software-renderer --screenshot` 组合证明"无 GPU 也能起来"。
|
||||
- 截图通道 `--screenshot <png>`:历史实现 `crates/app/src/screenshot.rs`,现役 `crates/app-iced/src/shot/`;
|
||||
软渲染下照样出图,是 CI 与远程机唯一可靠的"真出图"证据(发布冒烟见 §7,本机实跑 `--software-renderer --screenshot`)。
|
||||
|
||||
## 6. Cargo 构建档位(release 体积档 / fast 速度档)
|
||||
|
||||
@@ -237,14 +236,14 @@ SLINT_BACKEND=winit-software unlucky-launcher # 环境变量(Slint
|
||||
① **依赖 opt-level 从 3 退回 `"z"` 又快 29.6% 又小 19~24%**(两臂同为 cu16,唯一自变量是 opt-level)——抬 opt-level 是拿编译时间和体积换运行期;
|
||||
`cu1 → cu16` 的收益本轮**没有同条件对照**,未归因。② `fast` **冷编译比 `release` 还慢**(24m27s vs 16m01s)、体积 2.3 倍,瓶颈在两个大 UI
|
||||
crate + 链接 + 机械盘 IO——定位是 **SSD 机器与增量重编**,不是冷编译加速。体积归因:GUI 相对旧基线 +12.9%(13.92 → 15.72 MiB)里
|
||||
「代码增长」与「依赖 cu16」**未分离**;`ull` 只 +1.7%,在 +1~3% 口径内。体积构成:Slint 运行时(双渲染器 + winit/accesskit/托盘)+ rustls/reqwest + rig/rmcp/axum 为主,`ull` 更小是 D18(CLI 零 UI 依赖)的结果。
|
||||
「代码增长」与「依赖 cu16」**未分离**;`ull` 只 +1.7%,在 +1~3% 口径内。体积构成(**M118 前的 Slint 版,历史数**):Slint 运行时(双渲染器 + winit/accesskit/托盘)+ rustls/reqwest + rig/rmcp/axum 为主,`ull` 更小是 D18(CLI 零 UI 依赖)的结果。
|
||||
|
||||
### 7.2 冒烟(真跑,2026-10-31 夜间 + 11-01 早,本机 Win11 26100)
|
||||
|
||||
| 命令 | 实测结果 |
|
||||
|------|---------|
|
||||
| `ull.exe --version` | 输出 `ull 0.1.0(unlucky-cli)` + `os: Windows 11 · 10.0.26100(x86_64)· 满足最低要求`,exit 0 —— 版本与 workspace `0.1.0` 一致 |
|
||||
| `unlucky-launcher.exe --software-renderer --screenshot … --data-dir …` | exit 0,产出 1180×760 PNG(3,588,298 B);看图确认 Metro 实例页(侧栏/搜索/空态/AI 助手面板)正常渲染 → **软渲染路径真的能出图**,不依赖 GL |
|
||||
| `unlucky-launcher.exe --software-renderer --screenshot … --data-dir …`(Slint 版,历史实测) | exit 0,产出 1180×760 PNG(3,588,298 B);看图确认 Metro 实例页(侧栏/搜索/空态/AI 助手面板)正常渲染 → **软渲染路径真的能出图**,不依赖 GL |
|
||||
| `unlucky-launcher.exe --version` | **无输出**,8 秒后被 timeout 杀掉(exit 124)——GUI 当时不解析 `--version`,会直接开窗口。M82 后已修(走 CLI 分发,见 §10-1)|
|
||||
|
||||
### 7.3 打包验证(本机 Windows 槽位真跑)
|
||||
@@ -280,7 +279,7 @@ CI 的 MSVC `+crt-static` 产物同理(静态 CRT);`release.yml` 里用 `d
|
||||
总之不允许"悄悄要用户装可再发行包"。
|
||||
注意:本机只装了 GNU 工具链,MSVC 那个槽位的产物本身**没有在本机验证过**,由 CI 首跑验证。
|
||||
|
||||
Linux 侧同一件事的对照(M82 实测:`readelf -d` + `ldd` + `nm -D`,容器内 Debian 12 glibc 2.36):Slint
|
||||
Linux 侧同一件事的对照(M82 实测:`readelf -d` + `ldd` + `nm -D`,容器内 Debian 12 glibc 2.36;被测的是 **Slint 版 GUI,历史实测**):Slint
|
||||
GUI 的 ELF `DT_NEEDED` 只有 `libfontconfig.so.1` / `libgcc_s.so.1` / `libm.so.6` / `libc.so.6` /
|
||||
`ld-linux-x86-64.so.2`;`libX11` / `libxcb` / `libxkbcommon` / `libwayland-client` / `libGL` / `libEGL`
|
||||
**都不在**导入表里,而是以字符串形式由 `dlopen` 在开窗那一刻加载(`nm -D` 可见 `U dlopen@GLIBC_2.34` /
|
||||
@@ -318,6 +317,7 @@ merge 后由 tower 重指 tag 重跑流水线,两槽位进 `SHA256SUMS.txt`
|
||||
三份文本在 UNIX 归档内、在 Windows 侧作为并列 Release 资产。
|
||||
- Slint 的 RF 2.0 义务:关于页保留 `AboutSlint` 部件(已在 UI 内),不得移除;
|
||||
选 RF 分支即不触发 GPL 分支义务(见 `deny.toml` 的许可证白名单注释)。
|
||||
- **M118 后这条义务只跟着已发布的 `v0.1.0` 资产走**:`crates/app` 已被 workspace `exclude`,发布矩阵里再没有链接 Slint 的二进制,新的 iced 版产物不链接 Slint;`deny.toml` 那条 RF-2.0 allow 因此暂时是死条目(不删,留给将来真有别的路径引入 Slint 时兜底)。
|
||||
- `README.md`(英文主版)随包分发;中文版 `README.zh-CN.md` 留在仓库不进包(避免包体噪音)。
|
||||
- 依赖许可门禁不变:`deny.toml` 白名单(Apache-2.0 / MIT / BSD / Zlib / BSL-1.0 / ISC / CC0 / Unlicense /
|
||||
Unicode-3.0 / CDLA-Permissive-2.0 / Slint-RF-2.0)。发布任务不新增任何依赖。
|
||||
|
||||
@@ -54,7 +54,13 @@ import tarfile
|
||||
from pathlib import Path
|
||||
from typing import NoReturn
|
||||
|
||||
LAUNCHER_BIN = "unlucky-launcher"
|
||||
# M118(D26):GUI 的**构建产物**名是 iced 版的 `unlucky-launcher-iced`。旧值 `unlucky-launcher`
|
||||
# 是 `crates/app`(Slint 退役树)的 bin —— 那棵树已被根 Cargo.toml `exclude`,再也不产出它了。
|
||||
# **对外**文件名仍叫 `unlucky-launcher`:下载链接 / SHA256SUMS / README 都绑着这个名字,
|
||||
# 改名是「翻牌」那一步的事,不是打包这一步的事。所以刻意拆成两个常量:
|
||||
# 找文件用 LAUNCHER_BIN,落盘(tar 内文件名 / exe 资产名)用 LAUNCHER_ASSET。
|
||||
LAUNCHER_BIN = "unlucky-launcher-iced"
|
||||
LAUNCHER_ASSET = "unlucky-launcher"
|
||||
CLI_BIN = "ull"
|
||||
# 随包分发的合规文本(仓库根目录);英文主版 README 是对外分发口径。
|
||||
COMPLIANCE_DOCS = ("LICENSE", "NOTICE", "README.md")
|
||||
@@ -216,7 +222,7 @@ def stage_archive(out_dir: Path, tag: str, version: str, launcher: Path) -> Path
|
||||
if stage.exists():
|
||||
shutil.rmtree(stage)
|
||||
stage.mkdir(parents=True)
|
||||
shutil.copy2(launcher, stage / launcher.name)
|
||||
shutil.copy2(launcher, stage / LAUNCHER_ASSET)
|
||||
for doc in COMPLIANCE_DOCS:
|
||||
source = REPO_ROOT / doc
|
||||
if not source.is_file():
|
||||
@@ -232,7 +238,7 @@ def stage_archive(out_dir: Path, tag: str, version: str, launcher: Path) -> Path
|
||||
info.mtime = 0
|
||||
info.uid = info.gid = 0
|
||||
info.uname = info.gname = ""
|
||||
info.mode = 0o755 if entry.name == launcher.name else 0o644
|
||||
info.mode = 0o755 if entry.name == LAUNCHER_ASSET else 0o644
|
||||
with entry.open("rb") as handle:
|
||||
tar.addfile(info, handle)
|
||||
shutil.rmtree(stage)
|
||||
|
||||
Reference in new issue
Block a user