From 0052a6ae30276858c091f4afc273689d62cc64a4 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Tue, 7 Jul 2026 23:41:10 +0200 Subject: [PATCH] fix(packaging): vulkan-headers build dep + ship punktfunk-session across desktop packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The re-architecture split the Linux client into two binaries (shell + Vulkan session streamer) and added the pf-ffvk crate, whose build.rs runs bindgen over FFmpeg's libavutil/hwcontext_vulkan.h (#include ). Two release regressions fell out of that on the desktop-package legs: 1. Missing build dep. The Arch build (archlinux:base-devel + its own pacman list) fatal-errored at `vulkan/vulkan.h file not found`. Add the Vulkan dev headers wherever the client compiles from a self-managed dep set: arch (PKGBUILD makedepends + arch.yml), rpm (spec BuildRequires + rpm.yml + fedora image), deb.yml (belt-and-suspenders; the rust-ci image already bakes libvulkan-dev), and the screenshots job. The flatpak builds offline against the GNOME SDK, so install Vulkan-Headers into /app as a pinned module and point pf-ffvk's bindgen at it via PF_FFVK_VULKAN_INCLUDE. 2. Only the shell shipped. arch/deb/rpm built and installed just punktfunk-client; the shell execs its sibling punktfunk-session for a connect, so desktop streaming would break exactly as Decky's did. Build and install BOTH binaries in all three, and declare the runtime Vulkan loader the session binary dlopens (vulkan-icd-loader / vulkan-loader / libvulkan1 — not a DT_NEEDED, so shlibdeps/auto-requires can't see it). Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/arch.yml | 2 +- .gitea/workflows/deb.yml | 9 ++++++-- .gitea/workflows/linux-client-screenshots.yml | 2 +- .gitea/workflows/rpm.yml | 4 +++- ci/fedora-rpm.Dockerfile | 2 ++ packaging/arch/PKGBUILD | 22 ++++++++++++++----- packaging/debian/build-client-deb.sh | 18 +++++++++++---- packaging/flatpak/io.unom.Punktfunk.yml | 20 +++++++++++++++++ packaging/rpm/punktfunk.spec | 16 ++++++++++++-- 9 files changed, 78 insertions(+), 17 deletions(-) diff --git a/.gitea/workflows/arch.yml b/.gitea/workflows/arch.yml index 6cff7953..65e692e4 100644 --- a/.gitea/workflows/arch.yml +++ b/.gitea/workflows/arch.yml @@ -42,7 +42,7 @@ jobs: - name: Install build + runtime-dev deps run: | pacman -Syu --noconfirm --needed \ - git nodejs rust clang cmake nasm pkgconf python \ + git nodejs rust clang cmake nasm pkgconf python vulkan-headers \ gtk4 libadwaita sdl3 ffmpeg pipewire wayland libxkbcommon opus libei \ mesa libglvnd unzip libarchive # bun builds the punktfunk-web console AND is vendored as its runtime (PF_WITH_WEB=1); diff --git a/.gitea/workflows/deb.yml b/.gitea/workflows/deb.yml index 865ab4ae..1cecf14d 100644 --- a/.gitea/workflows/deb.yml +++ b/.gitea/workflows/deb.yml @@ -60,8 +60,10 @@ jobs: run: | apt-get update # python3 is used by scripts/ci/gitea-release.sh for the stable-tag release attach. + # libvulkan-dev: /usr/include/vulkan/vulkan.h for the client's pf-ffvk bindgen + # (FFmpeg's hwcontext_vulkan.h includes it). apt-get install -y --no-install-recommends dpkg-dev python3 \ - libgtk-4-dev libadwaita-1-dev libsdl3-dev + libgtk-4-dev libadwaita-1-dev libsdl3-dev libvulkan-dev # Share ci.yml's cache keys so the release build reuses its registry + target artifacts. - name: Cache keys @@ -86,7 +88,10 @@ jobs: PUNKTFUNK_BUILD_VERSION: ${{ env.VERSION }} # stamped into the binary (build.rs) run: | git config --global --add safe.directory "$PWD" - cargo build --release -p punktfunk-host -p punktfunk-client-linux --locked + # punktfunk-client-session is the Vulkan/Skia streamer the shell execs for a connect — + # both client binaries must ship (build-client-deb.sh installs both). + cargo build --release --locked \ + -p punktfunk-host -p punktfunk-client-linux -p punktfunk-client-session - name: Build + smoke-boot web console (bun preset) # Gate the .deb on a real bun boot: the punktfunk-web .deb runs the Nitro `bun` preset diff --git a/.gitea/workflows/linux-client-screenshots.yml b/.gitea/workflows/linux-client-screenshots.yml index 8aec5c97..700926c0 100644 --- a/.gitea/workflows/linux-client-screenshots.yml +++ b/.gitea/workflows/linux-client-screenshots.yml @@ -30,7 +30,7 @@ jobs: run: | apt-get update apt-get install -y --no-install-recommends \ - libgtk-4-dev libadwaita-1-dev libsdl3-dev \ + libgtk-4-dev libadwaita-1-dev libsdl3-dev libvulkan-dev \ xvfb x11-utils imagemagick scrot \ libgl1-mesa-dri mesa-vulkan-drivers \ adwaita-icon-theme fonts-cantarell fonts-dejavu-core diff --git a/.gitea/workflows/rpm.yml b/.gitea/workflows/rpm.yml index 7ffe4414..2b22a883 100644 --- a/.gitea/workflows/rpm.yml +++ b/.gitea/workflows/rpm.yml @@ -54,7 +54,9 @@ jobs: - name: Prep run: | git config --global --add safe.directory "$PWD" - dnf -y install gtk4-devel libadwaita-devel SDL3-devel + # vulkan-headers: the client's pf-ffvk crate runs bindgen over FFmpeg's + # libavutil/hwcontext_vulkan.h (#include ). + dnf -y install gtk4-devel libadwaita-devel SDL3-devel vulkan-headers # sysext build (packaging/bazzite/build-sysext.sh): squashfs + SELinux labeling. dnf -y install squashfs-tools cpio libselinux-utils selinux-policy-targeted # bun builds the punktfunk-web console (--with web). Baked into the image; install it diff --git a/ci/fedora-rpm.Dockerfile b/ci/fedora-rpm.Dockerfile index 39c96ff3..b0d3be75 100644 --- a/ci/fedora-rpm.Dockerfile +++ b/ci/fedora-rpm.Dockerfile @@ -27,6 +27,8 @@ RUN dnf -y install \ mesa-libGL-devel mesa-libgbm-devel \ # punktfunk-client link deps (GTK4 shell + SDL3 gamepads) gtk4-devel libadwaita-devel SDL3-devel \ + # pf-ffvk bindgen over libavutil/hwcontext_vulkan.h needs + vulkan-headers \ && dnf clean all # bun — both the BUILD tool and the RUNTIME for the punktfunk-web console (`bun run build` -> the diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index d26cfc59..a794bd29 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -34,8 +34,9 @@ license=('MIT OR Apache-2.0') options=('!lto' '!debug') # All build deps for both crates (Arch runtime packages ship their own headers, so these cover -# build + link). aws-lc/ring need clang+cmake; nasm is for asm. -makedepends=('rust' 'cargo' 'clang' 'cmake' 'nasm' 'pkgconf' 'git' +# build + link). aws-lc/ring need clang+cmake; nasm is for asm. vulkan-headers: the client's +# pf-ffvk crate runs bindgen over FFmpeg's libavutil/hwcontext_vulkan.h (#include ). +makedepends=('rust' 'cargo' 'clang' 'cmake' 'nasm' 'pkgconf' 'git' 'vulkan-headers' 'gtk4' 'libadwaita' 'sdl3' 'ffmpeg' 'pipewire' 'wayland' 'libxkbcommon' 'opus' 'libei') # Opt-in punktfunk-web: only then is bun (the build tool AND the vendored runtime) required. @@ -64,7 +65,10 @@ build() { # The host's zero-copy FFI link-needs libcuda at build time; nvidia-utils provides it on an # NVIDIA builder. On a GPU-less builder symlink the CUDA stub into the link path first (same # caveat the RPM documents): ln -s "$(find / -name libcuda.so -path '*stubs*'|head -1)" /usr/lib/ - cargo build --release --locked -p punktfunk-host -p punktfunk-client-linux -p punktfunk-tray + # punktfunk-client-session is the Vulkan/Skia streamer the shell (punktfunk-client) execs for + # a connect — both binaries must ship or streaming from the desktop client breaks. + cargo build --release --locked \ + -p punktfunk-host -p punktfunk-client-linux -p punktfunk-client-session -p punktfunk-tray # Management web console (opt-in): the Nitro `bun`-preset .output bundle (Bun.serve TLS), # built AND run with bun. if [ "${PF_WITH_WEB:-0}" = 1 ]; then @@ -157,16 +161,22 @@ package_punktfunk-host() { package_punktfunk-client() { pkgdesc="Low-latency desktop/game streaming CLIENT — native GTK4/libadwaita Linux app" - # The GTK4/libadwaita client: SDL3 gamepads, FFmpeg (VAAPI) decode, PipeWire audio/mic. + # The GTK4/libadwaita shell + its Vulkan session streamer: SDL3 gamepads, FFmpeg (VAAPI + + # Vulkan Video) decode, PipeWire audio/mic. vulkan-icd-loader: the session binary loads + # libvulkan at runtime (ash) for its ash/Skia presenter. depends=('gtk4' 'libadwaita' 'sdl3' 'ffmpeg' 'pipewire' 'wireplumber' 'pipewire-pulse' - 'opus' 'libglvnd') + 'opus' 'libglvnd' 'vulkan-icd-loader') optdepends=('libva-mesa-driver: VAAPI hardware decode on AMD (incl. Steam Deck); software fallback otherwise' 'intel-media-driver: VAAPI hardware decode on Intel' + 'vulkan-radeon: Vulkan Video decode + presenter on AMD' + 'vulkan-nouveau: Vulkan Video decode + presenter on NVIDIA (nvidia-utils for the proprietary ICD)' 'gamescope: run the client fullscreen in a Gaming-Mode session') install=punktfunk-client.install local R; R="$(_repo)"; local T="$srcdir/target/release" - install -Dm0755 "$T/punktfunk-client" "$pkgdir/usr/bin/punktfunk-client" + install -Dm0755 "$T/punktfunk-client" "$pkgdir/usr/bin/punktfunk-client" + # The session streamer the shell execs for a connect (resolved as its sibling in /usr/bin). + install -Dm0755 "$T/punktfunk-session" "$pkgdir/usr/bin/punktfunk-session" install -Dm0644 "$R/packaging/linux/io.unom.Punktfunk.desktop" \ "$pkgdir/usr/share/applications/io.unom.Punktfunk.desktop" # DualSense hidraw access (full pad fidelity through SDL's HIDAPI driver). diff --git a/packaging/debian/build-client-deb.sh b/packaging/debian/build-client-deb.sh index 3615f6d6..ef8b38d9 100644 --- a/packaging/debian/build-client-deb.sh +++ b/packaging/debian/build-client-deb.sh @@ -19,9 +19,12 @@ ROOTDIR="$(cd "$(dirname "$0")/../.." && pwd)" cd "$ROOTDIR" BIN="target/release/$PKG" -if [ ! -x "$BIN" ]; then - echo "==> building $CRATE (release)" - cargo build --release -p "$CRATE" --locked +# The Vulkan/Skia session streamer the shell execs for a connect — shipped alongside the shell +# (the shell resolves it as its /usr/bin sibling), or desktop streaming breaks. +SESSION_BIN="target/release/punktfunk-session" +if [ ! -x "$BIN" ] || [ ! -x "$SESSION_BIN" ]; then + echo "==> building $CRATE + punktfunk-client-session (release)" + cargo build --release --locked -p "$CRATE" -p punktfunk-client-session fi STAGE="$(mktemp -d)" @@ -30,6 +33,7 @@ DOCDIR="$STAGE/usr/share/doc/$PKG" # --- file layout -------------------------------------------------------------- install -Dm0755 "$BIN" "$STAGE/usr/bin/$PKG" +install -Dm0755 "$SESSION_BIN" "$STAGE/usr/bin/punktfunk-session" install -Dm0644 packaging/linux/io.unom.Punktfunk.desktop \ "$STAGE/usr/share/applications/io.unom.Punktfunk.desktop" # DualSense hidraw access (full pad fidelity through SDL's HIDAPI driver). @@ -73,11 +77,17 @@ Package: $PKG Architecture: any Depends: \${shlibs:Depends} EOF -SHDEPS="$(cd "$SHLIB_TMP" && dpkg-shlibdeps -O --ignore-missing-info "$ROOTDIR/$BIN" 2>/dev/null \ +# Resolve DT_NEEDED for BOTH the shell and the session streamer (dpkg-shlibdeps merges). +SHDEPS="$(cd "$SHLIB_TMP" && dpkg-shlibdeps -O --ignore-missing-info \ + "$ROOTDIR/$BIN" "$ROOTDIR/$SESSION_BIN" 2>/dev/null \ | sed -n 's/^shlibs:Depends=//p')" rm -rf "$SHLIB_TMP" [ -n "$SHDEPS" ] || { echo "dpkg-shlibdeps produced no deps — is dpkg-dev installed?" >&2; exit 1; } +# Manual addition shlibdeps can't see: the session streamer loads libvulkan at runtime (ash, +# dlopen — not a DT_NEEDED), and streaming can't start without it, so it's a hard Depends. +SHDEPS="$SHDEPS, libvulkan1" + # Manual additions shlibdeps can't see: the PipeWire daemon + session manager are runtime # services (audio playback / mic capture degrade gracefully without them — Recommends). RECOMMENDS="pipewire, wireplumber, pipewire-pulse" diff --git a/packaging/flatpak/io.unom.Punktfunk.yml b/packaging/flatpak/io.unom.Punktfunk.yml index c20d0fd7..7c325e12 100644 --- a/packaging/flatpak/io.unom.Punktfunk.yml +++ b/packaging/flatpak/io.unom.Punktfunk.yml @@ -131,6 +131,23 @@ modules: - /lib/cmake - /lib/pkgconfig + # --------------------------------------------------------------------------------------- + # Vulkan-Headers — the SESSION binary's pf-ffvk crate runs bindgen over FFmpeg's + # libavutil/hwcontext_vulkan.h, which `#include `. The GNOME SDK is not + # guaranteed to ship those dev headers, so install them into /app ourselves (headers only, + # no compile) and point pf-ffvk's bindgen at them via PF_FFVK_VULKAN_INCLUDE below. Kept in + # cleanup — headers aren't needed at runtime (the Vulkan LOADER comes from the GL runtime). + # --------------------------------------------------------------------------------------- + - name: vulkan-headers + buildsystem: cmake-ninja + sources: + - type: archive + url: https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.313.0.tar.gz + # `sha256sum vulkan-sdk-1.4.313.0.tar.gz` (verified 2026-07-07). Bump url + sha together. + sha256: 20743c99a96c07290f24377360e7a12bdd2c465ba202e0c7ef2ec25d446cf61d + cleanup: + - '*' + # --------------------------------------------------------------------------------------- # The client. cargo-sources.json is the GENERATED offline crate cache: # python3 flatpak-cargo-generator.py Cargo.lock -o packaging/flatpak/cargo-sources.json @@ -151,6 +168,9 @@ modules: # flatpak-builder pre-downloaded as a pinned source below. No {tag}/{key} # placeholders needed: a template without them is used verbatim. SKIA_BINARIES_URL: file:///run/build/punktfunk-client/skia-binaries.tar.gz + # Point pf-ffvk's bindgen at the Vulkan-Headers installed into /app above (its clang + # invocation doesn't inherit the SDK's default include search, so pass it explicitly). + PF_FFVK_VULKAN_INCLUDE: /app/include build-commands: # Drop the Windows client from the workspace before building. It pins windows-rs as a # git dependency (cfg(windows)-gated, but cargo resolves it for the whole workspace diff --git a/packaging/rpm/punktfunk.spec b/packaging/rpm/punktfunk.spec index 7ac03fd8..aef20ea7 100644 --- a/packaging/rpm/punktfunk.spec +++ b/packaging/rpm/punktfunk.spec @@ -75,10 +75,13 @@ BuildRequires: pkgconfig(libavutil) # Zero-copy GPU path: src/zerocopy/ links libGL + libgbm (mesa) via hand-rolled FFI. BuildRequires: pkgconfig(gl) BuildRequires: pkgconfig(gbm) -# The client subpackage (GTK4 shell + SDL3 gamepads). +# The client subpackage (GTK4 shell + SDL3 gamepads + the Vulkan session streamer). BuildRequires: pkgconfig(gtk4) BuildRequires: pkgconfig(libadwaita-1) BuildRequires: pkgconfig(sdl3) +# The client's pf-ffvk crate runs bindgen over FFmpeg's libavutil/hwcontext_vulkan.h, which +# #include — provided by vulkan-headers (Fedora). +BuildRequires: vulkan-headers # It ALSO links the NVIDIA CUDA driver lib (-lcuda) via FFI, so libcuda.so must be present # at LINK time. A normal NVIDIA host (or Bazzite -nvidia) has it; a headless COPR/koji builder # without a GPU does NOT — point %build at the CUDA toolkit stub (…/stubs/libcuda.so) there, @@ -124,6 +127,9 @@ Summary: Low-latency desktop/game streaming client (punktfunk/1, GTK4) # Audio playback / mic capture want the PipeWire daemon; degrade gracefully without it. Recommends: pipewire Recommends: wireplumber +# The session streamer loads libvulkan at runtime (ash) for its ash/Skia presenter + Vulkan +# Video decode. vulkan-loader provides libvulkan.so.1; the ICD is the GPU's mesa/NVIDIA driver. +Requires: vulkan-loader %description client The native Linux client for punktfunk. Discovers hosts on the LAN (mDNS), trusts @@ -167,7 +173,10 @@ export RUSTUP_TOOLCHAIN=stable # Stamp the exact NVR into the binary for --version / mgmt /health provenance (build.rs reads it). export PUNKTFUNK_BUILD_VERSION="%{version}-%{release}" # --locked: reproducible from (commit + Cargo.lock), matching the .deb build path. -cargo build --release --locked -p punktfunk-host -p punktfunk-client-linux -p punktfunk-tray +# punktfunk-client-session is the Vulkan/Skia streamer the shell execs for a connect — both +# client binaries must ship or streaming from the desktop client breaks. +cargo build --release --locked \ + -p punktfunk-host -p punktfunk-client-linux -p punktfunk-client-session -p punktfunk-tray %if %{with web} # Management web console: build the Nitro SSR bundle with bun (the `bun` preset + our Bun.serve @@ -224,6 +233,8 @@ done # --- client subpackage --- install -Dm0755 target/release/punktfunk-client %{buildroot}%{_bindir}/punktfunk-client +# The session streamer the shell execs for a connect (resolved as its sibling in %{_bindir}). +install -Dm0755 target/release/punktfunk-session %{buildroot}%{_bindir}/punktfunk-session install -Dm0644 packaging/linux/io.unom.Punktfunk.desktop \ %{buildroot}%{_datadir}/applications/io.unom.Punktfunk.desktop # DualSense hidraw access (full pad fidelity through SDL's HIDAPI driver). @@ -316,6 +327,7 @@ install -Dm0644 web/web.env.example %{buildroot}%{_datadir}/punkt %files client %license LICENSE-MIT LICENSE-APACHE THIRD-PARTY-NOTICES.txt %{_bindir}/punktfunk-client +%{_bindir}/punktfunk-session %{_datadir}/applications/io.unom.Punktfunk.desktop %{_udevrulesdir}/70-punktfunk-client.rules %{_prefix}/lib/sysctl.d/99-punktfunk-client-net.conf