From c5615cd7b1e2ac9117bd829b3f1bb0a5559a85de Mon Sep 17 00:00:00 2001 From: Joshua Tam <297250+joshuatam@users.noreply.github.com> Date: Mon, 2 Nov 2026 08:45:39 +0800 Subject: [PATCH] android: rebuild Xwayland instead of trusting an existing binary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit android/package-gamescope.sh absorbed the Xwayland payload behind an existence check: [ -x "$XW_DIR/build-android/hw/xwayland/Xwayland" ] || bash build-xwayland.sh so the binary was built only when it was missing. The daemon libraries staged a few dozen lines above get a strict check_fresh guard against their sources, but Xwayland got nothing: once a binary existed, a change to gamenative-xwayland source — hw/xwayland, Xext, the glamor path — packaged the previous build silently and the payload shipped a stale Xwayland. The tree was in exactly that state when this was written: Xext/shm.c and hw/xwayland/xwayland-glamor-gbm.c were newer than the 2026-10-22 Xwayland binary, and the old predicate would have copied it into the asset without a word. On device that shows up as a missing or wrong behaviour in the X server behind gamescope — an X extension the guest expects, a glamor/GBM fix that is simply not there — with nothing in the build log pointing at the binary. Build it always, the way the daemon libraries are built, and assert the result converged: bash "$XW_DIR/android/build-xwayland.sh" ninja -C "$XW_DIR/build-android" -n | grep -qx 'ninja: no work to do.' build-xwayland.sh is incremental (meson reconfigure, ninja relinks only what changed), so a current tree pays only its xkbcomp/xkeyboard-config tail: 8.9-9.5 s over three warm runs here. A stale tree pays a rebuild, which is the point. If the dry run still reports work, the script fails with the binary path instead of packaging it. The assertion is ninja's dry run rather than a find-based check_fresh because a source scan cannot answer the question for this tree: the xkbcomp tail rewrites android/deps/xkbcomp-build/config.h after the link, so a "source newer than the binary" test reports the tree stale on every run. ninja already knows every input, including that generated header, so "no work to do" is the honest statement that the binary matches its sources. Verified on a tree where the old predicate would have shipped the stale binary: the always-rebuild costs 8.9-9.5 s over three warm runs, and the dry run settles at "ninja: no work to do." --- android/package-gamescope.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/android/package-gamescope.sh b/android/package-gamescope.sh index 5b5b28b3f..07a697198 100755 --- a/android/package-gamescope.sh +++ b/android/package-gamescope.sh @@ -395,7 +395,21 @@ mkdir -p "$STAGE/share/hwdata" # runtime prefix files/gamescope — same as gamescope itself). Absorb its stage # into this package root so GameNative ships a single gamescope asset. XW_DIR="${GN_XWAYLAND_DIR:-$WS_DIR/gamenative-xwayland}" -[ -x "$XW_DIR/build-android/hw/xwayland/Xwayland" ] || bash "$XW_DIR/android/build-xwayland.sh" +XW_BIN="$XW_DIR/build-android/hw/xwayland/Xwayland" +# Rebuilt always, like the daemon libraries above and for the same reason: the +# binary comes out of a build directory, so an existing file says nothing about +# whether it is current, and a stale Xwayland is invisible in the payload — +# gamescope only finds out at run time. build-xwayland.sh is incremental (meson +# reconfigure, ninja relinks only what changed), so a current tree costs its +# xkbcomp/xkeyboard-config tail, seconds; a stale one costs a rebuild. The dry +# run is the assertion in place of a find pattern: ninja knows every input, +# including the generated config.h the xkb tail rewrites after the link, which +# a scan of this upstream tree would report as stale on every run. +bash "$XW_DIR/android/build-xwayland.sh" +if ! ninja -C "$XW_DIR/build-android" -n 2>/dev/null | grep -qx 'ninja: no work to do.'; then + echo "error: $XW_BIN is not current after build-xwayland.sh — ninja still has work" >&2 + exit 1 +fi bash "$XW_DIR/android/package-xwayland.sh" "$DATE" >/dev/null XW_TZST="$OUT_ASSETS/xwayland-gamenative-$DATE.tzst" [ -f "$XW_TZST" ] || { echo "error: xwayland payload $XW_TZST not produced" >&2; exit 1; }