Repository navigation
android: rebuild Xwayland instead of trusting an existing binary - #29
Merged
Merged
Conversation
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."
This was referenced Nov 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
android/package-gamescope.shabsorbed the Xwayland payload behind an existence check:So the binary was built only when it was missing. The daemon libraries staged a few dozen lines above it get a strict
check_freshguard against the sources they compile, but Xwayland got nothing: once a binary existed, any change to gamenative-xwayland source —hw/xwayland,Xext, the glamor/GBM path — packaged the previous build silently and the asset shipped a stale Xwayland.That is not hypothetical. The tree this was written on was in exactly that state:
Xext/shm.candhw/xwayland/xwayland-glamor-gbm.cwere newer than the 2026-10-22 Xwayland binary, and the old predicate would have copied that binary into the payload without a word. On device it presents as a missing or wrong behaviour in the X server behind gamescope — an X extension the guest expects, a glamor/GBM fix that simply is not there — with nothing in the build log pointing at the binary.Fix
Build it always, the way the daemon libraries above are built, and assert the result converged:
build-xwayland.shis incremental (meson reconfigure, ninja relinks only what changed), so a current tree pays only its xkbcomp/xkeyboard-config tail; a stale tree pays a rebuild, which is the point. If the dry run still reports work, the script fails naming the binary rather than packaging it.Why ninja's dry run and not a
check_freshsource scanA
find -newerscan cannot answer this question for this tree: the xkbcomp tail rewritesandroid/deps/xkbcomp-build/config.hafter the link, so "any source newer than the binary" is true on every run and the check would fail the build permanently. ninja already knows every input, including that generated header, soninja: no work to do.is the honest statement that the binary matches its sources.Measurement
On a current tree the always-rebuild costs 8.9–9.5 s over three warm runs, and the dry run settles at
ninja: no work to do.Touch nothing else: this is one file, and the patch train's dirty
src/tree is not part of the commit.