feat(eui-neo): 接上 Linux 托盘(EUI_TRAY_SNI),全部取自 xim - #269
Merged
Conversation
0.5.7 的 `tray_bridge.c` 新增了走 GDBus 的 freedesktop StatusNotifierItem 后端:设 `EUI_TRAY_SNI` 之后只需要 glib/gio,不再需要 GTK3 + libappindicator。 此前 Linux 腿只能编 `EUI_TRAY_HAS_BACKEND=0` 的桩。 ## 来源:全部在 mcpp + xlings 体系内,不碰宿主 - **构建**:`xim:glib@2.80.0`。install() 把它的头文件与它自己的四个 `.so` 拷进包里(6.6 MB),编译与链接因此自足且版本固定。 - **运行**:glib 自己拉的那些**不暂存**,经 subos 库视图解析。实测闭包: libz→xim:zlib、libmount→xim:util-linux、libselinux→xim:libselinux、 libffi→xim:libffi、libpcre2→xim:pcre2。⚠️ **不暂存 libz 是一个决定**:包里再放一份对任何同时构建 `compat.zlib` 的 消费者就是第二个提供者(mcpp#519)。最省的做法是不发那个副本。 ## 三处写下来的理由 - `-DEUI_TRAY_SNI=1` 对每个已发布版本都安全:0.5.6 及更早根本没有那一支 (对着 tarball 核过),预处理器落回原来的桩。`mcpp` 段版本无关,必须核实。 - 显式 `-L` 与 `runtime.library_dirs` 不重复:后者只变成 `-Wl,-rpath`。 - `*/` 的 wrap 层由 install() 归一,**纯 xmake Lua**(Windows 没有 `sh`, 而这个沙箱里既没有 `os.files` 也没有 `path.basename`)。⚠️ 扁平分支是防御性的:实测 gitcode 的 tarball 与 GitHub 是同一份字节。 - 为什么默认开启而不是 feature:xpkg 的 feature 带不了 `ldflags`,关掉的 消费者照样链 glib —— 代价一样、托盘没有。详见描述符里的注释与 mcpp#522。 ## CN 镜像 0.5.7 此前 404、0.5.5 的注释还写着「从未发布」。本地 gtc 各发一次并 **重新下载核过**(sha256 与描述符一致、wrap 层一致),三个平台腿都改成 `{ GLOBAL, CN }`。 ## 验证(mcpp 2026.8.28.2) readelf -d bin/traytest | grep NEEDED libgio-2.0.so.0 libgobject-2.0.so.0 libglib-2.0.so.0 ./traytest eui_tray_init -> 1 # 真的注册上了 StatusNotifierWatcher survived shutdown 桩里没有任何 `g_dbus` 引用,这个二进制里有 10 处。
Sunrisepeak
force-pushed
the
feat/eui-neo-linux-sni-tray
branch
from
August 28, 2026 02:33
8bbdd11 to
d9ff56b
Compare
Sunrisepeak
added a commit
that referenced
this pull request
Aug 28, 2026
索引里六个 eui-neo 示例,没有一个碰托盘,也没有一个**能**碰:
tray_bridge.c 的 `#else` stub 定义了全部六个同名符号、每个返回 0。
Linux 腿一旦丢掉 `-DEUI_TRAY_SNI=1`,照样编译、照样链接、六个示例
全部照常变绿,而托盘静默消失。
新增 tests/examples/eui-neo-tray,两件事:
1. 用户可抄的写法。走公开的 `core::platform` 接口(六个自由函数 +
两字段结构体),不走内部的 core/platform/tray_bridge.h。托盘不需要
窗口、不需要 GL、不需要 DSL app loop —— 一个纯托盘程序就十行。
2. 判据。做了两版,第一版是钝的,而且是实测证伪的:
- `dlsym(RTLD_DEFAULT, "g_bus_get_sync") != nullptr` —— 把 define
拿掉重建,它照样通过。描述文件的 ldflags 无条件带 `-lgio-2.0`,
所以 gio 始终在 DT_NEEDED 里。它回答的是「gio 链上了吗」,
不是「后端是真的吗」。
- 自起一条私有 session bus,断言 `initializeTray()` 为真。不需要
显示器、不需要面板、不需要桌面会话,普通 runner 就能跑。
双向实测(把实现退回去再跑,确认判据不是空转的唯一办法):
真后端 -> ok,"verified over a private session bus"
stub -> FAIL (exit 1),并指出是描述文件哪一行
dbus-run-session 起不来时报错退出而不是跳过 —— 「没验成」不能和
「验过了」同一个读数,这正是本 member 存在的理由。
描述文件同时更正三处(净代码 -5 行,但文件 +16 行,因为加的是实测记录):
- 删掉「扁平归档」回落分支。它建立在 `os.cp("*", layer)` 上,而
libxpkg 的 os.cp 取字面路径,遇到 glob 静默什么都不拷 —— 这个分支
只可能在下一行返回 false,是形状上的回落而非实际的回落。
- 文件自相矛盾:`-- DONE IN THE SHELL` 就压在一个首行写着
`-- NO SHELL` 的函数上面,前者是被取代的旧设计留下的。
- 把运行时归给了 xmake。不是 —— 是 libxpkg,两者的 API 面不同,
正是这个误认让人去读了错的 sandbox,得出 os.files 存在的结论。
Windows/macOS 只有编译链接覆盖:两边的后端在描述文件里是无条件的,
也没有同样廉价、无头 runner 能做的探针。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
承接 #245 的需求(该 PR 已回退到无净改动)。0.5.7 的
tray_bridge.c新增了走GDBus 的 freedesktop StatusNotifierItem 后端:设
EUI_TRAY_SNI之后只需要glib/gio,不再需要 GTK3 + libappindicator。此前 Linux 腿只能编
EUI_TRAY_HAS_BACKEND=0的桩。来源:全部在 mcpp + xlings 体系内,不碰宿主
.soxim:glib@2.80.0mcpp_generated/glib/libzlibmountlibselinuxlibffilibpcre2xim:zlib/util-linux/libselinux/libffi/pcre2实测消费者的闭包:
libz.so.1,对任何同时构建
compat.zlib的消费者就是第二个提供者 —— exe 里那份会在全部 88 个符号上获胜,glib 跑在一份它并非针对其链接的 zlib 上(mcpp#519)。最省的做法是不发
那个副本。
/usr/lib暂存 libmount/libselinux/libblkid,因为没有查。三处需要写下来的
-DEUI_TRAY_SNI=1对每个已发布版本都安全。 0.5.6 及更早的tray_bridge.c根本没有#elif defined(EUI_TRAY_SNI)这一支(对着 0.5.6 的tarball 核过),预处理器落回原来的
#else桩。mcpp段是版本无关的,所以这条必须核实而不是假设 —— 一个半生效的 define 会留下
EUI_TRAY_HAS_BACKEND=1而背后没有实现。-L与runtime.library_dirs不重复。 后者只变成-Wl,-rpath,是给加载器的,不是给链接器的。lld 恰好会搜 rpath 从而掩盖这一点,GNU ld
不会,
-lglib-2.0就会落空到宿主(或落空到没有)。*/的 wrap 层现在由 install() 负责归一。 本描述符每条源码 glob 都以*/开头,恰好吸收一层;没有 hook 时那一层来自 tarball 的形状,有了 hook 就得自己保证。GitHub 的包有一层、CN 镜像的可能没有,所以在 shell 里归一 ——
这个 xim 的 Lua 沙箱里既没有
os.files也没有path.basename,两次都是在整套依赖下载完之后才以
attempt to call a nil value现形。验证(本机,mcpp 2026.8.28.2)
索引三项 lint(
check_cross_package_refs/check_platform_version_parity/check_duplicate_versions)与mcpp xpkg parse全部通过。已知
同时用到
compat.zlib(经 libpng)的消费者会收到 mcpp#519 的「一个库两个提供者」警告。这是真的:静态 zlib 与 gio 加载的
libz.so.1并存,exe 那份获胜。根治要等
compat.zlib能声明soname = "libz.so.1"—— 需要索引latest的mcpp 下限跨过 2026.8.28.2(mcpp#519 §11.3 的发布顺序)。