CI & Build / Build now, or wait for Android? (push) Successful in 2s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 3s
CI & Build / Web typecheck and unit tests (push) Successful in 10s
CI & Build / Python lint (push) Successful in 1s
Android / Build, or is the channel already serving this? (push) Successful in 3s
Android / Core and FFI clippy and tests (push) Skipped
Android / Kotlin + Rust (APK) (push) Skipped
Android / Build the server image (push) Skipped
CI & Build / Python tests (push) Successful in 13s
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Successful in 1m45s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 1m56s
Desktop (Tauri) / Update manifest (push) Successful in 4s
CI & Build / integration (push) Successful in 1m31s
CI & Build / Build & push image (push) Successful in 14s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 2m59s
appimagetool's continuous build from 2026-10-29 rejects a tree that not every user can read and run, which failed the desktop Linux lane. Extraction keeps the build's restrictive modes (0700 directories, a 0770 AppRun.wrapped), and an AppImage runs as whichever user launches it, so the modes are corrected rather than the check skipped. Issue #6712. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
124 lines
4.9 KiB
Bash
Executable File
124 lines
4.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# De-bundle host-coupled graphics/display libraries from the built Tauri AppImage.
|
|
#
|
|
# WHY: Tauri's AppImage bundles the BUILD host's libEGL/libGL/libdrm/libgbm/
|
|
# libwayland-* into usr/lib. On many end-user systems (Arch/CachyOS, NVIDIA,
|
|
# Wayland) those bundled copies clash with the running kernel driver + Mesa and
|
|
# abort with "Could not create default EGL display: EGL_BAD_PARAMETER" -> a black
|
|
# window. They load before any renderer choice, so the runtime env
|
|
# fallbacks (WEBKIT_DISABLE_DMABUF_RENDERER etc.) cannot rescue it. Per the
|
|
# AppImage excludelist these libraries MUST come from the host. We strip exactly
|
|
# that graphics/display subset -- keeping webkit/gtk/javascriptcore bundled for
|
|
# portability -- so the dynamic loader falls through to the system copies (the
|
|
# AppRun keeps usr/lib first on LD_LIBRARY_PATH, then system paths).
|
|
#
|
|
# CI-only post-build step: extract -> remove libs -> repackage, overwriting the
|
|
# original AppImage in place so the desktop.yml artifact glob emits the
|
|
# de-bundled one.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
BUNDLE_DIR="$REPO_ROOT/target/release/bundle/appimage"
|
|
|
|
# appimagetool is published only under the rolling "continuous" tag (the project
|
|
# cuts no semver releases), so this URL is the pinned distribution channel.
|
|
# Preferred source is Tauri's own already-downloaded copy (see below); this is
|
|
# the network fallback.
|
|
APPIMAGETOOL_URL="https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
|
|
|
# Graphics/display libraries that must come from the host, per the AppImage
|
|
# excludelist (github.com/AppImage/pkg2appimage/blob/master/excludelist), plus
|
|
# the libwayland-* family that slips in through the GTK/WebKit dependency chain.
|
|
# Globs (.so*) catch every versioned variant. Only the GPU/driver stack is
|
|
# stripped; webkit/gtk stay bundled.
|
|
REMOVE_GLOBS=(
|
|
'libGL.so*' 'libEGL.so*' 'libGLdispatch.so*' 'libGLX.so*' 'libOpenGL.so*'
|
|
'libglapi.so*' 'libgbm.so*' 'libdrm.so*'
|
|
'libxcb.so*' 'libxcb-dri2.so*' 'libxcb-dri3.so*'
|
|
'libX11.so*' 'libX11-xcb.so*'
|
|
'libwayland-client.so*' 'libwayland-cursor.so*'
|
|
'libwayland-egl.so*' 'libwayland-server.so*'
|
|
)
|
|
|
|
echo "==> Locating built AppImage under $BUNDLE_DIR"
|
|
shopt -s nullglob
|
|
appimages=("$BUNDLE_DIR"/*.AppImage)
|
|
if [ ${#appimages[@]} -eq 0 ]; then
|
|
echo "ERROR: no .AppImage in $BUNDLE_DIR (did the tauri build run?)" >&2
|
|
exit 1
|
|
fi
|
|
APPIMAGE="${appimages[0]}"
|
|
echo " $APPIMAGE"
|
|
|
|
WORK="$(mktemp -d)"
|
|
trap 'rm -rf "$WORK"' EXIT
|
|
|
|
echo "==> Extracting AppImage (FUSE-free)"
|
|
cp "$APPIMAGE" "$WORK/app.AppImage"
|
|
chmod +x "$WORK/app.AppImage"
|
|
(cd "$WORK" && ./app.AppImage --appimage-extract >/dev/null)
|
|
LIBDIR="$WORK/squashfs-root/usr/lib"
|
|
[ -d "$LIBDIR" ] || {
|
|
echo "ERROR: no usr/lib in the extracted AppImage" >&2
|
|
exit 1
|
|
}
|
|
|
|
echo "==> Removing host-coupled graphics/display libraries"
|
|
before=$(find "$LIBDIR" -maxdepth 1 -type f -name '*.so*' | wc -l)
|
|
removed=0
|
|
for pat in "${REMOVE_GLOBS[@]}"; do
|
|
for f in "$LIBDIR"/$pat; do
|
|
echo " - $(basename "$f")"
|
|
rm -f "$f"
|
|
removed=$((removed + 1))
|
|
done
|
|
done
|
|
if [ -d "$LIBDIR/dri" ]; then
|
|
n=$(find "$LIBDIR/dri" -type f | wc -l)
|
|
echo " - dri/ (${n} Mesa GPU drivers)"
|
|
rm -rf "$LIBDIR/dri"
|
|
removed=$((removed + 1))
|
|
fi
|
|
after=$(find "$LIBDIR" -maxdepth 1 -type f -name '*.so*' | wc -l)
|
|
echo " removed ${removed} entries (usr/lib .so files: ${before} -> ${after})"
|
|
if [ "$removed" -eq 0 ]; then
|
|
echo "WARNING: nothing removed -- excludelist libs were not bundled here." >&2
|
|
fi
|
|
|
|
echo "==> Locating appimagetool"
|
|
# Prefer the copy Tauri already downloaded during the build (no network, and
|
|
# version-matched to the toolchain that produced the AppImage).
|
|
APPIMAGETOOL="$(find "$REPO_ROOT/target" -name 'appimagetool-*.AppImage' -type f 2>/dev/null | head -n1 || true)"
|
|
if [ -z "${APPIMAGETOOL:-}" ]; then
|
|
echo " not cached by Tauri; downloading from continuous channel"
|
|
APPIMAGETOOL="$WORK/appimagetool"
|
|
if command -v curl >/dev/null 2>&1; then
|
|
curl -fsSL -o "$APPIMAGETOOL" "$APPIMAGETOOL_URL"
|
|
elif command -v wget >/dev/null 2>&1; then
|
|
wget -qO "$APPIMAGETOOL" "$APPIMAGETOOL_URL"
|
|
else
|
|
echo "ERROR: need curl or wget to fetch appimagetool" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
echo " reusing Tauri's copy: $APPIMAGETOOL"
|
|
fi
|
|
chmod +x "$APPIMAGETOOL"
|
|
|
|
echo "==> Repackaging AppImage (overwriting original)"
|
|
rm -f "$APPIMAGE"
|
|
# appimagetool refuses a tree it can't be sure everyone can read and run: the
|
|
# AppImage runs as whichever user launches it, and extraction keeps the build's
|
|
# restrictive modes.
|
|
chmod -R a+rX "$WORK/squashfs-root"
|
|
chmod a+rx "$WORK/squashfs-root/AppRun"
|
|
# APPIMAGE_EXTRACT_AND_RUN lets appimagetool (itself an AppImage) run without
|
|
# FUSE in the CI container; ARCH is required by the embedded runtime.
|
|
export APPIMAGE_EXTRACT_AND_RUN=1
|
|
ARCH=x86_64 "$APPIMAGETOOL" "$WORK/squashfs-root" "$APPIMAGE"
|
|
|
|
echo "==> Done: de-bundled AppImage at"
|
|
ls -lh "$APPIMAGE"
|