Linux: engines and apps build in an Ubuntu 26.04 container, glibc 2.43 at most (L1.4)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-11 11:00:48 -04:00
1 parent c2f16bc899
commit e3bfe8ade4
11 files changed
+110 -5

No files matched your search

+3
View File
@@ -133,6 +133,8 @@ tests/scripts/lo-patches.sh 补丁序列从中途接着打、再打一次为
tests/scripts/media-targets.sh 媒体播放接口在 Linux、Windows 目标可编译(缺目标时 SKIP)
tests/scripts/linux-idle.sh 真窗口 ElyTree:打开仓库后、Omarchy 换主题与改设置后,空闲时不读主题、设置,不跑 git status;照样跟随换主题、改设置与改文件,经内存映射的写入也跟随
tests/scripts/linux-backends.sh Linux 构建带 Wayland 与 X11;Hyprland 上 ElyTree 在两者上都映射出窗口、画出页面与起始页文字(截窗口量色,tesseract 读字)
packaging/linux/container.sh 命令 在 Ubuntu 26.04 镜像里运行(引擎、应用、打包;目标在 target/ubuntu)
tests/scripts/linux-glibc.sh Linux 的应用、worker 与引擎要求的 glibc 不高于 2.43
cargo test -p ely-show --test compose 切换半程帧经 Metal 取像素(主线程,仅 macOS)
tests/scripts/*.sh *.py 脚本测试(缺工具时报 SKIP)
packaging/macos/bundle.sh ely-doc debug 出 dist/ElyDoc.app(带图标、文档类型与该应用的引擎)
@@ -296,3 +298,4 @@ cargo run -p ely-doc 启动一个应用(ElyDoc 先 cargo build -p ely
- 2026-10-09(用户定):代码与发布从 GitHub 搬到自建的 Gitea(git.zacharyzhang.com;GitHub 账号被封,推送与发布都被拒)。公开仓库 `ZacharyZhang-NY/ElyOffice`(原样推上 main、缺陷清单分支与 v0.1.0、v0.1.1 标签),组件库为同站的 `ZacharyZhang-NY/Ely-GPUI-Components`(Cargo 的 git 依赖与 `fetch-references.sh` 随之改址,钉的提交不变)。v0.1.1 的六个 dmg 与两个源码包重新发在 Gitea 的 v0.1.1 发布里。官网的下载与源码链接指向 Gitea(`releases/latest` 会跳到最新发布页)。`.github/workflows` 删去(它们靠 GitHub 的 macOS 机器与 `gh`,发布改在本机以 `packaging/macos/release.sh` 构建、经 Gitea API 上传)。发布视频里写的地址已在源文件改为 Gitea,已发布的成片仍是旧地址,重渲染后才更新。上游项目(LibreOffice、MuPDF、git-lfs、tessdata 等)照旧从它们自己的 GitHub 地址取。
- 2026-10-11(用户报:Omarchy 上六个 AppImage 都打不开):`gpui-pre-platform` 对 `gpui-pre-linux` 关了默认特性,Wayland 与 X11 只经它自己的 `wayland`、`x11` 特性打开;工作区原只开 `font-kit`,Linux 上 gpui 退成无头平台,日志照写“window open”,合成器里从无窗口。工作区的 `gpui_platform` 加开两者;`tests/scripts/linux-backends.sh` 核对特性,在 Hyprland 上核对 Wayland 与 X11 两路都映射出窗口、截图里有均匀的深色页面,tesseract 读出起始页的 “Open a repository”(不交缓冲的窗口 Hyprland 不映射;不画字形时读不出)。
- 2026-10-11:Linux 的 inotify 把打开文件报成事件(notify 的 `Access`),macOS 的 FSEvents 不报;四处文件监视原把任何事件当作改动,重读本身又触发下一次:Omarchy 主题与通用设置在第一次改动后、ElyTree 打开仓库起(`git status` 读仓库),空闲时每 250 毫秒重读。四处都经 `ely_ui::watching::only_read` 略去读取(打开、读、只读关闭),写后关闭照算改动(经内存映射的写入只报 CLOSE_WRITE,不报 MODIFY);`tests/scripts/linux-idle.sh` 以 inotifywait 从外面数空闲时的读取与 git status 次数。
- 2026-10-11(用户定):Linux 的引擎、应用与包都在 `ubuntu:26.04` 容器里构建(`packaging/linux/Dockerfile`,钉摘要;glibc 2.43),不在本机(Arch 的 glibc 更新,建出的程序在 Ubuntu 上起不来)。`packaging/linux/container.sh` 以本人身份运行,Cargo 的目标与家目录另放 `target/ubuntu*`;`stage.sh` 取 `CARGO_TARGET_DIR`;Git 2.56 用自己的 `target/` 链接其 Rust 部分,`build-git.sh` 为它去掉该变量。`tests/scripts/linux-glibc.sh` 核对每个动态链接的 ELF(静态的 git-lfs 不算)。
+20
View File
@@ -0,0 +1,20 @@
# Linux builds on glibc 2.43 run on Ubuntu 26.04 onward.
FROM ubuntu:26.04@sha256:f144425ff09be612d6d9ad965196e9cdc23dae1f42110a8a11a3e9a8198759f7
ENV DEBIAN_FRONTEND=noninteractive
RUN sed -i 's/^Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources \
&& apt-get update \
&& apt-get build-dep -y libreoffice \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl ca-certificates git rsync patch file jq python3 nodejs npm rustup \
cmake ninja-build pkg-config nasm \
libssl-dev libjitterentropy3-dev libzstd-dev zlib1g-dev \
libxkbcommon-dev libxkbcommon-x11-dev libwayland-dev libx11-xcb-dev libxcb1-dev libfontconfig-dev \
&& rm -rf /var/lib/apt/lists/*
ENV RUSTUP_HOME=/opt/rustup
# As rust-toolchain.toml pins it.
RUN rustup toolchain install 1.96.0 --profile minimal --component rustfmt,clippy \
&& rustup default 1.96.0 \
&& chmod -R a+rX /opt/rustup
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Usage: container.sh <command...>; runs it in Ubuntu 26.04.
set -euo pipefail
root=$(cd "$(dirname "$0")/../.." && pwd)
[ $# -gt 0 ] || {
echo "container.sh: give a command, such as scripts/build-libreoffice.sh" >&2
exit 1
}
image=ely-office-linux-build
docker build -q -t "$image" "$root/packaging/linux" >/dev/null
# Own target and Cargo home: host builds need newer glibc.
mkdir -p "$root/target/ubuntu" "$root/target/ubuntu-cargo" "$root/target/ubuntu-home"
docker run --rm --user "$(id -u):$(id -g)" -v "$root:$root" -w "$root" \
-e HOME="$root/target/ubuntu-home" -e CARGO_HOME="$root/target/ubuntu-cargo" \
-e CARGO_TARGET_DIR="$root/target/ubuntu" -e ELY_RELEASE_TOKEN \
"$image" "$@"
+4 -3
View File
@@ -25,16 +25,17 @@ need() { # path, what to run
}
}
build() { cargo build --manifest-path "$root/Cargo.toml" --release "$@"; }
release=${CARGO_TARGET_DIR:-$root/target}/release
rm -rf "$out"
mkdir -p "$out"
build -p "$slug"
cp "$root/target/release/$slug$exe" "$out/"
cp "$release/$slug$exe" "$out/"
if uses ely-lok; then
lo=${ELY_LO_DIR:-$root/engines/lo-src/instdir}
need "$lo/program" scripts/build-libreoffice.sh
build -p ely-lok --bin ely-lok-worker
cp "$root/target/release/ely-lok-worker$exe" "$out/"
cp "$release/ely-lok-worker$exe" "$out/"
# The kernel in LibreOffice's layout, beside the app.
mkdir "$out/libreoffice"
cp -R "$lo/program" "$lo/share" "$lo/presets" "$out/libreoffice/"
@@ -56,7 +57,7 @@ if uses ely-pdf-engine; then
tessdata=${ELY_TESSDATA:-$root/engines/tessdata}
need "$tessdata/eng.traineddata" scripts/fetch-tessdata.sh
build -p ely-pdf-engine --bin ely-pdf-worker
cp "$root/target/release/ely-pdf-worker$exe" "$out/"
cp "$release/ely-pdf-worker$exe" "$out/"
mkdir "$out/tessdata"
cp "$tessdata"/{eng,chi_sim,chi_tra}.traineddata "$out/tessdata/"
fi
+1 -1
View File
@@ -38,6 +38,6 @@ if [ "$(cat "$out/.flags" 2>/dev/null)" != "$flags" ]; then
rm -rf "$out"
fi
# shellcheck disable=SC2086
make -C "$src" $flags -j"$jobs" install
env -u CARGO_TARGET_DIR make -C "$src" $flags -j"$jobs" install # Git's Rust uses its target/
echo "$flags" >"$out/.flags"
"$out/bin/git" --version
+1 -1
View File
@@ -204,7 +204,7 @@
- [x] L1.1 Linux 显示后端:`gpui_platform` 开 `wayland` 与 `x11`(原样无头,“window open”而合成器里没有窗口);Omarchy(Hyprland)上 ElyTree 在 Wayland 与 X11 上画出窗口(其余五个要引擎,随 L1.6 实测);`tests/scripts/linux-backends.sh` — R1 锁文件、目标目录、未证明交帧;R2 产物路径、字形未核;R3 语言、OCR 错误被吞;R4 PASS
- [x] L1.2 Linux 上的文件监视把读取当作改动(inotify 报打开,FSEvents 不报):Omarchy 主题、通用设置在第一次改动后、ElyTree 打开仓库起,每次重读自己又触发下一次,空闲时每 250 毫秒读一遍;四处监视(主题、设置、ElyTree、ElyMark)经 `ely_ui::watching::only_read` 略去读取,写后关闭照算改动;`theme.name` 读不出不再吞掉;`tests/scripts/linux-idle.sh`(ElyMark 要 CEF,随 L1.6 实测) — R1 写后关闭也被略去、注释超长;R2 PASS
- [x] L1.3 设置的单测在 Linux 上失败(“a menu bar needs menus”):Linux 未设菜单时给空表而非 None,测试未像应用那样先设菜单;真窗口里 Ctrl+, 打开设置不崩(已实测) — R1 PASS
- [ ] L1.4 Linux 构建环境:`ubuntu:26.04` 容器里构建全部引擎与六个应用(glibc 不高于 2.43)
- [x] L1.4 Linux 构建环境:`ubuntu:26.04` 容器里构建全部引擎与六个应用(glibc 不高于 2.43);`packaging/linux/container.sh`、`tests/scripts/linux-glibc.sh` — R1 读不出当作静态、缺件照过、注释超长;R2 链接文件、读错;R3 链接目录;R4 PASS
- [ ] L1.5 Linux 包:deb、rpm、Arch(pkg.tar.zst)、AppImage 出自同一份分装,装到 `/opt/ely-office/<应用>`,带桌面项、图标与文件类型
- [ ] L1.6 本机出六个应用的四种包;Omarchy 上装 Arch 包与 AppImage 出窗口;deb、rpm 在各自发行版的容器里装上并冒烟
- [ ] L1.7 v0.1.3:删去旧 AppImage,上传新包;`ci.sh` 的 Linux 产出四种包;agents.md 与官网随之
+9
View File
@@ -0,0 +1,9 @@
FAIL
- tests/scripts/linux-glibc.sh:26 — A failed `readelf` command is treated as evidence that the ELF is static. With `readelf` forced to return 1, the existing outputs still exit 0 and report all 187 ELF files compliant (`.work/L1.4-r1-readelf-failure.log`). A missing tool or failed inspection therefore bypasses every glibc check. Check tool availability explicitly and propagate inspection errors; skip version analysis only after a successful inspection establishes that the binary is static.
- tests/scripts/linux-glibc.sh:19 — Required outputs only need to exist; non-ELF files are skipped at line 23, and line 32 requires just one ELF across all inputs. A compiled probe with eight text files in place of the applications/workers, empty LibreOffice and CEF directories, and one unrelated ELF under Git exits 0 (`.work/L1.4-r1-non-elf.log`). Validate each required application/worker as an ELF and require the actual engine binaries before scanning their versions.
- tests/scripts/linux-glibc.sh:31 — The `find` process substitution loses enumeration failures, allowing a partial scan to pass. With valid ELF inputs and an unreadable LibreOffice subdirectory containing another ELF, `find` reports permission denied, but the test exits 0 and declares the 11 accessible ELF files compliant (`.work/L1.4-r1-find-failure.log`). Check and propagate the enumeration status before reporting success.
- packaging/linux/container.sh:2 — Scoped comments violate the mandatory one-line, ten-word limit: this line has 12 words, line 12 has 11, packaging/linux/Dockerfile:1 has 12, and tests/scripts/linux-glibc.sh:2 has 11. scripts/build-git.sh:40 and :41 also form consecutive comment lines. The repository comment checker rejects the shell comments (`.work/L1.4-r1-comments.log`). Shorten the long comments and remove or separate the consecutive explanation and directive.
+7
View File
@@ -0,0 +1,7 @@
FAIL
- packaging/linux/container.sh:2 — The round 1 comment defect remains: this comment has eleven words, and scripts/build-git.sh:40–41 still has consecutive comment lines. Running tests/scripts/comments.py exits 1 and rejects both (`.work/L1.4-r2-comments.log`). Shorten the remaining long comment and remove or separate the consecutive comments.
- tests/scripts/linux-glibc.sh:28 — Required outputs may be symlinks, but `find -type f` excludes them from version inspection. A compiled application probe declaring GLIBC_2.99 fails as a regular file; replacing it with a symlink to the identical ELF makes the test exit 0 and report only ten compliant files (`.work/L1.4-r2-probes.log`). Inspect every required ELF regardless of symlinks and include referenced engine libraries in the scan.
- tests/scripts/linux-glibc.sh:32 — `is_elf` conflates failed reads with non-ELF content, so engine inspection errors still produce success. An additional LibreOffice library declaring GLIBC_2.99 correctly fails while readable; making that file unreadable prints `head: Permission denied` but exits 0 and declares the eleven other ELF files compliant (`.work/L1.4-r2-probes.log`). Propagate header-read failures and skip files only after successfully reading and identifying non-ELF content.
+3
View File
@@ -0,0 +1,3 @@
FAIL
- tests/scripts/linux-glibc.sh:28 — The scan checks symlinked files but never traverses symlinked directories, so required engines can still escape version inspection. In the probe, a regular LibreOffice `program` directory containing `libmergedlo.so` declaring GLIBC_2.99 correctly fails; replacing that directory with a symlink to the same contents exits 0 and reports ten compliant ELF files. A linked library subdirectory also hides an incompatible library (`.work/L1.4-r3-probes.log`). Follow engine directory links while propagating traversal errors, and ensure every required ELF receives version inspection regardless of its directory layout.
+1
View File
@@ -0,0 +1 @@
PASS
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
# Linux builds need glibc 2.43 at most, as Ubuntu 26.04.
set -euo pipefail
root=$(cd "$(dirname "$0")/../.." && pwd)
limit=2.43
fail() {
echo "FAIL: $*" >&2
exit 1
}
for tool in objdump readelf; do
command -v "$tool" >/dev/null || {
echo "SKIP: no $tool"
exit 0
}
done
release=$root/target/ubuntu/release
lo=$root/engines/lo-src/instdir/program
required=("$release"/ely-{doc,table,show,pdf,tree,mark,lok-worker,pdf-worker} "$lo/libmergedlo.so"
"$root/engines/git/bin/git" "$root/engines/cef/libcef.so")
for file in "${required[@]}"; do
[ -f "$file" ] || fail "no $file; build in packaging/linux/container.sh"
magic=$(head -c 4 "$file" | od -An -c | tr -d ' ') || fail "cannot read $file"
[ "$magic" = '177ELF' ] || fail "$file is not an ELF file"
done
list=$(mktemp)
trap 'rm -f "$list"' EXIT
find -L "$release"/ely-{doc,table,show,pdf,tree,mark,lok-worker,pdf-worker} "$lo" "$root/engines/git" \
"$root/engines/cef" -type f -print0 >"$list" || fail "cannot list every file"
checked=0
while IFS= read -r -d '' file; do
magic=$(head -c 4 "$file" | od -An -c | tr -d ' ') || fail "cannot read $file"
[ "$magic" = '177ELF' ] || continue
checked=$((checked + 1))
headers=$(readelf -lW "$file") || fail "readelf cannot read $file"
# Static binaries, like git-lfs, need no glibc.
grep -q ' DYNAMIC ' <<<"$headers" || continue
symbols=$(objdump -T "$file") || fail "objdump cannot read $file"
need=$(sed -n 's/.*GLIBC_\([0-9.]*\).*/\1/p' <<<"$symbols" | sort -V | tail -n 1)
[ -z "$need" ] && continue
[ "$(printf '%s\n%s\n' "$need" "$limit" | sort -V | tail -n 1)" = "$limit" ] ||
fail "${file#"$root"/} needs glibc $need, above $limit"
done <"$list"
echo "linux: $checked ELF files need glibc $limit at most"