The gamescope prune deleted the compositor and shipped only its launcher #355
@@ -31,11 +31,39 @@
|
||||
{
|
||||
lib,
|
||||
gamescope,
|
||||
fetchFromGitHub,
|
||||
python3,
|
||||
patchDir,
|
||||
manifestRewriter,
|
||||
}:
|
||||
let
|
||||
# PIN THE COMPOSITOR SOURCE, rather than patching whatever gamescope nixpkgs happens to carry.
|
||||
# Every other channel already ships this exact commit — packaging/gamescope/README.md,
|
||||
# punktfunk-gamescope.spec, the PKGBUILD and build-punktfunk-gamescope.sh — and nix was the
|
||||
# only one tracking nixpkgs' version and hoping ten patches still applied.
|
||||
#
|
||||
# They did not, and the failures were not academic (MEASURED 2026-08-19/20):
|
||||
# * nixpkgs shipped 3.16.24 and patch 0009's context did not exist there at all, so the
|
||||
# build died at patchPhase — every `services.punktfunk.host.enable = true` with it.
|
||||
# * bumping the lock to 3.16.25 fixed that, then `--version` printed NOTHING: upstream's
|
||||
# `gamescope::PrintVersion()` landed AFTER the 3.16.25 tag. The host reads that banner to
|
||||
# decide a session's bit depth and cursor compositing BEFORE the virtual display exists,
|
||||
# so a silent banner means a silent fall back to SDR — the exact failure every guard in
|
||||
# this file is written to prevent.
|
||||
# Both are the same bug: nixpkgs' gamescope is older than the tree these patches target.
|
||||
# Pinning makes the nix package agree with every other channel byte for byte.
|
||||
#
|
||||
# Bumping this: move the rev, then `nix-prefetch-git --url https://github.com/ValveSoftware/gamescope
|
||||
# --rev <new> --fetch-submodules` for the hash, and keep packaging/gamescope/README.md in step.
|
||||
pfRev = "5fb8dce4a09d0a68d097b9faf9513782106bc843";
|
||||
pfVersion = "3.16.25-11-g5fb8dce";
|
||||
pfSrc = fetchFromGitHub {
|
||||
owner = "ValveSoftware";
|
||||
repo = "gamescope";
|
||||
rev = pfRev;
|
||||
fetchSubmodules = true;
|
||||
hash = "sha256-pGBiO+7LSdIc0k9K+SQnv/Og2DYD/cjvOImxIl91L2A=";
|
||||
};
|
||||
# As of nixos-unstable (checked 2026-07-28) `gamescope` IS the buildable derivation — pname
|
||||
# "gamescope", version 3.16.25, carrying `src`/`patches`/`mesonFlags`. Revisions that wrap it
|
||||
# (to wire the WSI layer + capabilities) expose the build as `.unwrapped`, so prefer that where
|
||||
@@ -76,6 +104,8 @@ let
|
||||
in
|
||||
unwrapped.overrideAttrs (old: {
|
||||
pname = "punktfunk-gamescope";
|
||||
version = pfVersion;
|
||||
src = pfSrc;
|
||||
|
||||
# Read the patch DIRECTORY rather than naming files: `builtins.attrNames` sorts
|
||||
# lexicographically, which for `000N-` prefixes is exactly the apply order, and a patch added or
|
||||
@@ -96,7 +126,19 @@ unwrapped.overrideAttrs (old: {
|
||||
substituteInPlace src/meson.build \
|
||||
--replace-fail \
|
||||
"vcs_tag = run_command(vcs_tag_cmd, check: false).stdout().strip()" \
|
||||
"vcs_tag = '${old.version}'"
|
||||
"vcs_tag = '${pfVersion}'"
|
||||
|
||||
# Source-level gate, the same one packaging/gamescope/build-punktfunk-gamescope.sh applies.
|
||||
# Splits a missing marker into its two possible stages: fire HERE and patch 0005 or the
|
||||
# substitution above lost it; pass here and fail the ELF check later, and it was lost in
|
||||
# meson configuration or compilation instead. Without this the two are indistinguishable,
|
||||
# at a full compositor build per guess.
|
||||
grep -q '+pfhdr' src/meson.build || {
|
||||
echo "punktfunk-gamescope: +pfhdr is not in src/meson.build after patching" >&2
|
||||
echo " --- version block as patched: ---" >&2
|
||||
sed -n '/^vcs_tag_cmd/,/^gamescope_version_conf/p' src/meson.build | sed 's/^/ | /' >&2
|
||||
exit 1
|
||||
}
|
||||
'';
|
||||
|
||||
# Ship the compositor, renamed, AND the WSI layer built beside it. Everything else nixpkgs
|
||||
@@ -134,7 +176,17 @@ unwrapped.overrideAttrs (old: {
|
||||
chmod -R u+w $out
|
||||
|
||||
find $out -mindepth 1 -maxdepth 1 ! -name bin -exec rm -rf {} +
|
||||
find $out/bin -mindepth 1 ! -name gamescope -delete
|
||||
# KEEP `.gamescope-wrapped`. nixpkgs wraps this package: makeWrapper leaves the real
|
||||
# compositor ELF at bin/.gamescope-wrapped and installs a small launcher at bin/gamescope
|
||||
# that sets PATH (xwininfo) before exec'ing it. A prune that keeps only `gamescope` deletes
|
||||
# the compositor and ships the launcher alone — MEASURED 2026-08-20 (run 19622): $out/bin
|
||||
# held a single 16 KB file, `--version` printed nothing because the launcher exec'd a path
|
||||
# that no longer existed, and no +pfhdr marker was present because a wrapper carries no
|
||||
# version string. Every symptom chased for three builds came from this one line.
|
||||
#
|
||||
# The launcher references its target by ABSOLUTE path, so renaming the launcher is safe
|
||||
# while the target keeps its name.
|
||||
find $out/bin -mindepth 1 ! -name gamescope ! -name '.gamescope-wrapped' -delete
|
||||
mv $out/bin/gamescope $out/bin/punktfunk-gamescope
|
||||
|
||||
install -Dm0755 "$TMPDIR/pf-layer.so" \
|
||||
@@ -147,8 +199,38 @@ unwrapped.overrideAttrs (old: {
|
||||
doInstallCheck = true;
|
||||
installCheckPhase = ''
|
||||
runHook preInstallCheck
|
||||
$out/bin/punktfunk-gamescope --version 2>&1 | grep -q '+pfhdr' \
|
||||
|| { echo "punktfunk-gamescope: the +pfhdr marker is missing — the patches did not take"; exit 1; }
|
||||
# Assert the marker is compiled INTO the shipped binary, rather than running it.
|
||||
#
|
||||
# Running it does not work here and never did: `--version` produced EMPTY output under the
|
||||
# build sandbox on BOTH nixpkgs' 3.16.25 and the pinned 5fb8dce4 (MEASURED 2026-08-19/20,
|
||||
# runs 19551 / 19573 / 19594). That is a property of the sandbox, not a defect in the binary:
|
||||
# gamescope calls PrintVersion() before the getopt loop (src/main.cpp:721 at the pinned rev),
|
||||
# so `gamescope --version` DOES print the banner on a real system — which is what the host's
|
||||
# capability probe reads.
|
||||
#
|
||||
# packaging/gamescope/build-punktfunk-gamescope.sh makes the same call, asserting on
|
||||
# src/meson.build. Grepping the installed ELF is strictly stronger: the version string reaches
|
||||
# .rodata through GamescopeVersion.h's k_szGamescopeVersion, so this proves the marker survived
|
||||
# patching, meson configuration AND compilation into the artifact we actually ship, and it
|
||||
# cannot be defeated by the binary being unable to start.
|
||||
# Grep the WRAPPED ELF: bin/punktfunk-gamescope is nixpkgs' launcher and carries no version
|
||||
# string at all, so asserting on it would pass only by accident. Fall back to the launcher
|
||||
# for a future nixpkgs that stops wrapping.
|
||||
gsElf=$out/bin/.gamescope-wrapped
|
||||
[ -f "$gsElf" ] || gsElf=$out/bin/punktfunk-gamescope
|
||||
grep -aq '+pfhdr' "$gsElf" || {
|
||||
echo "punktfunk-gamescope: the +pfhdr marker is not in the installed binary." >&2
|
||||
echo " src/meson.build carried it (asserted in postPatch), so it was lost between" >&2
|
||||
echo " meson configuration and the linked artifact. Evidence:" >&2
|
||||
echo " --- $out/bin ---" >&2
|
||||
ls -l $out/bin 2>&1 | sed 's/^/ | /' >&2
|
||||
echo " --- anything under $out mentioning pfhdr ---" >&2
|
||||
grep -ral 'pfhdr' $out 2>/dev/null | sed 's/^/ | /' >&2 || echo " | (nothing)" >&2
|
||||
echo " --- version-ish strings in the binary ---" >&2
|
||||
grep -aoE '[0-9]+\.[0-9]+\.[0-9]+[^ ]*' "$gsElf" 2>/dev/null \
|
||||
| sort -u | head -5 | sed 's/^/ | /' >&2 || true
|
||||
exit 1
|
||||
}
|
||||
# The manifest must name a library this derivation actually installed. A manifest pointing at a
|
||||
# path that does not exist is the worst shape of this bug: the loader reads it, finds nothing,
|
||||
# and carries on silently, so the box looks healthy and every game renders SDR.
|
||||
|
||||
Reference in New Issue
Block a user