From 8e9b30af4443d27b8779a343cbcaab3586a3b3db Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Sun, 27 Sep 2026 04:47:03 +0800 Subject: [PATCH 1/2] 0.15.2: Qt at its upstream version, 6.11.1; a synthesised rules-qt program that was asked for nothing reports nothing - The fixtures, the missing-SDK message and docs/rules-qt.md name xim:qt-base and xim:qt 6.11.1, the single key the index keeps (openxlings/xim-pkgindex#891). - docs/rules-qt.md states how a project uses its own Qt: comment out the declared payload, then name the SDK with QT_ROOT_DIR or options::root. - A package that enables rules-qt only to import mcpp.rules.qt and writes no build.mcpp runs the program mcpp synthesises (mcpp#715). With no SDK and no .ui, .qrc or .ts of its own it now says nothing; the qt-import-only fixture holds that. - The CI sandbox caches take a new generation, so none restores the Qt payload laid out before the runtime closure. --- .../docs/2026-09-27-plugins-0.15.2-plan.md | 97 ++++++++++++ ...ng-assets-locale-and-galtranslpp-review.md | 147 ++++++++++++++++++ .github/scripts/check-deps-and-qt.sh | 14 +- .github/workflows/ci.yml | 14 +- README.md | 2 +- docs/deps.md | 2 +- docs/rules-qt.md | 20 ++- mcpp.toml | 2 +- rules/qt.cppm | 12 +- src/plugins.cppm | 2 +- tests/qt-consumer/mcpp.toml | 2 +- tests/qt-import-only/mcpp.toml | 27 ++++ tests/qt-import-only/src/main.cpp | 1 + tests/qt-sdk-consumer/mcpp.toml | 2 +- tests/qt-widgets-consumer/mcpp.toml | 2 +- 15 files changed, 330 insertions(+), 16 deletions(-) create mode 100644 .agents/docs/2026-09-27-plugins-0.15.2-plan.md create mode 100644 .agents/docs/2026-09-27-versioning-assets-locale-and-galtranslpp-review.md create mode 100644 tests/qt-import-only/mcpp.toml create mode 100644 tests/qt-import-only/src/main.cpp diff --git a/.agents/docs/2026-09-27-plugins-0.15.2-plan.md b/.agents/docs/2026-09-27-plugins-0.15.2-plan.md new file mode 100644 index 0000000..7e2a634 --- /dev/null +++ b/.agents/docs/2026-09-27-plugins-0.15.2-plan.md @@ -0,0 +1,97 @@ +# plugins 0.15.2 与生态收敛方案 + +日期:2026-09-27。依据:`2026-09-27-versioning-assets-locale-and-galtranslpp-review.md` 及其后的讨论结论。 + +## 0. 目标 + +1. Qt 以上游版本 `6.11.1` 作为唯一版本键,消费方书写上游版本。 +2. brotli 资源恢复规范文件名,GitHub 与 GitCode 逐字节一致。 +3. GalTranslPP PR2 达到当前生态能力下的最佳形态:版本单点声明、可配置项有文档、emit 开销可解释且可测。 +4. 需要 mcpp、xlings、xim glibc 改动的事项,以 issue 形式交给各自仓库。 + +非目标:修改 mcpp、xlings 或 glibc 配方本身。 + +## 1. 已确定的决策 + +| # | 决策 | 理由 | +|---|---|---| +| D1 | Qt 只保留 `6.11.1` 键,删除 `6.11.1.1` | 该包无外部消费者;持有修正前载荷的只有两处 CI 缓存与本机沙箱,均可清除 | +| D2 | brotli 资源使用规范名,删除 `-r1` | GitHub 规范名已是修正内容;下载层按 sha256 校验缓存,同名替换安全 | +| D3 | Qt 的 GitCode 资源不删除 | Qt 归档来自 Qt 官方仓库及镜像;xlings-res/qt-base 仅含 QtQml 重打包,内容正确且仍被引用 | +| D4 | 就地修正与修订号的分界 | 包在索引中无外部消费者时就地修正;有外部消费者后用第四段修订号,直至 xlings 支持 `revision` | +| D5 | 版本单点声明,按需引用 | 版本写在工作区根一处;是否使用由成员的 build.mcpp 决定,声明只提供版本与载荷可见性 | + +关键事实:`6.11.1` 与 `6.11.1.1` 共用同一配方体。因此在今天的索引上,全新安装的 `6.11.1` 已经是修正后的载荷。 +D1 的索引改动只是删除冗余键;消费方的切换不依赖它先合入。 + +## 2. 工作项 + +### 2.1 xlings-res/brotli(无需 PR) + +1. 向 GitCode 1.2.0 上传规范名资源 `brotli-1.2.0-linux-{x86_64,aarch64}.tar.gz`,文件取自 GitHub 规范名资源(sha256 `0b20a7cc…`、`07f52426…`)。 +2. 两端 `SHA256SUMS` 改为规范名(GitHub 用 `--clobber`;GitCode 已由用户删除,直接上传)。 +3. 两端逐字节核对。 + +### 2.2 xim-pkgindex:一个 PR + +- qt、qt-base、qt-addons:删除 `6.11.1.1` 键及其说明注释,`latest` 指向 `6.11.1`;qt-addons 的依赖改为 `xim:qt@6.11.1`。 +- brotli:URL 改回规范名,sha256 不变。 +- 验收:xim CI 全绿;合入后等待索引发布,再用 `xlings info` 确认 `qt-base` 只列出 `6.11.1`。 + +### 2.3 mcpp-plugins 0.15.2:一个 PR + +- `rules/qt.cppm`:缺少 SDK 时的提示改为 `"xim:qt-base" = "6.11.1"`。 +- 测试 fixture(qt-consumer、qt-widgets-consumer)与 `docs/rules-qt.md`、README:版本改为 `6.11.1`。 +- `ci.yml`:沙箱缓存 key 的前缀加代次(`mcpp-sandbox-v2-…`),`restore-keys` 同步修改。仅 fixture 哈希变化不够:现有 `restore-keys` 前缀会恢复持有旧 6.11.1 的缓存。 +- 验收:三平台 CI 全绿。其中 Linux 的 widgets 打包检查要确认新缓存下装出的 `6.11.1` 带有运行时闭包(libdbus、xkbcommon、fontconfig),这正是 D1 的实证。 +- 发布:tag v0.15.2、GitCode 镜像(sha256 比对)、mcpp-index 登记。 + +### 2.4 GalTranslPP PR2 + +| 项 | 内容 | 验收 | +|---|---|---| +| E1 版本 | `xim:qt-base` 改为 `6.11.1`;`mcpp.plugins` 改为 0.15.2 | CI 全绿 | +| E2 插件版本单点 | 根 `[workspace.dependencies] mcpp.plugins = "0.15.2"`,成员写 `{ workspace = true, features = [...], host-module = true }` | 构建通过;不支持时回退为逐成员声明,并记入 mcpp issue | +| E3 xlings 条目单点 | `xim:qt-base`、`xim:7zip` 移至根清单 `[target.windows.xlings.workspace]` | 成员构建程序中 rules-qt 事实为 `xlings: …/6.11.1`,7z.dll 仍在发布目录;不生效时回退并记入 mcpp issue | +| E4 文档 | `how-to-build.md`:Qt 6.11.1;以 `> 注:` 说明 `QT_ROOT_DIR`、vcpkg 的 `options.root`、`VCPKG_DOWNLOADS`、`VCPKG_DEFAULT_BINARY_CACHE`、`fast-release`,并注明:不使用 xim 的 Qt 时,注释掉 `xim:qt-base` 的声明,再设置 `QT_ROOT_DIR`,或在 build.mcpp 中以 `qt.root` 指定路径(声明即下载,属预期行为) | 评审 | +| E5 注释 | 修正成员清单中 7z 与 Qt 注释的错位(E3 成立时随之消失) | 评审 | +| E6 emit 测量 | CI 增加"再跑一次 emit"步骤并计时;首次 emit 加 `-v`,定位 5 条 "no Qt SDK" 警告的来源 | 得到第二次 emit 的实测时间与警告来源 | +| E7 缓存 | xpkgs 缓存 key 升级 | 日志显示 Qt 按 `6.11.1` 新装 | + +E6 若查明警告来自插件(例如 rules-qt 在不需要 Qt 的构建程序中被调用),修正并入 0.15.2;否则记入 mcpp issue。 + +### 2.5 收尾 + +1. 索引发布后删除 GitHub 的 brotli `-r1` 资源(我),GitCode 的 `-r1` 资源由用户删除。 +2. 删除本机沙箱中修正前的 Qt 载荷。 +3. 更新两份评估文档与交付记录。 + +## 3. 顺序与依赖 + +``` +2.1 brotli 资源 ──► 2.2 xim PR ──► 索引发布 ──► 2.5-1 删除 -r1 +2.3 plugins 0.15.2 ──► 发布 + index 登记 ──► 2.4 GalTranslPP PR2 +``` + +两条链互不阻塞:2.3 与 2.4 使用 `6.11.1` 键,该键今天已存在且内容已修正(见 §1 关键事实)。 + +## 4. 上游 issue(已提交,由上游决定处理方式) + +| issue | 内容 | 是否阻碍开发 | +|---|---|---| +| mcpp-community/mcpp#710 | 宿主工具的子构建不使用其缓存键记录的工具链,首次 emit 额外安装 llvm@20.1.7 | 否:只增加首次耗时和磁盘占用 | +| mcpp-community/mcpp#711 | 发布物无法依赖另一个包按目标平台构建的可执行文件,只能借宿主工具边 | 否:本机构建结果正确;交叉编译时才会出错 | +| mcpp-community/mcpp#712 | `xpkg_dir` 把裸版本当字面 pin,xlings 则会匹配到四段版本键;已复现(libglvnd `1.7` → 装了 1.7.0.1,`xpkg_dir` 返回空) | 否:写精确版本键即可避开 | +| openxlings/xlings#620 | 配方修订号独立于版本号 | 否:没有外部用户时就地修正(D4) | +| openxlings/xlings#621 | glibc 载荷没有 locale 数据,编译进去的 locale 路径不在载荷内 | 否:只是一条提示;GalTranslPP 仅构建 Windows,不受影响 | + +不再提交:设置 `QT_ROOT_DIR` 时仍下载声明的 Qt。这是预期行为,按 E4 写进文档。 +视 E2、E3 的结果,可能再提交"xlings 条目支持从工作区继承"。 + +## 5. 风险 + +| 风险 | 缓解 | +|---|---| +| 删除 `6.11.1.1` 后,仍书写 `6.11.1.1` 的消费方解析失败 | 已知消费方只有 plugins fixture 与 GalTranslPP,二者均在本方案中改为 `6.11.1` | +| 某处缓存仍恢复出修正前的 `6.11.1` 载荷 | 两处 CI 缓存 key 均升级;Linux widgets 打包检查会在闭包缺失时失败 | +| E2 或 E3 不被 mcpp 支持 | 回退为逐成员声明,不阻塞发布 | diff --git a/.agents/docs/2026-09-27-versioning-assets-locale-and-galtranslpp-review.md b/.agents/docs/2026-09-27-versioning-assets-locale-and-galtranslpp-review.md new file mode 100644 index 0000000..80bda2e --- /dev/null +++ b/.agents/docs/2026-09-27-versioning-assets-locale-and-galtranslpp-review.md @@ -0,0 +1,147 @@ +# 版本号、资源命名、locale 与 GalTranslPP 构建体验评估 + +日期:2026-09-27。范围:0.15.x 交付遗留的三个问题的最佳形态,以及 GalTranslPP PR2 相对 VS 与早期 mcpp 构建的对比。 +所有结论均经本地实验或源码核对;证据列于各节末尾。 + +## 1. Qt 版本号 6.11.1.1 + +### 1.1 事实 + +| 组件 | 行为 | 证据 | +|---|---|---| +| xlings 安装判定 | 仅依据 `(ns, name, version)` 对应的载荷目录与 ledger;不存在配方修订号、构建号或载荷哈希 | `xlings/src/core/xim/install_state.cpp:35-80`;`xim-pkgindex/pkgs/g/glibc.lua:93-101` | +| xlings 版本解析 | 先按字面键查找;未命中时按区间解析,三段精确版本以三段为下限比较,`12.9.1` 选中 `12.9.1.4` | `semver.cppm:255-264`;本地 `xlings info libcublas 12.9.1` → 12.9.1.4 | +| xlings 区间安装 | 已安装版本满足区间时不升级:`~6.11.1` 在装有 6.11.1 的机器上保持 6.11.1 | 本地实验:同步索引后以 `~6.11.1` 构建 qt-consumer,仍使用 6.11.1 | +| mcpp 载荷定位 | 先取字面目录;三段精确版本视为 pin,字面目录缺失即返回空,不接受 6.11.1.x | `mcpp/src/xlings/xlings.cppm:941-951` | +| 生态先例 | 第四段作为打包修订:fontconfig 2.15.0.1、libglvnd 1.7.0.1、llvm-dev 20.1.7.1 | `xim-pkgindex/pkgs/` | + +### 1.2 结论(2026-09-27 修订) + +6.11.1 与 6.11.1.1 均于 2026-09-26 发布,项目 CI 之外没有消费者。持有修正前 6.11.1 载荷的只有三处: +plugins CI 缓存、GalTranslPP CI 缓存与本机沙箱,均可清除。修订号的价值在于保护已有用户,此处不存在该前提。 + +- **最佳形态:只保留一个键 `6.11.1`,内容为修正后的配方;删除 `6.11.1.1`。** 消费方写上游版本 `6.11.1`,xlings 与 mcpp 都按字面解析,两侧一致。 +- 清理:两处 CI 的缓存 key 升级,本机沙箱删除旧载荷。 +- 约定:包在索引中没有外部消费者时,就地修正;有外部消费者后,使用第四段修订号,直到 xlings 支持 `revision`(§1.3)。 + +### 1.3 根治方向(生态层,非本次交付) + +1. xlings:配方声明 `revision`,ledger 记录之;修订不一致即重装。此后打包修正不再需要新版本键,用户写上游版本 `6.11.1`。 +2. mcpp:载荷定位与 xlings 采用同一解析规则(或直接询问 xlings 选定的版本),消除"一个问题两个答案"。 + +## 2. brotli 的 `-r1` 资源名 + +### 2.1 事实 + +- GitHub `xlings-res/brotli@1.2.0`:规范名 `brotli-1.2.0-linux-{x86_64,aarch64}.tar.gz` 已是修正内容,sha256 与 `-r1` 相同(`0b20a7cc…`、`07f52426…`)。 +- GitCode 同名资源仍是缺头文件的旧内容;`gtc` 无删除与覆盖能力。 +- xlings 下载缓存以 URL 文件名为键;配方声明 sha256 时,缓存文件校验失败即重新下载(`downloader.cpp:508-525`)。因此同名替换对下载层是安全的。 +- 受影响面:已安装旧 brotli 载荷的机器不会重装(见 §1.1),但缺失的仅是头文件;Qt 只加载 `.so`,无功能影响。 + +### 2.2 最佳形态与步骤 + +目标:两端恢复规范名,配方不再引用 `-r1`。 + +1. **(需你手动)** 在 GitCode `xlings-res/brotli` 的 1.2.0 release 中删除 `brotli-1.2.0-linux-x86_64.tar.gz`、`brotli-1.2.0-linux-aarch64.tar.gz` 与 `SHA256SUMS`。 +2. 以规范名向 GitCode 上传修正文件,并在两端上传规范名的 `SHA256SUMS`;随后逐字节核对两端。 +3. xim-pkgindex PR:brotli 的 URL 改回规范名,sha256 不变。 +4. 索引发布后,删除两端的 `-r1` 资源(GitHub 由我执行,GitCode 由你手动)。 + +约定(写入发布流程):资源发布前先在本地以配方安装一次并检查载荷;已发布资源若有误,同名替换并更新 sha256,不另起文件名。 + +## 3. xlings glibc 缺少 UTF-8 locale + +### 3.1 事实 + +- xim glibc 载荷不含 `lib/locale` 与 `locale-archive`;libc 编译期 locale 路径为占位符 `/nonexistent/xlings-use-rpath-not-default-search/lib/locale`,不存在。 +- 因此 `setlocale(LC_ALL, "")` 在任何主机上都回落到 `C`,Qt 报告 "failed to switch to UTF-8"。 +- 本地实验:用载荷自带的 `localedef` 生成 `C.utf8`(416 KB),经 `LOCPATH` 提供后,Qt 输出变为 "has switched to C.UTF-8",即功能恢复。 + +### 3.2 影响 + +- GalTranslPP:无影响(仅 Windows)。 +- Linux 上的 Qt 程序:Qt 6 在 Unix 上的 local8Bit 固定为 UTF-8,Qt 自身文本处理不受影响;受影响的是程序直接调用的 C 库多字节与宽字符函数(`mbstowcs`、`std::locale("")` 等)。 + +### 3.3 最佳形态 + +归属 xim glibc 配方(非插件、非 mcpp): + +1. 载荷内置 `lib/locale/C.utf8`(416 KB); +2. 安装时将占位符前缀改写为载荷前缀(与 elfpatch 改写解释器同理),使 libc 默认 locale 路径指向载荷自身。 + +两项完成后无需 `LOCPATH`,`mcpp run` 与 `mcpp pack` 产物行为一致。不采用 `LOCPATH` 注入方案:它对打包后由用户直接启动的程序无效。 + +## 4. GalTranslPP:VS → mcpp → 优化后的 mcpp + +### 4.1 首次构建所需操作(Windows) + +| | VS(ebd2a90 之前) | mcpp(上游 8a2c76a) | 优化后 mcpp(PR2,plugins 0.15.1) | +|---|---|---|---| +| 手动安装 | VS 2026 IDE(指定 MSVC v14.50)、CMake、git、vcpkg(克隆、bootstrap、integrate)、Qt 在线安装器(需账户)、Qt VS Tools 插件 | xlings、mcpp、VS Build Tools、CMake、Python、git、vcpkg(克隆、bootstrap、PATH)、Qt 在线安装器 | git、xlings、VS Build Tools | +| Qt 路径配置 | 3 处:Qt VS Tools 导入、ElaWidgetTools `CMakeLists.txt`、vcxproj `QtInstall` | 2 处:`build.py`、`qt-root.txt` | 0 处 | +| 依赖构建 | 手动运行 `build.bat` 编译 ElaWidgetTools,并检查 3 个产物 | 手动运行 `build.py` 与 `vcpkg install --triplet …` | 由构建完成(`deps-cmake`、`deps-vcpkg`) | +| 构建命令 | IDE 中切换 Release 并逐项目生成 | `mcpp build -p GPPCLI/GPPGUI` | 同左 | +| 运行时部署 | `Release.bat` | 解压 Python、`Release.py`、`windeployqt` ×2 | 由构建完成:Qt 库、插件与翻译、Ela、vcpkg DLL、7z.dll、Python、OpenCC、BaseConfig、VC++ 运行时 | +| 分发 | 手动整理 | 手动整理 | `mcpp pack --format dir` | +| 手动步骤合计 | 约 12 | 约 13 | 4(安装 xlings、安装 mcpp、克隆、`mcpp build`) | + +### 4.2 CI 耗时(GitHub Windows runner) + +| 阶段 | 早期 mcpp + 手动 vcpkg(run 36164741493) | plugins 0.14.0(run 36234085633) | plugins 0.15.1(run 36260450278) | +|---|---|---|---| +| vcpkg 二进制缓存 | 未命中,独立安装 51 分钟 | 命中 678 MB,缺失部分在 emit 中源码编译(保存后增至 999 MB) | 命中 999 MB,完整 | +| `mcpp emit`(全新 checkout) | 0.4 分钟(依赖已预装) | 53 分钟 | 4.8 分钟 | +| GPPCLI(fast-release) | — | 6.5 分钟 | 6.3 分钟 | +| GPPGUI(fast-release) | — | 18.0 分钟 | 19.7 分钟 | +| 无改动的第二次构建 | — | 0.8 分钟,无安装 | 0.8 分钟,无安装 | + +更正:53 → 4.8 分钟的主要原因是 vcpkg 二进制缓存从部分命中变为完整命中,而非移除 mcpp-deps。 + +全新 checkout 上 emit 的 4.8 分钟包含: + +1. **宿主工具构建**:GPPGUI 以 `tools = ["Updater"]` 取得 Updater.exe,emit 为此以宿主身份完整构建 Updater(Qt 与 vcpkg 程序),runtime_stage 同理。 +2. **第二套 LLVM**:宿主工具构建不继承工作区的 `[toolchain] windows = "llvm@22.1.8"`,日志显示 "no toolchain configured — installing llvm@20.1.7",因此额外下载一套 LLVM 并编译其 std 模块。 +3. **vcpkg 安装**:Updater 的构建会执行 vcpkg install,此时从二进制缓存恢复约 22 个库。 +4. **构建程序**:5 个成员的 build.mcpp 及其 host 模块(mcpp.plugins、gpp.build)各编译一次。 + +已构建过一次后,宿主工具按"包源码 + 宿主工具链"缓存,vcpkg 前缀已存在,构建程序显示 "up to date (cached)",因此 emit 预计为秒级。 +同条件下的"第二次构建"为 0.8 分钟,可作旁证;emit 本身未单独测量。 + +另:Updater 作为发布物,语义上是目标产物而非宿主工具(交叉编译时架构即不同)。 +以宿主工具取得它,既导致重复构建,也引入第二套工具链。正确形态需要 mcpp 提供"目标产物依赖"或工作区级发布布局。 + +### 4.3 可配置项 + +| 配置项 | 方式 | 当前状态 | +|---|---|---| +| Qt SDK | build.mcpp `qt.root` → `QT_ROOT_DIR` → 成员声明的 `xim:qt-base` | 可用;设置 `QT_ROOT_DIR` 时 `xim:qt-base` 仍会被下载(mcpp 无条件安装声明的包) | +| vcpkg 根目录 | build.mcpp `options.root`,缺省为 `xim:vcpkg` | 可用;有意不读 `VCPKG_ROOT`,以保证版本确定 | +| vcpkg 下载与二进制缓存 | `VCPKG_DOWNLOADS`、`VCPKG_DEFAULT_BINARY_CACHE` | 可用 | +| 工具链 | 根 `mcpp.toml` `[toolchain] windows = "llvm@22.1.8"` | 可用 | +| 优化级别 | `--profile release` / `fast-release` | 可用 | + +### 4.4 与最佳形态的差距 + +| # | 差距 | 处理 | +|---|---|---| +| G1 | `how-to-build.md` 写 "Qt 6.11.1",清单写 `6.11.1.1`,且未说明可配置项 | 改 PR2 文档:版本统一为 `6.11.1`,以 `> 注:` 说明 `QT_ROOT_DIR`、vcpkg 缓存变量与 `fast-release` | +| G2 | 版本重复声明:`mcpp.plugins` 在 5 个成员中各写 `0.15.1`;`xim:qt-base` 与 `xim:7zip` 在 4 个成员中各写一次 | `mcpp.plugins` 改用已有的 `[workspace.dependencies]` 加 `.workspace = true`(需验证它能否与 `features`、`host-module` 同用)。xlings 条目没有逐项继承机制:先验证根清单的 `[target.windows.xlings.workspace]` 被继承后 `xpkg_dir` 是否对成员生效;不生效则向 mcpp 提出 xlings 条目的 `.workspace = true` | +| G3 | `QT_ROOT_DIR` 生效时仍下载 `xim:qt-base` | mcpp 侧能力:声明可被覆盖的 xlings 包;记为 mcpp issue 候选 | +| G4 | 仍需手动安装 VS Build Tools(vcpkg 的 MSVC triplet 与 ElaWidgetTools) | 长期项:vcpkg chainload mcpp 的 clang;现阶段保留为文档前提 | +| G5 | 成员清单中 7z 的注释位于 Qt 条目之上 | 随 G1 修正 | +| G6 | PR2 为验证分支(`ci(temporary)` 提交) | 向上游提交时压缩为一次迁移提交,CI 工作流按上游需要保留或删除 | +| G7 | emit 的首次开销来自宿主工具与第二套 LLVM(§4.2) | mcpp:宿主工具继承工作区工具链;提供目标产物依赖。在此之前,GalTranslPP 可先在 CI 中固定默认工具链 | + +### 4.5 结论 + +构建体验已达到当前生态能力下的最佳形态:首次构建为 4 个步骤,路径配置为零,运行时完整部署,第二次构建无安装。 +剩余差距中,G1 与 G5 属于文档修正,可立即完成;G2 需一次 CI 验证;G3 与 G4 取决于 mcpp 与工具链能力,不影响当前可用性。 + +## 5. 待决事项 + +| 事项 | 负责方 | +|---|---| +| 删除 GitCode brotli 旧资源(§2.2 第 1 步与第 4 步) | 你 | +| brotli 恢复规范名(§2.2 第 2、3 步) | 我,在你完成删除后执行 | +| PR2 文档修正(G1、G5)与 G2 验证 | 我 | +| glibc locale(§3.3)、xlings 修订号(§1.3-1)、mcpp 解析一致性(§1.3-2)与可覆盖声明(G3) | 各仓库 issue,待你确认后提交 | diff --git a/.github/scripts/check-deps-and-qt.sh b/.github/scripts/check-deps-and-qt.sh index 08b9b69..728b998 100644 --- a/.github/scripts/check-deps-and-qt.sh +++ b/.github/scripts/check-deps-and-qt.sh @@ -328,6 +328,17 @@ qt_sdk_consumer() { echo "ok: options::root names the SDK ahead of QT_ROOT_DIR" } +qt_import_only() { + cd "$ROOT/tests/qt-import-only" + rm -rf target + mkdir -p target/ci + "$MCPP" build 2>&1 | tee target/ci/build.log + grep -q 'build.mcpp running' target/ci/build.log || fail "mcpp synthesised no build program for the rule" + ! grep -q 'no Qt SDK' target/ci/build.log || + fail "a synthesised program with no SDK and no Qt source reported a missing SDK" + echo "ok: a package that enables rules-qt only for its module builds without a report" +} + case "${1:-}" in vcpkg-consumer) vcpkg_consumer ;; vcpkg-libcxx) vcpkg_libcxx ;; @@ -337,5 +348,6 @@ case "${1:-}" in qt-consumer) qt_consumer ;; qt-widgets-consumer) qt_widgets_consumer ;; qt-sdk-consumer) qt_sdk_consumer ;; - *) echo "usage: $0 vcpkg-consumer|vcpkg-libcxx|archive-consumer|vcpkg-workspace|cmake-consumer|qt-consumer|qt-widgets-consumer|qt-sdk-consumer"; exit 2 ;; + qt-import-only) qt_import_only ;; + *) echo "usage: $0 vcpkg-consumer|vcpkg-libcxx|archive-consumer|vcpkg-workspace|cmake-consumer|qt-consumer|qt-widgets-consumer|qt-sdk-consumer|qt-import-only"; exit 2 ;; esac diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a6bace..e0917a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,9 +98,9 @@ jobs: uses: actions/cache@v4 with: path: ~/.mcpp - key: mcpp-sandbox-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-${{ hashFiles('tests/*/mcpp.toml') }} + key: mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-${{ hashFiles('tests/*/mcpp.toml') }} restore-keys: | - mcpp-sandbox-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}- + mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}- - name: Fetch the released mcpp run: | @@ -1677,6 +1677,9 @@ jobs: - name: rules-qt takes the SDK from the project's payload, QT_ROOT_DIR or options::root run: bash .github/scripts/check-deps-and-qt.sh qt-sdk-consumer + - name: a package that enables rules-qt only for its module builds without a report + run: bash .github/scripts/check-deps-and-qt.sh qt-import-only + # ── THE SAME RULE ON THE OTHER TWO PLATFORMS ──────────────────────────────── # # `rules-spirv` is the only member whose payload this ecosystem publishes for @@ -1749,9 +1752,9 @@ jobs: uses: actions/cache@v4 with: path: ~/.mcpp - key: mcpp-sandbox-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-${{ hashFiles('tests/spirv-consumer/mcpp.toml') }} + key: mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-${{ hashFiles('tests/spirv-consumer/mcpp.toml') }} restore-keys: | - mcpp-sandbox-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}- + mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}- - name: Fetch the released mcpp run: | @@ -2360,3 +2363,6 @@ jobs: - name: rules-qt takes the SDK from the project's payload, QT_ROOT_DIR or options::root run: bash .github/scripts/check-deps-and-qt.sh qt-sdk-consumer + + - name: a package that enables rules-qt only for its module builds without a report + run: bash .github/scripts/check-deps-and-qt.sh qt-import-only diff --git a/README.md b/README.md index 3772b9b..8caef87 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ module name the member declares, and configures it there. ```toml [build-dependencies.mcpp] -plugins = { version = "0.15.1", features = ["rules-spirv"], host-module = true } +plugins = { version = "0.15.2", features = ["rules-spirv"], host-module = true } ``` ```cpp diff --git a/docs/deps.md b/docs/deps.md index 9e4596e..a27827b 100644 --- a/docs/deps.md +++ b/docs/deps.md @@ -24,7 +24,7 @@ Module `mcpp.deps.archive`; engine floor: 2026.9.26.2. ```toml [build-dependencies.mcpp] -plugins = { version = "0.15.1", features = ["deps-vcpkg"], host-module = true } +plugins = { version = "0.15.2", features = ["deps-vcpkg"], host-module = true } ``` ```cpp diff --git a/docs/rules-qt.md b/docs/rules-qt.md index f5fc9cb..0857025 100644 --- a/docs/rules-qt.md +++ b/docs/rules-qt.md @@ -6,11 +6,11 @@ ```toml [build-dependencies.mcpp] -plugins = { version = "0.15.1", features = ["rules-qt"], host-module = true } +plugins = { version = "0.15.2", features = ["rules-qt"], host-module = true } # The SDK and its version are the project's declaration. [target.'cfg(any(windows, linux, macos))'.xlings.workspace] -"xim:qt-base" = "6.11.1.1" +"xim:qt-base" = "6.11.1" [build] sources = ["src/*.cpp", "res/*.qrc", "i18n/*.ts", "ui/*.ui"] @@ -45,7 +45,21 @@ The first of three levels that names an SDK decides, and the rule records which | `xim:qt` | qtbase, qtsvg, qtdeclarative, qttools, qttranslations | | `xim:qt-addons` | the additional libraries, beside `xim:qt` | -The payloads that carry their runtime closure are version `6.11.1.1` (the Qt 6.11.1 archives, laid out anew); a machine that holds `6.11.1` keeps the earlier layout. 0.15.0 removed the features `rules-qt-xim`, `rules-qt-xim-base` and `rules-qt-xim-addons`, which declared a payload at a fixed version: a feature states a mechanism, and the SDK a program links is the project's choice. A project that named one declares the payload instead, as above. +Each payload carries its runtime closure: the loader and the libraries Qt loads on Linux, and the VC++ runtime on Windows x64. 0.15.0 removed the features `rules-qt-xim`, `rules-qt-xim-base` and `rules-qt-xim-addons`, which declared a payload at a fixed version. A feature states a mechanism; the SDK a program links is the project's choice. A project that used one of those features declares the payload instead, as above. + +A project that does not use a payload comments out its declaration, because `mcpp build` provisions every declared payload whether or not a higher level names another SDK. It then names its SDK with `QT_ROOT_DIR` or with `options::root` in `build.mcpp`: + +```toml +[target.'cfg(any(windows, linux, macos))'.xlings.workspace] +# "xim:qt-base" = "6.11.1" +``` + +```cpp +mcpp::rules::qt::options o; +o.root = "D:/Qt/6.11.1/msvc2022_64"; // or leave empty and set QT_ROOT_DIR +``` + +A package that enables `rules-qt` only to import `mcpp.rules.qt`, and writes no `build.mcpp`, runs the program mcpp synthesises. When it has no SDK and no `.ui`, `.qrc` or `.ts` of its own, that program reports nothing (0.15.2; mcpp#715). ## Options diff --git a/mcpp.toml b/mcpp.toml index cd6e554..f99e027 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] name = "plugins" namespace = "mcpp" -version = "0.15.1" +version = "0.15.2" description = "Official mcpp build plugins: rule packages under mcpp.rules.*, build-time utilities under mcpp.tools.*, each member selected by a feature" license = "Apache-2.0" authors = ["mcpp-community"] diff --git a/rules/qt.cppm b/rules/qt.cppm index 6a8528f..67f4534 100644 --- a/rules/qt.cppm +++ b/rules/qt.cppm @@ -362,11 +362,21 @@ inline bool compile(options opt = {}) { const sdk_source source = locate(opt); const auto& sdks = source.roots; if (sdks.empty()) { + // A package that enables `rules-qt` only to import this module, such as + // a library of build logic, and writes no `build.mcpp` gets the program + // mcpp synthesises, which calls compile() with the defaults. Without an + // SDK and without a `.ui`, `.qrc` or `.ts` of its own, that program + // asked for nothing, so it says nothing (0.15.2; mcpp#715). + std::error_code missing_ec; + if (!fs::exists(fs::path(mcpp::manifest_dir()) / "build.mcpp", missing_ec) + && detail::device(".ui").empty() && detail::device(".qrc").empty() + && detail::device(".ts").empty()) + return true; detail::warn(std::format( "{}: no Qt SDK{}. Nothing Qt-specific is planned. Name one with options::root or " "QT_ROOT_DIR, or declare a payload, which `mcpp build` provisions:\n" " [target.'cfg(any(windows, linux, macos))'.xlings.workspace]\n" - " \"xim:qt-base\" = \"6.11.1.1\"", + " \"xim:qt-base\" = \"6.11.1\"", who, source.level.empty() ? std::string() : " at the directory " + source.level + " names")); return true; diff --git a/src/plugins.cppm b/src/plugins.cppm index 7e6443a..5e4c2ff 100644 --- a/src/plugins.cppm +++ b/src/plugins.cppm @@ -49,7 +49,7 @@ export namespace mcpp::plugins { // // One package, one version: the number lives in mcpp.toml, and the CI step // `the collection states its own version` compares the two. -inline constexpr std::string_view version = "0.15.1"; +inline constexpr std::string_view version = "0.15.2"; } // namespace mcpp::plugins diff --git a/tests/qt-consumer/mcpp.toml b/tests/qt-consumer/mcpp.toml index 96cfba9..00821bc 100644 --- a/tests/qt-consumer/mcpp.toml +++ b/tests/qt-consumer/mcpp.toml @@ -37,7 +37,7 @@ plugins = { path = "../..", features = ["rules-qt"], host-module = true } # The SDK is the project's declaration, at the version it chooses. [target.'cfg(any(windows, linux, macos))'.xlings.workspace] -"xim:qt-base" = "6.11.1.1" +"xim:qt-base" = "6.11.1" [build] # Qt's Linux libraries load the shared libstdc++ (`libstdc++.so.6`), so the diff --git a/tests/qt-import-only/mcpp.toml b/tests/qt-import-only/mcpp.toml new file mode 100644 index 0000000..2ce4777 --- /dev/null +++ b/tests/qt-import-only/mcpp.toml @@ -0,0 +1,27 @@ +# Fixture: a package that enables `rules-qt` only to import `mcpp.rules.qt`, +# the shape of a library of build logic that other packages' build programs +# import (GalTranslPP's `gpp.build`). It writes no `build.mcpp`, has no `.ui`, +# `.qrc` or `.ts`, and declares no Qt, so the program mcpp synthesises for it +# asks for nothing and reports nothing (0.15.2; mcpp#715). +[package] +name = "qt-import-only" +version = "0.1.0" +description = "Fixture: rules-qt enabled only for its module" +license = "Apache-2.0" +authors = ["mcpp-community"] + +[language] +standard = "c++23" +modules = true +import_std = false + +[build-dependencies.mcpp] +plugins = { path = "../..", features = ["rules-qt"], host-module = true } + +[build] +cxx_runtime = "toolchain-coupled" +sources = ["src/*.cpp"] + +[targets.qt-import-only] +kind = "bin" +main = "src/main.cpp" diff --git a/tests/qt-import-only/src/main.cpp b/tests/qt-import-only/src/main.cpp new file mode 100644 index 0000000..76e8197 --- /dev/null +++ b/tests/qt-import-only/src/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/qt-sdk-consumer/mcpp.toml b/tests/qt-sdk-consumer/mcpp.toml index aaf01d9..165f4ce 100644 --- a/tests/qt-sdk-consumer/mcpp.toml +++ b/tests/qt-sdk-consumer/mcpp.toml @@ -21,7 +21,7 @@ import_std = false plugins = { path = "../..", features = ["rules-qt"], host-module = true } [target.'cfg(any(windows, linux, macos))'.xlings.workspace] -"xim:qt-base" = "6.11.1.1" +"xim:qt-base" = "6.11.1" [build] # Qt's Linux libraries load the shared libstdc++; see tests/qt-consumer. diff --git a/tests/qt-widgets-consumer/mcpp.toml b/tests/qt-widgets-consumer/mcpp.toml index fabda0e..fcc68eb 100644 --- a/tests/qt-widgets-consumer/mcpp.toml +++ b/tests/qt-widgets-consumer/mcpp.toml @@ -25,7 +25,7 @@ plugins = { path = "../..", features = ["rules-qt"], host-module = true } # The SDK is the project's declaration: the full base package here, and # `xim:qt-base` in tests/qt-consumer. [target.'cfg(any(windows, linux, macos))'.xlings.workspace] -"xim:qt" = "6.11.1.1" +"xim:qt" = "6.11.1" # Built, run and packed on every host by CI. On Linux the payload carries # QtGui's runtime closure (libdbus, fontconfig, xcb, ...); on Windows, the VC++ From 879b67d0019876ec7e54cd6f8c69b277d53b26c1 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Sun, 27 Sep 2026 04:50:48 +0800 Subject: [PATCH 2/2] plan: the execution record -- E2 holds for members only (mcpp#714), E3 does not (mcpp#713), the warnings came from gpp.build's synthesised program (mcpp#715) --- .agents/docs/2026-09-27-plugins-0.15.2-plan.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.agents/docs/2026-09-27-plugins-0.15.2-plan.md b/.agents/docs/2026-09-27-plugins-0.15.2-plan.md index 7e2a634..4628e91 100644 --- a/.agents/docs/2026-09-27-plugins-0.15.2-plan.md +++ b/.agents/docs/2026-09-27-plugins-0.15.2-plan.md @@ -95,3 +95,18 @@ E6 若查明警告来自插件(例如 rules-qt 在不需要 Qt 的构建程序 | 删除 `6.11.1.1` 后,仍书写 `6.11.1.1` 的消费方解析失败 | 已知消费方只有 plugins fixture 与 GalTranslPP,二者均在本方案中改为 `6.11.1` | | 某处缓存仍恢复出修正前的 `6.11.1` 载荷 | 两处 CI 缓存 key 均升级;Linux widgets 打包检查会在闭包缺失时失败 | | E2 或 E3 不被 mcpp 支持 | 回退为逐成员声明,不阻塞发布 | + +## 6. 执行记录(2026-09-27) + +| 项 | 结果 | +|---|---| +| 2.1 brotli | GitCode 已上传规范名资源与 `SHA256SUMS`,两端逐字节一致;GitHub 的 `-r1` 已删除;GitCode 的 `-r1` 待用户删除 | +| 2.2 xim | openxlings/xim-pkgindex#891 已合入(4c1dc850);发布后的索引中 qt、qt-base、qt-addons 只列出 `6.11.1`;brotli 按规范名安装,带头文件 | +| 2.3 plugins | mcpp-community/mcpp-plugins#34。本地 Linux 四项检查通过,均在清空载荷与 provisioning 印记后全新安装 `6.11.1` | +| E2 | 成员的 `.workspace = true` 可以与 `features`、`host-module` 同用。非成员的 `gpp.build` 不能继承(mcpp#714),改为自带版本;若把它设为成员,根目录的 `mcpp build` 会把它当作目标构建并失败 | +| E3 | 不成立:三种写法(带 cfg 的 target 表、`[target.linux]`、`[xlings.workspace]`)写在根清单时,成员的构建程序都看不到载荷(mcpp#713)。回退为逐成员声明 | +| E6 警告来源 | 21 条 "no Qt SDK" 全部来自 `gpp.build`:它启用 `rules-qt` 只为导入模块,自己没有 build.mcpp,mcpp 仍为它合成规则程序(mcpp#715)。0.15.2 让这种情况不再输出提示;新增 fixture `qt-import-only` | +| Qt 路径单点 | GalTranslPP 的 `gpp::qt_root` 与 `gpp::qt_options()` 汇集到一处:规则、发布布局、ElaWidgetTools 的 `QT_SDK_DIR` 都取同一个 SDK | + +新发现并已提交的 mcpp issue:#713(根清单的 xlings 声明对成员不可见)、#714(非成员的 `.workspace = true` 变成空版本)、 +#715(没有设备源也合成规则程序)、#716(provisioning 印记在载荷删除后仍然有效)。