41 Commits

Author SHA1 Message Date
Daniel Johnson
7550fe8731 appimage: install a modern setuptools + packaging in the build image
Noble's apt-shipped setuptools (68.1.2) predates PEP 639 SPDX string
license support, added in setuptools 77.0.0. Since pyproject.toml
declares `license = "GPL-3.0-or-later"` in that form, `setup.py
install` now aborts with

    configuration error: `project.license` must be valid exactly by
    one definition (2 matches found)

on every AppImage build.

Add three things to the existing pycairo pip install:

* `setuptools>=77` — the actual PEP 639 fix.
* `packaging>=24.2` — setuptools 77+ delegates SPDX normalization to
  `packaging.licenses`, which landed in packaging 24.2; Noble ships
  24.0, so the setuptools upgrade alone raises
  `ImportError: Cannot import packaging.licenses`.
* `--ignore-installed packaging` — Noble's `python3-packaging` is
  apt-managed with no RECORD file, so pip refuses to upgrade it in
  place ("Cannot uninstall packaging 24.0"). Ignoring the installed
  copy lets the newer packaging land alongside and shadow it on
  sys.path, without disturbing dpkg's view of the system.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-03 09:44:34 -04:00
Daniel Johnson
7f996c589e appimage: bundle adwaita-icon-theme so GtkSpinner renders on Fedora
Gtk 3's Adwaita CSS (compiled into libgtk-3 as a GResource) draws
GtkSpinner via -gtk-icontheme("process-working-symbolic"). Recent
adwaita-icon-theme releases (Fedora 43 ships 49) dropped that icon,
and linuxdeploy-plugin-gtk doesn't bundle icon themes — it only
extends XDG_DATA_DIRS to /usr/share so lookups fall through to the
host. On Fedora hosts the lookup fails: the spinner widget occupies
its CSS min-size but shows no visible content. Sidebar service
reloads and Preferences dialogs both looked frozen even though the
underlying operation was progressing.

Add adwaita-icon-theme to apt and copy /usr/share/icons/Adwaita into
$APPDIR/usr/share/icons/Adwaita. Since AppRun places $APPDIR/usr/share
before /usr/share in XDG_DATA_DIRS, GTK finds the bundled Noble copy
(which still has the icon) before the host's newer, trimmed one.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-01 20:31:12 -04:00
Daniel Johnson
116916c060 appimage: bump base image to Ubuntu 24.04 for newer WebKit2 4.1
Jammy's WebKit2GTK 4.1 point release (2.42) has a bug that kills the
WebKitWebProcess after one input event on the ZOOM Platform login
page; once the renderer dies the dialog freezes, stops repainting,
and accepts no further input. The dialog frame itself stays alive
so it wasn't obvious from the outside — the page just seemed to
hang. Non-AppImage runs weren't affected because they load the
host's newer WebKit.

Noble's 2.44+ point release fixes it. Bump the base image, update
apt package names where they've been renamed in the t64 transition
(libfuse2 → libfuse2t64, libgnome-desktop-3-19 →
libgnome-desktop-3-20t64), switch to apt's meson (Noble's is
current enough for meson-python), and pass --break-system-packages
to pip since Noble's system Python is PEP 668-managed.

Trade-off: glibc floor moves from 2.35 to 2.39, so the AppImage
stops running on hosts older than roughly 2024 distros (Ubuntu 22.04
and Debian 12 are too old). Documented in the Dockerfile header.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-01 19:49:12 -04:00
Daniel Johnson
dcb0f518e1 appimage: make WebKit login work on non-Ubuntu hosts
Three related bugs prevented the AppImage's WebKit-based service
login from working on Fedora / Arch / openSUSE — invisible on Ubuntu
because the host happens to satisfy the AppDir's missing pieces.

1. TLS backend not bundled. linuxdeploy-plugin-gtk copies libgio but
   not the GIO modules directory that holds glib-networking's
   libgiognutls.so. Without it GIO falls back to a compile-time libdir
   that doesn't exist off-Debian, and WebKit reports "TLS is not
   available" on the first HTTPS request. Copy the modules directory
   into $APPDIR/usr/lib/gio/modules with an $ORIGIN/../.. RPATH, add
   glib-networking to apt explicitly (it was pulled transitively but
   its modules weren't being copied), and export GIO_MODULE_DIR in
   AppRun.

2. WebKit shared libraries not bundled. libwebkit2gtk-4.1 and
   libjavascriptcoregtk-4.1 are loaded lazily via gi.repository when
   the user clicks a login button, so they never appear in any
   binary's NEEDED chain — linuxdeploy has no reason to bundle them.
   On non-Ubuntu hosts dlopen() falls through to the host copies with
   different symbols, e.g. `undefined symbol: webkit_web_context_new`.
   Pass both sonames to linuxdeploy explicitly.

3. WebKit helper processes not bundled and hardcoded path unreachable.
   WebKit2 4.1 forks WebKitNetworkProcess / WebKitWebProcess from a
   compile-time path baked into libwebkit2gtk-4.1.so.0
   (/usr/lib/x86_64-linux-gnu/webkit2gtk-4.1/). linuxdeploy bundles
   shared libraries, not auxiliary executables, and WEBKIT_EXEC_PATH
   was removed upstream — the path is only overridable by byte-patching
   the .so. Copy the webkit2gtk-4.1/ directory into the AppDir with
   $ORIGIN/.. RPATH on each helper, and byte-patch the hardcoded
   compile-time path inside libwebkit2gtk-4.1.so.0 to a writable
   /tmp/.lutris-appimage.dir/webkit2gtk-4.1 (same byte length). AppRun
   creates the symlink there before launch.

Also disable WebKit's bubblewrap sandbox
(WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1): bwrap opens a fresh
mount namespace that can't see the AppImage's FUSE mount at
/tmp/.mount_LutrisXXX, so any helper spawned inside it fails to reach
either the symlink target or the bundled libs. Lutris already runs
unsandboxed and spawns Wine, so an additional WebKit sandbox buys
negligible isolation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-01 19:32:36 -04:00
Daniel Johnson
d1a1a45d81 Stop the AppImage from forcing the Adwaita GTK theme
linuxdeploy-plugin-gtk's generated AppRun hook unconditionally sets
GTK_THEME to "Adwaita:light/dark" with a comment that "custom themes
are broken." The "broken" claim is from 2018 and is disputed in
upstream #39 (open since 2023-02 with no maintainer response); the
practical effect is that Lutris's AppImage looks Adwaita-ish on every
host regardless of the user's actual GTK theme — visibly out of place
on KDE, breaks any custom theming, and undoes whatever care the user
took with their desktop.

Patch the vendored hook generator so GTK_THEME is exported only when
the caller explicitly opted in via APPIMAGE_GTK_THEME. The default is
no override at all, letting the host's GTK_THEME (or its absence)
take effect, which is what every other GTK app on the system does.

The colour-scheme detection block above the override is now dead
weight — it existed solely to choose between Adwaita:dark and
Adwaita:light — so drop it.

Each modification is annotated "LUTRIS-MOD" in the vendored script,
matching the convention promised in its file header.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 13:29:57 -07:00
Daniel Johnson
2f6eec4189 Vendor linuxdeploy-plugin-gtk at a pinned commit
The plugin's upstream (linuxdeploy/linuxdeploy-plugin-gtk) has had no
commits since 2023-10-01 and feedback on #6726 flagged its dormancy
as a concern. Fetching the script from `master` on every build also
means the AppImage we ship is implicitly tied to whatever upstream
serves at build time, which is not reproducible and not auditable.

Vendor the script at commit 3b67a1d1 alongside its MIT licence. The
Dockerfile now COPYs the local copy into the build image instead of
curl-ing it from raw.githubusercontent.com, so the AppImage build is
reproducible from the repo alone and we have a place to apply local
patches if upstream stays dead (a separate follow-up commit drops the
plugin's hardcoded GTK theme override, which is the first such patch).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 13:29:57 -07:00
Daniel Johnson
b38c229b0d Stop leaking AppImage PYTHONPATH and PATH into host subprocesses
Previous AppRun exported PYTHONPATH pointing at the bundled stdlib and
prepended $APPDIR/usr/bin to PATH. Both leaked into every host
subprocess Lutris launches: a host umu-launcher invoked via its
`#!/usr/bin/env python3` shebang picked up the bundled Python 3.10
instead of the host's (no Xlib, no requests, no umu deps), and any
host Python that did get used inherited a PYTHONPATH pointing at our
3.10 stdlib (MAGIC mismatch in _sre on Fedora's 3.14).

Both exports were structurally unnecessary: AppRun already execs the
bundled interpreter by full path, so PATH does not need our bin
directory at the front, and switching setup.py to --install-layout=deb
makes Lutris findable via the bundled Python's default sys.path search
(dist-packages, what Debian-patched Python uses) without an env-var
hint.

Net effect: host umu-launcher, wine, xrandr, etc. now inherit a clean
PATH and no PYTHONPATH from the AppImage. The AppImage still requires
host Python 3.10+ for runners that themselves call Python (UMU is the
practical case); modern distros satisfy this by default.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 13:29:57 -07:00
Daniel Johnson
af9a32b110 Install PyGObject and dbus-python via pip instead of apt-copying
Replaces the manual `cp -a /usr/lib/python3/dist-packages/{gi,cairo,
dbus,_dbus_*}` block with `pip install --target` on PyGObject<3.50,
dbus-python, and pycairo, so every runtime Python dep in the AppImage
comes from a single source we can version-pin instead of being
silently tied to whatever Ubuntu 22.04's apt happens to ship.

This requires the build image to be able to compile both packages
from source — they ship as sdist only and have moved to meson-python
as their build backend — so the Dockerfile gains:

* meson via pip (>=0.63.3; apt's 0.61 is too old for meson-python)
* pycairo via pip in the build image, so PyGObject's meson can find
  its C headers (apt's python3-cairo ships no headers; the python3-
  cairo and python3-gi-cairo apt packages are no longer needed and
  have been dropped)
* ninja-build, libdbus-glib-1-dev — meson's runner and dbus-python's
  GLib mainloop bindings respectively

PyGObject is pinned <3.50 because 3.50 switched to the girepository-
2.0 ABI introduced in GLib 2.80, which Ubuntu 22.04 (GLib 2.72)
doesn't have. Apt's python3-gi 3.42 stays installed for build-time
use — setup.py imports lutris/__init__.py which calls
gi.require_version() at import time.

The patchelf RPATH step from the previous commit still applies: pip
installs land in dist-packages with no RPATH set, and linuxdeploy
only patches the copies it makes (in usr/lib), not the originals
where Python actually loads them from.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 13:29:57 -07:00
Daniel Johnson
4b7d73332c Strip Python's config-* from the AppImage's bundled stdlib
The usr/lib/python3.10/config-3.10-x86_64-linux-gnu/ directory holds
link-time-only artifacts (Makefile, libpython symlinks, and a
relocatable object file `python.o` that wraps Py_Main for embedding
Python in a custom executable). None of it is referenced when running
Python code, but the relocatable object made linuxdeploy emit a
spurious "patchelf: wrong ELF type" error on every build — patchelf
refuses to touch ET_REL files, linuxdeploy logs the failure and moves
on. Strip the directory along with the other developer-only chunks of
the stdlib already removed; saves a few MB and leaves the build log
free of distracting errors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 13:29:57 -07:00
Daniel Johnson
b88b3fe580 Default LUTRIS_VERSION from lutris/__init__.py in AppImage build
Previously `make appimage` produced Lutris-dev-x86_64.AppImage unless the
caller remembered to set LUTRIS_VERSION. On a tagged release commit that
yielded a misleadingly-named artifact. Have build.sh awk the version out
of lutris/__init__.py when no explicit value is provided; an env override
(e.g. LUTRIS_VERSION=0.5.23-rc1 for a release candidate) still wins.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 13:29:57 -07:00
Daniel Johnson
7ecd2ba969 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-30 13:29:57 -07:00
Mathieu Comandon
64f7e7aa9e Remove clean_configs script 2026-04-07 12:25:47 -07:00
Mathieu Comandon
cf3dd08f78 Remove issuelocker script 2026-04-06 11:54:51 -07:00
Daniel Johnson
697fa22d23 Detect string literals in | union annotations (crashes Python <3.14)
`"Foo" | None` fails at runtime on Python 3.10–3.13 because str doesn't
implement __or__. This only works on 3.14+ where PEP 749 defers annotation
evaluation. Add a check for this pattern alongside the existing conditional
import check so we catch it before it reaches users.

Ref: https://github.com/lutris/lutris/pull/6595

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 07:16:30 -04:00
Daniel Johnson
444385decc check_annotations: detect all conditional imports, not just TYPE_CHECKING
Broaden the checker to flag unquoted annotations referencing any import
under an `if` or `try` block, not only `TYPE_CHECKING` guards. This
catches cases like try/except optional imports (e.g. GnomeDesktop) that
can be None at runtime and crash on dotted attribute access in eager
annotations.

Also fix dotted access check to cover `from X import Y` names used as
`Y.Attr` in annotations, not just `import X` modules.

Motivated by #6552 (fixed in 7019866).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:30:35 -04:00
Daniel Johnson
ea743a236f Detect unquoted TYPE_CHECKING annotations that break on Python 3.10
Python 3.14 evaluates annotations lazily (PEP 649), so unquoted
annotations like `threading.Event` work even when `threading` is only
imported under TYPE_CHECKING. On Python 3.10, these annotations are
evaluated eagerly and raise NameError at import time.

Add utils/check_annotations.py, an AST-based checker that detects
unquoted annotations referencing TYPE_CHECKING-only imports, covering
both bare names (`HTTPResponse`) and dotted access (`threading.Event`)
— the latter being a gap in ruff's FA102 rule. Wire it into `make
annotation-compat`, `make check`, and a new CI job.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 16:12:14 -05:00
Eikeno
9dd0254caa formatting fix
ruff related

[ticket: X]
2025-03-22 18:39:43 +01:00
Eikeno
1d40df3cf2 modify refs from ~/.config/lutris to ~/.local/share/lutris
Also make utils/clean_config use CONFIG_DIR from settings.py instead of
hardcoded ref.

1 typo fix
2025-03-22 18:30:29 +01:00
Mathieu Comandon
3866cf21bd Make lutris panic, crash and burn on key errors on DB game object because this should not be inconsistent 2024-04-07 15:18:26 -07:00
Mathieu Comandon
00652b9653 Improve prefix cleaner 2024-04-07 00:43:01 -07:00
Rafał Mikrut
5378de4060 Add CI checks for every commit 2024-02-28 16:27:06 -08:00
Mathieu Comandon
35e29e657c Sync categories to website 2024-02-26 22:56:20 -08:00
Mathieu Comandon
daa3eea2e9 Add issuelocker script 2024-02-26 17:53:56 -08:00
Mathieu Comandon
24f8fee432 Re-enable imports sorting 2024-02-24 21:14:32 -08:00
Mathieu Comandon
38fbe9f05e Ruff reformat 2024-02-24 21:02:06 -08:00
Mathieu Comandon
0934b014fe Remove libstrangle option 2024-01-31 10:31:45 -08:00
Mathieu Comandon
9952c97b4c Add clean_configs script 2024-01-27 13:36:12 -08:00
Mathieu Comandon
fedc9d857e Improvements to clean_prefix script 2023-06-06 21:31:26 -07:00
Mathieu Comandon
0879886ffc Reformat cleanup_prefix 2023-02-05 20:12:25 -08:00
Mathieu Comandon
4d3d04d4ec Minor adjustment to prefix scanner 2023-01-31 15:57:05 -08:00
Mathieu Comandon
40cd119aea Prefix scanning implementation 2023-01-31 13:21:40 -08:00
Daniel Johnson
77d00fefdc Move extract_icon to a more appropriate directory
./utils contains stand alone utility scripts; utility routines used
by wine seem to be in lutris/util/wine, so lets move this there.

I am hoping this will address issue #4529
2022-09-28 03:55:15 -04:00
Mathieu Comandon
5ee931679e Handle pefile not being installed 2022-09-26 20:26:56 -07:00
Fedi Takeli
f69a04b043 formatting 2022-09-26 20:16:42 -07:00
Fedi Takeli
363e5cba8e init - extract_icon 2022-09-26 20:16:42 -07:00
Maximiliano Sandoval R
f52a7308bf meson: Add post install scrip
Makes sure the icons and desktop file are installed
2022-04-11 14:09:21 -07:00
Alexander Ravenheart
f5e8e007b3 - Replaced pipenv with poetry
- Updated min version check in setup.py to Python 3.6
- Updated isort config file and calls to align with v5.x
- Added init-hook for gi imports in .pylintrc to avoid invalid no-member issues
- Makefile: added lock, show-tree, bandit, black, mypy; updated test, cover, dev, isort, autopep8, check, isort-check, flake8, pylint; removed req, requirements;
- Updated .travis.yml to use poetry and make
- Added my email in AUTHORS
- Updated CONTRIBUTING.md
- Updated lint_python.yml to use poetry and make, reorganized instructions to have all install related steps first
- sorted imports: lutris, lutris-wrapper, cleanup_prefix.py and multiple files in tests dir
2021-11-17 21:17:43 -08:00
Christian Clauss
e5652a0210 Placate flake8 2021-08-02 13:44:18 -07:00
Mathieu Comandon
85d5a32b06 Add prototype script for wine prefix cleanup 2021-05-24 18:24:06 -07:00
Mathieu Comandon
7e000f5cfa Add scanners package 2021-05-10 23:16:15 -07:00
Mathieu Comandon
663f1e5b62 Add a proof of concept for Retroarch ROM import 2021-04-25 16:08:16 -07:00