Files
lutris/utils/appimage/Dockerfile
Daniel Johnson 053933a34c Add AppImage packaging proof-of-concept
Flathub's recent ban on AI-using projects (see #6724) puts Lutris's
Flatpak channel at risk, and Flatpak has always been an awkward fit
anyway: Lutris is fundamentally an unsandboxed game manager that needs
to call host xrandr, 7z, fuser, wine, flatpak, mount drives, and reach
the user's whole $HOME. AppImage gives us a single-file distribution
that does none of that sandboxing.

This adds `make appimage`, which builds a self-contained AppImage in
a Docker/Podman container based on Ubuntu 22.04 (glibc 2.35, Python
3.10, GTK3, WebKit2GTK 4.1). The pipeline:

  utils/appimage/build.sh          — host wrapper (docker or podman)
  utils/appimage/Dockerfile        — build env with all GI typelibs
  utils/appimage/build-in-container.sh
                                   — assembles AppDir via linuxdeploy
                                     + linuxdeploy-plugin-gtk, runs
                                     appimagetool
  utils/appimage/AppRun            — launcher; sources plugin-gtk hook,
                                     sets PYTHONPATH, execs bundled
                                     python3 with bin/lutris

Design notes worth flagging for review:

* The bundled Python is the build image's /usr/bin/python3.10 plus its
  stdlib, with tkinter/test/idle stripped.

* PyGObject and dbus-python are taken from apt (python3-gi, python3-dbus)
  rather than pip — both have switched to meson-python build backends
  that drag in a sizeable toolchain, and the prebuilt packages link
  against exactly the libgirepository/libdbus we already bundle from
  the same distro.

* AppRun deliberately does NOT export LD_LIBRARY_PATH. linuxdeploy
  already sets $ORIGIN-relative RPATH on every binary it deploys, and
  exporting LD_LIBRARY_PATH would leak into every host subprocess —
  which surfaced immediately when flatpak crashed loading our bundled
  libssl 3.0 instead of the host's 3.4. The build script patchelf's
  the RPATH on the manually-copied _gi.so / _dbus*.so so they still
  find the bundled libgirepository without the env override.

* PATH is left intact apart from prepending $APPDIR/usr/bin, so host
  tools (xrandr, 7z, wine, flatpak) still win — that's the whole
  point of choosing AppImage over Flatpak here.

Output is dist/Lutris-<version>-x86_64.AppImage at ~83 MB. Smoke-tested
end-to-end on Fedora 43 Nobara: boots GUI, GPU detection, DB load,
service auth, GTK theme, and host subprocess invocations all work.

Refs #6724.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 17:15:30 -04:00

76 lines
2.5 KiB
Docker

# Build environment for the Lutris AppImage proof-of-concept.
#
# Ubuntu 22.04 is chosen as a balance between glibc backward compatibility
# (glibc 2.35) and shipping Python 3.10 + GTK3 + WebKit2GTK 4.1 in the
# distro repos. If we promote this from PoC to a supported channel, we
# may want to drop to 20.04 (glibc 2.31) for wider portability.
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
ENV LC_ALL=C.UTF-8
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
wget \
file \
git \
desktop-file-utils \
gettext \
appstream \
libfuse2 \
fuse \
patchelf \
python3 \
python3-dev \
python3-pip \
python3-venv \
python3-setuptools \
python3-wheel \
pkg-config \
build-essential \
libcairo2-dev \
libgirepository1.0-dev \
libdbus-1-dev \
libsystemd-dev \
python3-gi \
python3-gi-cairo \
python3-dbus \
gir1.2-gtk-3.0 \
gir1.2-gdkpixbuf-2.0 \
gir1.2-pango-1.0 \
gir1.2-gnomedesktop-3.0 \
gir1.2-webkit2-4.1 \
gir1.2-notify-0.7 \
gir1.2-ayatanaappindicator3-0.1 \
libgtk-3-0 \
libgtk-3-bin \
libwebkit2gtk-4.1-0 \
libnotify4 \
libayatana-appindicator3-1 \
libgnome-desktop-3-19 \
librsvg2-common \
&& rm -rf /var/lib/apt/lists/*
# linuxdeploy + plugin-gtk handle library/typelib bundling and GTK env setup.
WORKDIR /opt/tools
RUN curl -fsSL -o linuxdeploy-x86_64.AppImage \
https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage \
&& curl -fsSL -o linuxdeploy-plugin-gtk.sh \
https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh \
&& curl -fsSL -o appimagetool-x86_64.AppImage \
https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage \
&& chmod +x linuxdeploy-x86_64.AppImage linuxdeploy-plugin-gtk.sh appimagetool-x86_64.AppImage
# linuxdeploy and appimagetool are AppImages; extract them so they run
# without FUSE (which isn't always usable inside containers).
RUN ./linuxdeploy-x86_64.AppImage --appimage-extract >/dev/null \
&& mv squashfs-root linuxdeploy \
&& ln -sf /opt/tools/linuxdeploy/AppRun /usr/local/bin/linuxdeploy \
&& ./appimagetool-x86_64.AppImage --appimage-extract >/dev/null \
&& mv squashfs-root appimagetool \
&& ln -sf /opt/tools/appimagetool/AppRun /usr/local/bin/appimagetool \
&& ln -sf /opt/tools/linuxdeploy-plugin-gtk.sh /usr/local/bin/linuxdeploy-plugin-gtk
WORKDIR /src