ci / web (pull_request) Successful in 1m4s
ci / bun-nix (pull_request) Successful in 26s
apple / swift (pull_request) Successful in 1m40s
apple / screenshots (pull_request) Skipped
ci / rust (pull_request) Failing after 2m3s
ci / docs-site (pull_request) Successful in 1m41s
ci / rust-arm64 (pull_request) Successful in 2m44s
android / android (pull_request) Successful in 4m50s
nix / flake (pull_request) Failing after 16m12s
Until now the patched gamescope reached exactly four kinds of box: the Bazzite/Fedora-Atomic sysext, the Arch package, the SteamOS installer and a NixOS option. Everyone else was told to build gamescope from source. A traditional Fedora-family box — Nobara, plain Fedora, the HTPCs people actually stream from — therefore ran stock gamescope by default, which streams SDR, cursorless, and tells every game its display is 60 Hz. That is not a user error; there was no package to install. Both new packages REPACK the binary CI already builds rather than building gamescope again: it is a ~10-minute meson compile of an unrelated tree, cached per distro base because the binary is soname-coupled to it. The Arch PKGBUILD stays the one recipe that builds from source, because that is what makepkg is for. - packaging/gamescope/punktfunk-gamescope.spec + build-gamescope-rpm.sh. Version is derived from the binary's own banner (3.16.25.pfhdr4) — the only source that cannot drift from what is in the package. rpmbuild's automatic ELF Requires are what stop an f43 build installing on f44. - packaging/debian/build-gamescope-deb.sh, same shape, with dpkg-shlibdeps for Depends. - rpm.yml packages and publishes it beside the host RPMs; deb.yml gains a cached gamescope build (keyed on packaging/gamescope/** alone) and packages it into the existing publish loop. Both legs are best-effort, matching the sysext's existing rule: no binary, no package, and the host stays on its current SDR path. Neither package Provides or Conflicts with gamescope — it installs as /usr/bin/punktfunk-gamescope and only the sessions the host starts itself resolve it, so a box's own Game Mode keeps using the distro binary. Both refuse to package a binary without the +pfhdr marker. That marker is the host's entire capability probe, so a build that lost the patches would install fine and then silently stream SDR with no cursor. Verified: build-gamescope-deb.sh produces an installable .deb from a stand-in binary (correct version derived from the banner, 0755 tree, control fields) and exits 1 on an unmarked one. The .spec is not yet exercised — no rpm tooling on the box I had; CI's Fedora leg is its first run.
114 lines
5.2 KiB
Bash
Executable File
114 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Package an already-built punktfunk-gamescope binary as a .deb, for the Gitea apt registry.
|
|
#
|
|
# Counterpart to ../gamescope/build-gamescope-rpm.sh, and the same argument: the binary is a
|
|
# ~10-minute meson build of an unrelated tree that CI does once and caches, so this repacks rather
|
|
# than rebuilds. The Arch package (../gamescope/PKGBUILD) is the one recipe that builds from source,
|
|
# because that is what makepkg is for.
|
|
#
|
|
# Installed as /usr/bin/punktfunk-gamescope — it does NOT replace the distro's gamescope, and does
|
|
# not Provide/Conflict with it. Only the sessions punktfunk-host starts itself resolve this binary
|
|
# (PUNKTFUNK_GAMESCOPE_BIN > punktfunk-gamescope > gamescope).
|
|
#
|
|
# Usage:
|
|
# VERSION=3.16.25.pfhdr4~ci42.gdeadbee bash packaging/debian/build-gamescope-deb.sh \
|
|
# --binary gs-cache/punktfunk-gamescope [--arch amd64]
|
|
# Output: dist/punktfunk-gamescope_<version>_<arch>.deb
|
|
set -euo pipefail
|
|
|
|
BINARY=""
|
|
DEB_ARCH=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--binary) BINARY="${2:?--binary needs a path}"; shift 2 ;;
|
|
--arch) DEB_ARCH="${2:?--arch needs a value}"; shift 2 ;;
|
|
*) echo "unknown argument: $1" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
[ -n "$BINARY" ] || { echo "ERROR: --binary is required" >&2; exit 2; }
|
|
[ -x "$BINARY" ] || { echo "ERROR: $BINARY is not an executable file" >&2; exit 1; }
|
|
|
|
PKG="punktfunk-gamescope"
|
|
ROOTDIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
cd "$ROOTDIR"
|
|
|
|
DEB_ARCH="${DEB_ARCH:-$(dpkg --print-architecture)}"
|
|
|
|
# The marker is the host's whole capability probe: a binary that lost the patches installs fine and
|
|
# then silently streams SDR, cursorless, at a 60 Hz-advertising session. Refuse to package it.
|
|
BANNER="$("$BINARY" --version 2>&1 | head -1)"
|
|
case "$BANNER" in
|
|
*'+pfhdr'*) ;;
|
|
*) echo "ERROR: $BINARY has no +pfhdr marker — it is not a punktfunk gamescope build" >&2
|
|
echo " banner: $BANNER" >&2
|
|
exit 1 ;;
|
|
esac
|
|
|
|
# Derive the version from the binary when the caller did not pass one — it is the only source that
|
|
# cannot drift from what is actually in the package.
|
|
if [ -z "${VERSION:-}" ]; then
|
|
UPSTREAM="$(printf '%s\n' "$BANNER" | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1)"
|
|
PFHDR="$(printf '%s\n' "$BANNER" | grep -o '+pfhdr[0-9]\+' | head -1 | tr -d '+')"
|
|
[ -n "$UPSTREAM" ] || { echo "ERROR: no X.Y.Z version in banner: $BANNER" >&2; exit 1; }
|
|
VERSION="${UPSTREAM}.${PFHDR}"
|
|
fi
|
|
|
|
STAGE="$(mktemp -d)"
|
|
trap 'rm -rf "$STAGE"' EXIT
|
|
# mktemp gives 0700; the package root has to be world-readable or `dpkg-deb -c` shows the tree as
|
|
# root-only and some tooling refuses it.
|
|
chmod 0755 "$STAGE"
|
|
install -Dm0755 "$BINARY" "$STAGE/usr/bin/punktfunk-gamescope"
|
|
mkdir -p "$STAGE/DEBIAN"
|
|
|
|
# Shared-library dependencies straight from the binary's own ELF NEEDED entries. That is what makes
|
|
# the package honest about the Ubuntu release it was compiled on: gamescope links a broad set
|
|
# (wlroots, SDL, libliftoff, vulkan, xwayland's libs), and hand-listing them would rot.
|
|
DEPS=""
|
|
if command -v dpkg-shlibdeps >/dev/null 2>&1; then
|
|
# dpkg-shlibdeps insists on running from a package root with a debian/ dir.
|
|
mkdir -p "$STAGE/debian"
|
|
: > "$STAGE/debian/control"
|
|
( cd "$STAGE" && dpkg-shlibdeps -O --ignore-missing-info usr/bin/punktfunk-gamescope 2>/dev/null ) \
|
|
> "$STAGE/.shlibdeps" || true
|
|
DEPS="$(sed -n 's/^shlibs:Depends=//p' "$STAGE/.shlibdeps" | head -1)"
|
|
rm -rf "$STAGE/debian" "$STAGE/.shlibdeps"
|
|
fi
|
|
[ -n "$DEPS" ] || echo "WARNING: dpkg-shlibdeps produced no Depends — packaging without them" >&2
|
|
|
|
{
|
|
echo "Package: $PKG"
|
|
echo "Version: $VERSION"
|
|
echo "Architecture: $DEB_ARCH"
|
|
echo "Maintainer: unom <packages@unom.io>"
|
|
echo "Section: utils"
|
|
echo "Priority: optional"
|
|
[ -n "$DEPS" ] && echo "Depends: $DEPS"
|
|
# Not a hard dependency in either direction: the host works without this binary (SDR,
|
|
# host-composited cursor), and someone may want the binary for their own capture consumer.
|
|
echo "Recommends: punktfunk-host"
|
|
echo "Homepage: https://git.unom.io/unom/punktfunk"
|
|
echo "Description: gamescope with punktfunk's PipeWire capture patches"
|
|
echo " gamescope built from the upstream revision punktfunk pins, plus the patches in"
|
|
echo " packaging/gamescope/patches:"
|
|
echo " ."
|
|
echo " * 10-bit BT.2020/PQ capture formats, so an HDR game reaches a capture consumer as HDR"
|
|
echo " instead of pre-tonemapped SDR."
|
|
echo " * --pipewire-composite-cursor: the pointer is painted into the capture stream, so a"
|
|
echo " consumer with no cursor of its own gets one and the host stops blending one in."
|
|
echo " * A headless session advertises its real mode and refresh rates (and"
|
|
echo " --custom-refresh-rates), so Steam and games see the resolution and refresh the stream"
|
|
echo " actually runs at instead of an unnamed 60 Hz panel."
|
|
echo " * --pipewire-composite-external-overlay: the mangoapp performance overlay is painted"
|
|
echo " into the capture stream, so the fps/stats readout is visible remotely."
|
|
echo " ."
|
|
echo " Installed as /usr/bin/punktfunk-gamescope; your system gamescope is untouched."
|
|
} > "$STAGE/DEBIAN/control"
|
|
|
|
mkdir -p dist
|
|
OUT="dist/${PKG}_${VERSION}_${DEB_ARCH}.deb"
|
|
dpkg-deb --build --root-owner-group "$STAGE" "$OUT"
|
|
echo "==> wrote $OUT"
|
|
echo " banner: $BANNER"
|