fix(appimage): keep ld-linux bundled + recurse exclude into nested dirs#16
Conversation
The exclude list introduced for glibc/NSS (PR tinyhumansai#15 and tauri-apps#1996's precedent) broke AppImage launch on every host in two ways that the original PRs' test plans didn't cover: 1. `ld-linux` was bundled in the exclude list under the "glibc family" rationale, but sharun *requires* a loader to be present in `$APPDIR/shared/lib/` to bootstrap the dynamic OpenHuman binary (whose INTERP is stripped during lib4bin processing). With it excluded, sharun aborts with "Interpreter not found!" before any chromium code runs. The loader is ABI-stable enough across glibc versions for the host-vs-bundle mix here to remain safe. 2. The exclusion sweep used `fs::read_dir` on top-level `shared/lib` only. lib4bin mirrors source paths when libraries are pulled in from nested locations (e.g. `shared/lib/snap/core20/<rev>/usr/lib/x86_64-linux-gnu/libc.so.6` when the build host has snap-managed apps like VS Code), so nested copies of `libc.so`, `libm.so`, etc. survived the sweep and broke `GLIBC_2.x` symbol lookups on the target host even though the intent was to defer to host glibc. Both reproduce on Ubuntu 26.04 GNOME-Wayland with the locally-built v0.53.49 AppImage. Without (1), launch dies at sharun bootstrap; with (1) but without (2), launch dies at `libm.so.6: version GLIBC_2.35 not found`. Both fixed by this change. Refs tinyhumansai/openhuman#2001, tinyhumansai/openhuman#2032, tinyhumansai#15
📝 WalkthroughWalkthroughThis PR refines the AppImage bundling cleanup in the Tauri CEF bundler. The change clarifies glibc family exclusion rules by explicitly removing ChangesAppImage AppDir library cleanup refinement
Possibly related PRs
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/tauri-bundler/src/bundle/linux/appimage/sharun_cef.rs (1)
246-270: 🏗️ Heavy liftAdd a regression test for this cleanup pass.
This block now depends on two subtle contracts:
ld-linux*must survive, while nestedlibc/libm/...copies under mirrored paths must be removed recursively. Since both failure modes already slipped past CI once, a small filesystem-level test here would make future changes much safer.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/tauri-bundler/src/bundle/linux/appimage/sharun_cef.rs` around lines 246 - 270, Add a filesystem-level regression test that constructs a temporary app_dir with the nested layout exercised by the cleanup loop in sharun_cef.rs (paths like shared/lib/snap/core20/<rev>/usr/lib/... containing libc.so.6, libm.so, etc.) plus a surviving ld-linux* entry (e.g., lib/ld-linux-x86-64.so.2), then invoke the cleanup pass (the code in sharun_cef.rs that iterates over &["shared/lib","shared/lib32","lib","lib32"] using walkdir and exclude_prefixes) and assert that the nested libc/libm copies are removed recursively while the ld-linux* file still exists and other non-excluded files are unchanged; include both regular files and symlinks in the setup to cover the file_type checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/tauri-bundler/src/bundle/linux/appimage/sharun_cef.rs`:
- Around line 246-270: Add a filesystem-level regression test that constructs a
temporary app_dir with the nested layout exercised by the cleanup loop in
sharun_cef.rs (paths like shared/lib/snap/core20/<rev>/usr/lib/... containing
libc.so.6, libm.so, etc.) plus a surviving ld-linux* entry (e.g.,
lib/ld-linux-x86-64.so.2), then invoke the cleanup pass (the code in
sharun_cef.rs that iterates over &["shared/lib","shared/lib32","lib","lib32"]
using walkdir and exclude_prefixes) and assert that the nested libc/libm copies
are removed recursively while the ld-linux* file still exists and other
non-excluded files are unchanged; include both regular files and symlinks in the
setup to cover the file_type checks.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: dc30ef95-0ae4-4cdd-8c6a-83639b67e8e8
📒 Files selected for processing (1)
crates/tauri-bundler/src/bundle/linux/appimage/sharun_cef.rs
Summary
ld-linuxfrom the AppImageexclude_prefixes— sharun needs the loader present inshared/lib/to bootstrap the dynamic binary; stripping it leaves every locally-built AppImage aborting withInterpreter not found!before any chromium code runs.walkdir) so nested copies oflibc.so/libm.sothat lib4bin pulls into mirrored snap paths likeshared/lib/snap/core20/<rev>/usr/lib/x86_64-linux-gnu/are also stripped.Problem
PR #15's exclude list (which extended PR tauri-apps#1996's glibc precedent to NSS/NSPR for tinyhumansai/openhuman#2001) had two side effects nobody verified end-to-end:
ld-linux. lib4bin stripsINTERPfrom the dynamic binary and expects sharun to provide a bundled loader; deleting the loader fromshared/lib/leaves sharun aborting withInterpreter not found!before any user-visible startup.fs::read_dironly enumerates top-level entries. On build hosts with snap-managed apps (VS Code, etc.), lib4bin mirrors source paths intoshared/lib/snap/..., so oldlibc.so.6survives the sweep and breaksGLIBC_2.xsymbol resolution on rolling/newer distros even though the intent was to defer to host glibc.Both reproduce on Ubuntu 26.04 GNOME-Wayland with a locally-built v0.53.49 AppImage. Test plan items in tinyhumansai/openhuman#2032 for "Run the resulting AppImage in archlinux:latest" and "Smoke-test on Ubuntu 22.04 / 24.04" were never checked off.
Solution
"ld-linux"fromexclude_prefixeswith an inline comment explaining why it must stay bundled. Loader ABI is stable enough that the host-vs-bundle mix here remains safe — this matches the pattern in every working CEF/Electron-style AppImage I checked.fs::read_dirwithwalkdir::WalkDir::new(&dir_path).follow_links(false)so the sweep recurses into all nested mirror paths. Also accept symlinks (lib4bin produces both regular files and symlinks).walkdiris already a tauri-bundler dep (no new dep added).Verification
Locally-built v0.53.49 AppImage on Ubuntu 26.04 GNOME-Wayland:
Interpreter not found!from sharun.ld-linux-x86-64.so.2is present inshared/lib/, sharun bootstraps, and nolibc-2.31survives in nestedshared/lib/snap/...dirs. The dynamic binary loads, reachesRunEvent::Ready, and runs.(Local manual repro because CI runs on
ubuntu-22.04which doesn't have snap-managed apps and so doesn't surface either regression.)Impact
Linux AppImage bundles only. Other targets unchanged. Resolves the launch regression silently introduced by #15 + tauri-apps#1996; required for tinyhumansai/openhuman#2001 to actually close end-to-end.
Related
Summary by CodeRabbit