Files
wehub-resource-sync 3e779be6f3
CI / lint (push) Failing after 13m4s
CI / test (3.11, ubuntu-latest) (push) Failing after 2m4s
CI / test (3.13, ubuntu-latest) (push) Successful in 13m30s
CI / test (3.14, ubuntu-latest) (push) Successful in 17m21s
CI / test (3.12, ubuntu-latest) (push) Successful in 17m55s
CI / discover-apps-ps (push) Successful in 1m56s
CI / test (3.9, ubuntu-latest) (push) Successful in 13m17s
CI / test (3.10, ubuntu-latest) (push) Successful in 26m21s
CI / audit (push) Successful in 13m38s
Deploy site / deploy (push) Has been cancelled
CI / test (3.14, ubuntu-24.04-arm) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:37 +08:00

169 lines
5.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Stage system-level FreeRDP 3+ binaries into an existing python-
# appimage AppDir so the resulting AppImage runs on hosts that do not
# have a FreeRDP 3 client installed.
#
# Thin AppImage (0.6.0 item A): the container stack (podman /
# podman-compose / conmon / crun / netavark / aardvark-dns / pasta /
# passt / slirp4netns / fuse-overlayfs) is INTENTIONALLY NOT bundled.
# Rootless podman fundamentally needs host systemd / subuid integration
# that an AppImage cannot carry, and bundling it caused #357 (Ubuntu
# 26.04 -- bundled podman-compose shadowed the host's working stack)
# and #363 (Fedora Bluefin -- LD_LIBRARY_PATH prepend poisoned host
# systemd-run / aardvark-dns with bundled libcrypto). The Thin AppImage
# requires the user to install podman / docker / libvirt from their
# distro package manager (same model as install.sh). FreeRDP stays
# bundled because it is a leaf binary that does not spawn host helpers.
#
# Caveats (FreeRDP-only):
#
# - libX11 / libXrandr / libxkbcommon / libGL / libwayland-client stay
# on the host so xfreerdp3 integrates with the user's actual X /
# Wayland session (RAIL would break otherwise).
# - glibc + libdl / libpthread / libc / libm / libresolv / libnsl /
# libcrypt + ld-linux likewise stay on the host. Bundling glibc into
# an AppImage is a well-known footgun; the runner-side Fedora glibc
# would conflict with the user-side glibc on every reasonable distro.
#
# Usage:
# bundle-system-bins.sh <AppDir>
#
# Must be invoked from a Fedora 41+ environment that already has the
# packages below installed via dnf. See appimage-publish.yml workflow
# for the CI variant.
set -euo pipefail
APPDIR="${1:?usage: $0 <AppDir>}"
if [ ! -d "$APPDIR" ]; then
echo "[bundle] AppDir not found: $APPDIR" >&2
exit 1
fi
mkdir -p "$APPDIR/usr/bin" "$APPDIR/usr/lib"
# Binaries to bundle. Names match the Fedora package layout; the
# script tolerates missing entries so it can be re-used on newer
# distros where the FreeRDP 3 binary naming shifts (xfreerdp /
# xfreerdp3 / wlfreerdp / sdl-freerdp).
#
# Thin AppImage: only FreeRDP 3 client binaries here. The container
# stack (podman / podman-compose / conmon / crun / netavark /
# slirp4netns / pasta / passt) is intentionally NOT bundled -- see the
# header comment for the root-cause rationale (#357 / #363).
BINARIES=(
xfreerdp3
xfreerdp
wlfreerdp3
wlfreerdp
sdl-freerdp3
sdl-freerdp
)
echo "[bundle] Copying binaries into $APPDIR/usr/bin/ ..."
for bin in "${BINARIES[@]}"; do
for path in "/usr/bin/$bin" "/usr/libexec/podman/$bin" "/usr/libexec/$bin"; do
if [ -f "$path" ]; then
cp -L "$path" "$APPDIR/usr/bin/"
echo " + $bin (from $path)"
break
fi
done
done
# Defensive sweep: if the FreeRDP package shipped any /usr/bin/*freerdp*
# binary we didn't enumerate, grab it. Fedora package naming for the
# FreeRDP 3 client has changed across releases (xfreerdp / xfreerdp3 /
# freerdp / sdl-freerdp + arch suffix); this catches whichever variant
# is present in the install.
echo "[bundle] Defensive freerdp glob:"
for path in /usr/bin/*freerdp* /usr/libexec/*freerdp*; do
if [ -f "$path" ]; then
base="$(basename "$path")"
if [ ! -f "$APPDIR/usr/bin/$base" ]; then
cp -L "$path" "$APPDIR/usr/bin/"
echo " + $base (from $path, defensive)"
fi
fi
done
# Library exclude list -- these MUST come from the host even on
# distro-agnostic AppImages. Bundling them is either a crash hazard
# (glibc family) or a desktop-integration hazard (X / Wayland /
# GL stack).
HOST_LIBS_REGEX='^/(usr/)?(lib(64)?(/[^/]+)?)/('\
'ld-linux[^/]*\.so[^/]*'\
'|libc\.so[^/]*'\
'|libm\.so[^/]*'\
'|libdl\.so[^/]*'\
'|libpthread\.so[^/]*'\
'|librt\.so[^/]*'\
'|libutil\.so[^/]*'\
'|libresolv\.so[^/]*'\
'|libnsl\.so[^/]*'\
'|libcrypt\.so[^/]*'\
'|libgcc_s\.so[^/]*'\
'|libstdc\+\+\.so[^/]*'\
'|libX11\.so[^/]*'\
'|libXrandr\.so[^/]*'\
'|libXi\.so[^/]*'\
'|libXcursor\.so[^/]*'\
'|libXfixes\.so[^/]*'\
'|libXrender\.so[^/]*'\
'|libXext\.so[^/]*'\
'|libxcb[^/]*\.so[^/]*'\
'|libxkbcommon[^/]*\.so[^/]*'\
'|libwayland-[^/]+\.so[^/]*'\
'|libGL\.so[^/]*'\
'|libGLX\.so[^/]*'\
'|libGLdispatch\.so[^/]*'\
'|libEGL\.so[^/]*'\
'|libdbus-1\.so[^/]*'\
')$'
echo "[bundle] Traversing ldd for transitive deps ..."
declare -A SEEN_LIBS=()
copy_lib() {
local lib="$1"
[ -f "$lib" ] || return 0
local base
base="$(basename "$lib")"
[ -z "${SEEN_LIBS[$base]:-}" ] || return 0
SEEN_LIBS[$base]=1
if [[ "$lib" =~ $HOST_LIBS_REGEX ]]; then
return 0
fi
cp -L "$lib" "$APPDIR/usr/lib/" 2>/dev/null || true
}
# ldd-traverse every bundled binary + every lib we copy in (transitive).
# Two-pass: collect, then copy, then re-traverse the copies until
# fixpoint (libs depending on other libs).
queue=()
for bin in "$APPDIR/usr/bin"/*; do
[ -f "$bin" ] || continue
queue+=("$bin")
done
while [ ${#queue[@]} -gt 0 ]; do
next_queue=()
for item in "${queue[@]}"; do
# ldd output: " libfoo.so.1 => /usr/lib/libfoo.so.1 (0x...)"
while read -r lib; do
[ -n "$lib" ] || continue
local_before_count=${#SEEN_LIBS[@]}
copy_lib "$lib"
# If we copied a new lib, queue it for transitive ldd
base="$(basename "$lib")"
if [ -f "$APPDIR/usr/lib/$base" ] && [ "${SEEN_LIBS[$base]:-}" = "1" ] && [ $local_before_count -lt ${#SEEN_LIBS[@]} ]; then
next_queue+=("$APPDIR/usr/lib/$base")
fi
done < <(ldd "$item" 2>/dev/null | grep -oE '/[^ ]+\.so[^ ]*')
done
queue=("${next_queue[@]}")
done
echo "[bundle] Bundled binaries:"
ls -1 "$APPDIR/usr/bin" | sed 's/^/ /'
echo "[bundle] Bundled libraries: $(ls "$APPDIR/usr/lib" | wc -l) files"
echo "[bundle] AppDir size: $(du -sh "$APPDIR" | cut -f1)"