style(nix): run the repo's own nix fmt (nixfmt-rfc-style) over the flake
flake.nix, packaging/nix/packages.nix and packaging/nix/nixos-module.nix had drifted from the formatter the flake itself declares (`formatter = nixfmt-rfc-style`). Pure reformat — no expression changes — split out so the bun2nix migration that follows is reviewable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit 927b27c4fade6d646e3ef822678b6738f1e2f28a)
This commit is contained in:
@@ -26,10 +26,12 @@
|
|||||||
# The workspace version is the single source of truth (crates/*/Cargo.toml inherit it).
|
# The workspace version is the single source of truth (crates/*/Cargo.toml inherit it).
|
||||||
version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace.package.version;
|
version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace.package.version;
|
||||||
|
|
||||||
pkgsFor = system: import nixpkgs {
|
pkgsFor =
|
||||||
inherit system;
|
system:
|
||||||
overlays = [ (import rust-overlay) ];
|
import nixpkgs {
|
||||||
};
|
inherit system;
|
||||||
|
overlays = [ (import rust-overlay) ];
|
||||||
|
};
|
||||||
|
|
||||||
# Pin cargo/rustc EXACTLY to rust-toolchain.toml (channel 1.96.0 + rustfmt/clippy) so a Nix
|
# Pin cargo/rustc EXACTLY to rust-toolchain.toml (channel 1.96.0 + rustfmt/clippy) so a Nix
|
||||||
# build, a dev shell and CI all use the identical toolchain — the repo is deliberate about
|
# build, a dev shell and CI all use the identical toolchain — the repo is deliberate about
|
||||||
@@ -38,7 +40,8 @@
|
|||||||
|
|
||||||
craneLibFor = pkgs: (crane.mkLib pkgs).overrideToolchain toolchainFor;
|
craneLibFor = pkgs: (crane.mkLib pkgs).overrideToolchain toolchainFor;
|
||||||
|
|
||||||
packagesFor = system:
|
packagesFor =
|
||||||
|
system:
|
||||||
let
|
let
|
||||||
pkgs = pkgsFor system;
|
pkgs = pkgsFor system;
|
||||||
in
|
in
|
||||||
@@ -49,17 +52,30 @@
|
|||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages = forAllSystems (system:
|
packages = forAllSystems (
|
||||||
let pf = packagesFor system;
|
system:
|
||||||
in {
|
let
|
||||||
inherit (pf) punktfunk-host punktfunk-client punktfunk-web punktfunk-scripting punktfunk-tray;
|
pf = packagesFor system;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit (pf)
|
||||||
|
punktfunk-host
|
||||||
|
punktfunk-client
|
||||||
|
punktfunk-web
|
||||||
|
punktfunk-scripting
|
||||||
|
punktfunk-tray
|
||||||
|
;
|
||||||
default = pf.punktfunk-host;
|
default = pf.punktfunk-host;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
# `nix run .#punktfunk-host -- serve` / `nix run .#punktfunk-client`.
|
# `nix run .#punktfunk-host -- serve` / `nix run .#punktfunk-client`.
|
||||||
apps = forAllSystems (system:
|
apps = forAllSystems (
|
||||||
let pf = packagesFor system;
|
system:
|
||||||
in {
|
let
|
||||||
|
pf = packagesFor system;
|
||||||
|
in
|
||||||
|
{
|
||||||
punktfunk-host = {
|
punktfunk-host = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${pf.punktfunk-host}/bin/punktfunk-host";
|
program = "${pf.punktfunk-host}/bin/punktfunk-host";
|
||||||
@@ -80,19 +96,30 @@
|
|||||||
program = "${pf.punktfunk-scripting}/bin/punktfunk-scripting";
|
program = "${pf.punktfunk-scripting}/bin/punktfunk-scripting";
|
||||||
};
|
};
|
||||||
default = self.apps.${system}.punktfunk-host;
|
default = self.apps.${system}.punktfunk-host;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
# `nix flake check` builds every package (web included — needs its deps hash filled in, see
|
# `nix flake check` builds every package (web included — needs its deps hash filled in, see
|
||||||
# packaging/nix/README.md).
|
# packaging/nix/README.md).
|
||||||
checks = forAllSystems (system:
|
checks = forAllSystems (
|
||||||
let pf = packagesFor system;
|
system:
|
||||||
in {
|
let
|
||||||
inherit (pf) punktfunk-host punktfunk-client punktfunk-web punktfunk-scripting;
|
pf = packagesFor system;
|
||||||
});
|
in
|
||||||
|
{
|
||||||
|
inherit (pf)
|
||||||
|
punktfunk-host
|
||||||
|
punktfunk-client
|
||||||
|
punktfunk-web
|
||||||
|
punktfunk-scripting
|
||||||
|
;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
# `nix develop` — the pinned toolchain plus every system lib the workspace links, wired so
|
# `nix develop` — the pinned toolchain plus every system lib the workspace links, wired so
|
||||||
# `cargo build` (all crates, host + client) works out of the box.
|
# `cargo build` (all crates, host + client) works out of the box.
|
||||||
devShells = forAllSystems (system:
|
devShells = forAllSystems (
|
||||||
|
system:
|
||||||
let
|
let
|
||||||
pkgs = pkgsFor system;
|
pkgs = pkgsFor system;
|
||||||
toolchain = toolchainFor pkgs;
|
toolchain = toolchainFor pkgs;
|
||||||
@@ -134,9 +161,16 @@
|
|||||||
PF_FFVK_VULKAN_INCLUDE = "${pkgs.vulkan-headers}/include";
|
PF_FFVK_VULKAN_INCLUDE = "${pkgs.vulkan-headers}/include";
|
||||||
# CMake ≥ 4 rejects the pre-3.5 minimums some vendored C libs (libopus) still declare.
|
# CMake ≥ 4 rejects the pre-3.5 minimums some vendored C libs (libopus) still declare.
|
||||||
CMAKE_POLICY_VERSION_MINIMUM = "3.5";
|
CMAKE_POLICY_VERSION_MINIMUM = "3.5";
|
||||||
LD_LIBRARY_PATH = "/run/opengl-driver/lib:${pkgs.lib.makeLibraryPath [ pkgs.vulkan-loader pkgs.libGL gbm ]}";
|
LD_LIBRARY_PATH = "/run/opengl-driver/lib:${
|
||||||
|
pkgs.lib.makeLibraryPath [
|
||||||
|
pkgs.vulkan-loader
|
||||||
|
pkgs.libGL
|
||||||
|
gbm
|
||||||
|
]
|
||||||
|
}";
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
formatter = forAllSystems (system: (pkgsFor system).nixfmt-rfc-style);
|
formatter = forAllSystems (system: (pkgsFor system).nixfmt-rfc-style);
|
||||||
|
|
||||||
|
|||||||
@@ -21,22 +21,36 @@
|
|||||||
# for a session with `systemctl --user enable --now punktfunk-host` (or set `autoStart = true` for a
|
# for a session with `systemctl --user enable --now punktfunk-host` (or set `autoStart = true` for a
|
||||||
# headless appliance with `users.users.<u>.linger = true`).
|
# headless appliance with `users.users.<u>.linger = true`).
|
||||||
self:
|
self:
|
||||||
{ config, lib, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
mkEnableOption mkOption mkIf mkMerge mkDefault types
|
mkEnableOption
|
||||||
optional optionals optionalString literalExpression
|
mkOption
|
||||||
concatStringsSep mapAttrsToList genAttrs;
|
mkIf
|
||||||
|
mkMerge
|
||||||
|
mkDefault
|
||||||
|
types
|
||||||
|
optional
|
||||||
|
optionals
|
||||||
|
optionalString
|
||||||
|
literalExpression
|
||||||
|
concatStringsSep
|
||||||
|
mapAttrsToList
|
||||||
|
genAttrs
|
||||||
|
;
|
||||||
|
|
||||||
cfg = config.services.punktfunk;
|
cfg = config.services.punktfunk;
|
||||||
system = pkgs.stdenv.hostPlatform.system;
|
system = pkgs.stdenv.hostPlatform.system;
|
||||||
|
|
||||||
# host.env rendering: booleans → 1/0 (what PUNKTFUNK_* knobs expect), everything else verbatim.
|
# host.env rendering: booleans → 1/0 (what PUNKTFUNK_* knobs expect), everything else verbatim.
|
||||||
renderVal = v:
|
renderVal = v: if lib.isBool v then (if v then "1" else "0") else toString v;
|
||||||
if lib.isBool v then (if v then "1" else "0")
|
renderEnv =
|
||||||
else toString v;
|
attrs: concatStringsSep "\n" (mapAttrsToList (k: v: "${k}=${renderVal v}") attrs) + "\n";
|
||||||
renderEnv = attrs:
|
|
||||||
concatStringsSep "\n" (mapAttrsToList (k: v: "${k}=${renderVal v}") attrs) + "\n";
|
|
||||||
|
|
||||||
hostSettingsFile = pkgs.writeText "punktfunk-host.env" (renderEnv cfg.host.settings);
|
hostSettingsFile = pkgs.writeText "punktfunk-host.env" (renderEnv cfg.host.settings);
|
||||||
|
|
||||||
@@ -44,10 +58,21 @@ let
|
|||||||
# ephemeral per-session UDP port the host hole-punches, so nothing fixed to open (see
|
# ephemeral per-session UDP port the host hole-punches, so nothing fixed to open (see
|
||||||
# packaging/linux/punktfunk.ufw).
|
# packaging/linux/punktfunk.ufw).
|
||||||
nativeTCP = [ 47990 ]; # mgmt/library REST API (HTTPS + mTLS)
|
nativeTCP = [ 47990 ]; # mgmt/library REST API (HTTPS + mTLS)
|
||||||
nativeUDP = [ 9777 5353 ]; # QUIC control plane + mDNS
|
nativeUDP = [
|
||||||
|
9777
|
||||||
|
5353
|
||||||
|
]; # QUIC control plane + mDNS
|
||||||
# GameStream/Moonlight-compat fixed ports (opt-in with `host.gamestream`).
|
# GameStream/Moonlight-compat fixed ports (opt-in with `host.gamestream`).
|
||||||
gamestreamTCP = [ 47984 47989 48010 ];
|
gamestreamTCP = [
|
||||||
gamestreamUDP = [ 47998 47999 48000 ];
|
47984
|
||||||
|
47989
|
||||||
|
48010
|
||||||
|
];
|
||||||
|
gamestreamUDP = [
|
||||||
|
47998
|
||||||
|
47999
|
||||||
|
48000
|
||||||
|
];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.punktfunk = {
|
options.services.punktfunk = {
|
||||||
@@ -93,7 +118,13 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
settings = mkOption {
|
settings = mkOption {
|
||||||
type = types.attrsOf (types.oneOf [ types.str types.int types.bool ]);
|
type = types.attrsOf (
|
||||||
|
types.oneOf [
|
||||||
|
types.str
|
||||||
|
types.int
|
||||||
|
types.bool
|
||||||
|
]
|
||||||
|
);
|
||||||
default = { };
|
default = { };
|
||||||
example = literalExpression ''
|
example = literalExpression ''
|
||||||
{
|
{
|
||||||
@@ -233,10 +264,12 @@ in
|
|||||||
config = mkMerge [
|
config = mkMerge [
|
||||||
# --- shared: whenever either half is enabled -----------------------------------------------
|
# --- shared: whenever either half is enabled -----------------------------------------------
|
||||||
(mkIf (cfg.host.enable || cfg.client.enable) {
|
(mkIf (cfg.host.enable || cfg.client.enable) {
|
||||||
assertions = [{
|
assertions = [
|
||||||
assertion = system == "x86_64-linux";
|
{
|
||||||
message = "services.punktfunk is x86_64-linux only (desktop NVENC host; no aarch64 build).";
|
assertion = system == "x86_64-linux";
|
||||||
}];
|
message = "services.punktfunk is x86_64-linux only (desktop NVENC host; no aarch64 build).";
|
||||||
|
}
|
||||||
|
];
|
||||||
# The GPU driver libs the binaries dlopen at runtime (libcuda / libnvidia-encode / libEGL /
|
# The GPU driver libs the binaries dlopen at runtime (libcuda / libnvidia-encode / libEGL /
|
||||||
# the Vulkan ICD) live under /run/opengl-driver/lib — provided by hardware.graphics.
|
# the Vulkan ICD) live under /run/opengl-driver/lib — provided by hardware.graphics.
|
||||||
hardware.graphics.enable = mkDefault true;
|
hardware.graphics.enable = mkDefault true;
|
||||||
@@ -257,11 +290,17 @@ in
|
|||||||
services.udev.path = [ pkgs.coreutils ];
|
services.udev.path = [ pkgs.coreutils ];
|
||||||
# uinput/uhid: the virtual X360 + DualSense nodes. vhci-hcd: the usbip transport that makes
|
# uinput/uhid: the virtual X360 + DualSense nodes. vhci-hcd: the usbip transport that makes
|
||||||
# the virtual Steam Deck a real USB device (Steam Input only adopts USB pads).
|
# the virtual Steam Deck a real USB device (Steam Input only adopts USB pads).
|
||||||
boot.kernelModules = [ "uinput" "uhid" "vhci-hcd" ];
|
boot.kernelModules = [
|
||||||
|
"uinput"
|
||||||
|
"uhid"
|
||||||
|
"vhci-hcd"
|
||||||
|
];
|
||||||
|
|
||||||
# `input` group membership for the virtual-gamepad nodes (mirrors the RPM's usermod hint).
|
# `input` group membership for the virtual-gamepad nodes (mirrors the RPM's usermod hint).
|
||||||
users.groups.input = { };
|
users.groups.input = { };
|
||||||
users.users = genAttrs cfg.host.users (_: { extraGroups = [ "input" ]; });
|
users.users = genAttrs cfg.host.users (_: {
|
||||||
|
extraGroups = [ "input" ];
|
||||||
|
});
|
||||||
|
|
||||||
# Status-tray autostart entry (self-gating: `--autostart` exits unless this user runs a host).
|
# Status-tray autostart entry (self-gating: `--autostart` exits unless this user runs a host).
|
||||||
environment.etc."xdg/autostart/io.unom.Punktfunk.Tray.desktop".source =
|
environment.etc."xdg/autostart/io.unom.Punktfunk.Tray.desktop".source =
|
||||||
@@ -281,10 +320,14 @@ in
|
|||||||
wantedBy = optional cfg.host.autoStart "default.target";
|
wantedBy = optional cfg.host.autoStart "default.target";
|
||||||
# The host may exec external helpers (pw-dump, sh, and — for the gamescope/kwin backends —
|
# The host may exec external helpers (pw-dump, sh, and — for the gamescope/kwin backends —
|
||||||
# the compositor). Extend this in your config for a headless gamescope/KWin appliance.
|
# the compositor). Extend this in your config for a headless gamescope/KWin appliance.
|
||||||
path = [ pkgs.bash pkgs.coreutils pkgs.pipewire ];
|
path = [
|
||||||
|
pkgs.bash
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.pipewire
|
||||||
|
];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${cfg.host.package}/bin/punktfunk-host serve"
|
ExecStart =
|
||||||
+ optionalString cfg.host.gamestream " --gamestream";
|
"${cfg.host.package}/bin/punktfunk-host serve" + optionalString cfg.host.gamestream " --gamestream";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = 2;
|
RestartSec = 2;
|
||||||
EnvironmentFile =
|
EnvironmentFile =
|
||||||
@@ -339,7 +382,10 @@ in
|
|||||||
systemd.user.services.punktfunk-web = {
|
systemd.user.services.punktfunk-web = {
|
||||||
description = "punktfunk management web console";
|
description = "punktfunk management web console";
|
||||||
documentation = [ "https://git.unom.io/unom/punktfunk" ];
|
documentation = [ "https://git.unom.io/unom/punktfunk" ];
|
||||||
after = [ "punktfunk-web-init.service" "punktfunk-host.service" ];
|
after = [
|
||||||
|
"punktfunk-web-init.service"
|
||||||
|
"punktfunk-host.service"
|
||||||
|
];
|
||||||
wants = [ "punktfunk-web-init.service" ];
|
wants = [ "punktfunk-web-init.service" ];
|
||||||
wantedBy = optional cfg.web.autoStart "default.target";
|
wantedBy = optional cfg.web.autoStart "default.target";
|
||||||
environment = {
|
environment = {
|
||||||
|
|||||||
+156
-132
@@ -103,7 +103,10 @@ let
|
|||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
homepage = "https://git.unom.io/unom/punktfunk";
|
homepage = "https://git.unom.io/unom/punktfunk";
|
||||||
license = with lib.licenses; [ mit asl20 ];
|
license = with lib.licenses; [
|
||||||
|
mit
|
||||||
|
asl20
|
||||||
|
];
|
||||||
platforms = [ "x86_64-linux" ]; # NVENC desktop host; matches the RPM's ExclusiveArch: x86_64
|
platforms = [ "x86_64-linux" ]; # NVENC desktop host; matches the RPM's ExclusiveArch: x86_64
|
||||||
maintainers = [ ];
|
maintainers = [ ];
|
||||||
};
|
};
|
||||||
@@ -115,156 +118,164 @@ let
|
|||||||
# runtime (see crates/punktfunk-tray/Cargo.toml), so a tokio-flavoured zbus panics at startup:
|
# runtime (see crates/punktfunk-tray/Cargo.toml), so a tokio-flavoured zbus panics at startup:
|
||||||
# "there is no reactor running, must be called from the context of a Tokio 1.x runtime". A separate
|
# "there is no reactor running, must be called from the context of a Tokio 1.x runtime". A separate
|
||||||
# invocation keeps the tray's zbus on async-io. (The host package copies this binary into its $out.)
|
# invocation keeps the tray's zbus on async-io. (The host package copies this binary into its $out.)
|
||||||
punktfunk-tray = craneLib.buildPackage (commonArgs // {
|
punktfunk-tray = craneLib.buildPackage (
|
||||||
pname = "punktfunk-tray";
|
commonArgs
|
||||||
cargoExtraArgs = "--locked -p punktfunk-tray";
|
// {
|
||||||
PUNKTFUNK_BUILD_VERSION = buildVersion;
|
pname = "punktfunk-tray";
|
||||||
# Pure-Rust leaf: ksni/zbus talk to the dbus socket, ureq+rustls(ring) + punktfunk-core `tls` —
|
cargoExtraArgs = "--locked -p punktfunk-tray";
|
||||||
# nothing to link (no buildInputs) and no GPU driver runpath (it never dlopens libcuda/EGL/vulkan).
|
PUNKTFUNK_BUILD_VERSION = buildVersion;
|
||||||
meta = meta // {
|
# Pure-Rust leaf: ksni/zbus talk to the dbus socket, ureq+rustls(ring) + punktfunk-core `tls` —
|
||||||
description = "punktfunk host status tray (Linux StatusNotifierItem)";
|
# nothing to link (no buildInputs) and no GPU driver runpath (it never dlopens libcuda/EGL/vulkan).
|
||||||
mainProgram = "punktfunk-tray";
|
meta = meta // {
|
||||||
};
|
description = "punktfunk host status tray (Linux StatusNotifierItem)";
|
||||||
});
|
mainProgram = "punktfunk-tray";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
inherit punktfunk-tray;
|
inherit punktfunk-tray;
|
||||||
|
|
||||||
punktfunk-host = craneLib.buildPackage (commonArgs // {
|
punktfunk-host = craneLib.buildPackage (
|
||||||
pname = "punktfunk-host";
|
commonArgs
|
||||||
# HOST ONLY — the tray is a separate derivation (see the note above; co-building crashes it).
|
// {
|
||||||
cargoExtraArgs =
|
pname = "punktfunk-host";
|
||||||
"--locked -p punktfunk-host "
|
# HOST ONLY — the tray is a separate derivation (see the note above; co-building crashes it).
|
||||||
+ "--features punktfunk-host/nvenc,punktfunk-host/vulkan-encode";
|
cargoExtraArgs =
|
||||||
|
"--locked -p punktfunk-host " + "--features punktfunk-host/nvenc,punktfunk-host/vulkan-encode";
|
||||||
|
|
||||||
PUNKTFUNK_BUILD_VERSION = buildVersion;
|
PUNKTFUNK_BUILD_VERSION = buildVersion;
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
ffmpeg # libavcodec/avformat/avutil (NVENC + VAAPI encode), via ffmpeg-next → ffmpeg-sys-next pkg-config
|
ffmpeg # libavcodec/avformat/avutil (NVENC + VAAPI encode), via ffmpeg-next → ffmpeg-sys-next pkg-config
|
||||||
pipewire # libpipewire-0.3 + libspa-0.2 (portal capture + the `pipewire` crate)
|
pipewire # libpipewire-0.3 + libspa-0.2 (portal capture + the `pipewire` crate)
|
||||||
libopus # audiopus_sys links system opus via pkg-config (else it vendors a static libopus that mis-links)
|
libopus # audiopus_sys links system opus via pkg-config (else it vendors a static libopus that mis-links)
|
||||||
wayland # libwayland-client (wlr / KWin fake_input backends)
|
wayland # libwayland-client (wlr / KWin fake_input backends)
|
||||||
libxkbcommon # virtual-keyboard keymap build/validate
|
libxkbcommon # virtual-keyboard keymap build/validate
|
||||||
libGL # src/linux/zerocopy/egl.rs `#[link(name = "GL")]`
|
libGL # src/linux/zerocopy/egl.rs `#[link(name = "GL")]`
|
||||||
gbm # src/linux/zerocopy/egl.rs `#[link(name = "gbm")]`
|
gbm # src/linux/zerocopy/egl.rs `#[link(name = "gbm")]`
|
||||||
vulkan-loader # ash (Vulkan-Video encode + the dmabuf→VK bridge); loaded at runtime
|
vulkan-loader # ash (Vulkan-Video encode + the dmabuf→VK bridge); loaded at runtime
|
||||||
];
|
];
|
||||||
|
|
||||||
# KWin resolves a streaming client to a .desktop by matching /proc/<pid>/exe against `Exec`, so
|
# KWin resolves a streaming client to a .desktop by matching /proc/<pid>/exe against `Exec`, so
|
||||||
# the host's authorization .desktop must name the ACTUAL binary path (the store path here). The
|
# the host's authorization .desktop must name the ACTUAL binary path (the store path here). The
|
||||||
# tray/client .desktop Exec lines are rewritten for the same reason (menu launch / autostart).
|
# tray/client .desktop Exec lines are rewritten for the same reason (menu launch / autostart).
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
# The status tray, built in its own derivation (see the punktfunk-tray note above) so its zbus
|
# The status tray, built in its own derivation (see the punktfunk-tray note above) so its zbus
|
||||||
# stays on async-io; ship it in the host's $out so the tray .desktop below resolves it.
|
# stays on async-io; ship it in the host's $out so the tray .desktop below resolves it.
|
||||||
install -Dm0755 ${punktfunk-tray}/bin/punktfunk-tray "$out/bin/punktfunk-tray"
|
install -Dm0755 ${punktfunk-tray}/bin/punktfunk-tray "$out/bin/punktfunk-tray"
|
||||||
|
|
||||||
# udev: /dev/uinput + /dev/uhid (virtual gamepads) + the vhci sysfs perms for the virtual Deck.
|
# udev: /dev/uinput + /dev/uhid (virtual gamepads) + the vhci sysfs perms for the virtual Deck.
|
||||||
install -Dm0644 scripts/60-punktfunk.rules "$out/lib/udev/rules.d/60-punktfunk.rules"
|
install -Dm0644 scripts/60-punktfunk.rules "$out/lib/udev/rules.d/60-punktfunk.rules"
|
||||||
|
|
||||||
# KWin Desktop-mode authorization (zkde_screencast + fake_input). Point Exec at the store binary.
|
# KWin Desktop-mode authorization (zkde_screencast + fake_input). Point Exec at the store binary.
|
||||||
install -Dm0644 packaging/linux/io.unom.Punktfunk.Host.desktop \
|
install -Dm0644 packaging/linux/io.unom.Punktfunk.Host.desktop \
|
||||||
"$out/share/applications/io.unom.Punktfunk.Host.desktop"
|
"$out/share/applications/io.unom.Punktfunk.Host.desktop"
|
||||||
substituteInPlace "$out/share/applications/io.unom.Punktfunk.Host.desktop" \
|
substituteInPlace "$out/share/applications/io.unom.Punktfunk.Host.desktop" \
|
||||||
--replace-fail "/usr/bin/punktfunk-host" "$out/bin/punktfunk-host"
|
--replace-fail "/usr/bin/punktfunk-host" "$out/bin/punktfunk-host"
|
||||||
|
|
||||||
# Status-tray autostart entry + its hicolor status icons.
|
# Status-tray autostart entry + its hicolor status icons.
|
||||||
install -Dm0644 packaging/linux/io.unom.Punktfunk.Tray.desktop \
|
install -Dm0644 packaging/linux/io.unom.Punktfunk.Tray.desktop \
|
||||||
"$out/etc/xdg/autostart/io.unom.Punktfunk.Tray.desktop"
|
"$out/etc/xdg/autostart/io.unom.Punktfunk.Tray.desktop"
|
||||||
substituteInPlace "$out/etc/xdg/autostart/io.unom.Punktfunk.Tray.desktop" \
|
substituteInPlace "$out/etc/xdg/autostart/io.unom.Punktfunk.Tray.desktop" \
|
||||||
--replace-fail "/usr/bin/punktfunk-tray" "$out/bin/punktfunk-tray"
|
--replace-fail "/usr/bin/punktfunk-tray" "$out/bin/punktfunk-tray"
|
||||||
for sz in 22x22 48x48; do
|
for sz in 22x22 48x48; do
|
||||||
for png in packaging/linux/icons/hicolor/$sz/apps/*.png; do
|
for png in packaging/linux/icons/hicolor/$sz/apps/*.png; do
|
||||||
install -Dm0644 "$png" "$out/share/icons/hicolor/$sz/apps/$(basename "$png")"
|
install -Dm0644 "$png" "$out/share/icons/hicolor/$sz/apps/$(basename "$png")"
|
||||||
|
done
|
||||||
done
|
done
|
||||||
done
|
|
||||||
|
|
||||||
# Reference material: headless session helpers, example env files, the OpenAPI doc.
|
# Reference material: headless session helpers, example env files, the OpenAPI doc.
|
||||||
install -Dm0755 scripts/headless/run-headless-kde.sh "$out/share/punktfunk-host/headless/run-headless-kde.sh"
|
install -Dm0755 scripts/headless/run-headless-kde.sh "$out/share/punktfunk-host/headless/run-headless-kde.sh"
|
||||||
install -Dm0755 scripts/headless/run-headless-sway.sh "$out/share/punktfunk-host/headless/run-headless-sway.sh"
|
install -Dm0755 scripts/headless/run-headless-sway.sh "$out/share/punktfunk-host/headless/run-headless-sway.sh"
|
||||||
install -Dm0644 scripts/headless/kde-authorized "$out/share/punktfunk-host/headless/kde-authorized"
|
install -Dm0644 scripts/headless/kde-authorized "$out/share/punktfunk-host/headless/kde-authorized"
|
||||||
install -Dm0644 scripts/headless/punktfunk-sink.conf "$out/share/punktfunk-host/headless/punktfunk-sink.conf"
|
install -Dm0644 scripts/headless/punktfunk-sink.conf "$out/share/punktfunk-host/headless/punktfunk-sink.conf"
|
||||||
install -Dm0644 scripts/host.env.example "$out/share/punktfunk-host/host.env.example"
|
install -Dm0644 scripts/host.env.example "$out/share/punktfunk-host/host.env.example"
|
||||||
install -Dm0644 packaging/bazzite/host.env "$out/share/punktfunk-host/host.env.bazzite"
|
install -Dm0644 packaging/bazzite/host.env "$out/share/punktfunk-host/host.env.bazzite"
|
||||||
install -Dm0644 packaging/kde/host.env "$out/share/punktfunk-host/host.env.kde"
|
install -Dm0644 packaging/kde/host.env "$out/share/punktfunk-host/host.env.kde"
|
||||||
install -Dm0644 api/openapi.json "$out/share/punktfunk-host/openapi.json"
|
install -Dm0644 api/openapi.json "$out/share/punktfunk-host/openapi.json"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# Run AFTER fixup (patchelf --shrink-rpath would otherwise drop /run/opengl-driver/lib, which is
|
# Run AFTER fixup (patchelf --shrink-rpath would otherwise drop /run/opengl-driver/lib, which is
|
||||||
# empty at build time): append the driver runpath so the runtime dlopen of libcuda.so.1 /
|
# empty at build time): append the driver runpath so the runtime dlopen of libcuda.so.1 /
|
||||||
# libnvidia-encode.so.1 / libEGL.so.1 / the GPU's libvulkan ICD resolves from the running system.
|
# libnvidia-encode.so.1 / libEGL.so.1 / the GPU's libvulkan ICD resolves from the running system.
|
||||||
postFixup = ''
|
postFixup = ''
|
||||||
# Only the host dlopens the GPU stack; the tray (its own derivation, copied in above) does not.
|
# Only the host dlopens the GPU stack; the tray (its own derivation, copied in above) does not.
|
||||||
addDriverRunpath "$out/bin/punktfunk-host"
|
addDriverRunpath "$out/bin/punktfunk-host"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = meta // {
|
meta = meta // {
|
||||||
description = "Low-latency desktop/game streaming host (Moonlight-compatible + native punktfunk/1)";
|
description = "Low-latency desktop/game streaming host (Moonlight-compatible + native punktfunk/1)";
|
||||||
mainProgram = "punktfunk-host";
|
mainProgram = "punktfunk-host";
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
punktfunk-client = craneLib.buildPackage (commonArgs // {
|
punktfunk-client = craneLib.buildPackage (
|
||||||
pname = "punktfunk-client";
|
commonArgs
|
||||||
# The session's default `ui` feature pulls skia-safe, whose build DOWNLOADS a prebuilt Skia
|
// {
|
||||||
# (rust-skia releases) — impossible in Nix's network-less build sandbox, and a from-source Skia
|
pname = "punktfunk-client";
|
||||||
# build needs the full gn/ninja/python toolchain + network-fetched third-party. The `ui` feature
|
# The session's default `ui` feature pulls skia-safe, whose build DOWNLOADS a prebuilt Skia
|
||||||
# is explicitly droppable (clients/session/Cargo.toml: "same streaming, stats on stdout only"),
|
# (rust-skia releases) — impossible in Nix's network-less build sandbox, and a from-source Skia
|
||||||
# so build the session without it. The GTK shell (punktfunk-client-linux) is skia-free and full.
|
# build needs the full gn/ninja/python toolchain + network-fetched third-party. The `ui` feature
|
||||||
# Re-adding the Skia OSD under Nix is tracked in packaging/nix/README.md.
|
# is explicitly droppable (clients/session/Cargo.toml: "same streaming, stats on stdout only"),
|
||||||
cargoExtraArgs =
|
# so build the session without it. The GTK shell (punktfunk-client-linux) is skia-free and full.
|
||||||
"--locked -p punktfunk-client-linux -p punktfunk-client-session "
|
# Re-adding the Skia OSD under Nix is tracked in packaging/nix/README.md.
|
||||||
+ "--no-default-features --features punktfunk-client-session/pyrowave";
|
cargoExtraArgs =
|
||||||
|
"--locked -p punktfunk-client-linux -p punktfunk-client-session "
|
||||||
|
+ "--no-default-features --features punktfunk-client-session/pyrowave";
|
||||||
|
|
||||||
# pf-ffvk runs bindgen over libavutil/hwcontext_vulkan.h, which `#include <vulkan/vulkan.h>`.
|
# pf-ffvk runs bindgen over libavutil/hwcontext_vulkan.h, which `#include <vulkan/vulkan.h>`.
|
||||||
# There is no /usr/include on NixOS, so hand it the Vulkan-Headers include dir explicitly
|
# There is no /usr/include on NixOS, so hand it the Vulkan-Headers include dir explicitly
|
||||||
# (build.rs turns this into a clang `-I`). libavutil's own include path comes from pkg-config.
|
# (build.rs turns this into a clang `-I`). libavutil's own include path comes from pkg-config.
|
||||||
PF_FFVK_VULKAN_INCLUDE = "${vulkan-headers}/include";
|
PF_FFVK_VULKAN_INCLUDE = "${vulkan-headers}/include";
|
||||||
|
|
||||||
nativeBuildInputs = commonArgs.nativeBuildInputs ++ [ wrapGAppsHook4 ];
|
nativeBuildInputs = commonArgs.nativeBuildInputs ++ [ wrapGAppsHook4 ];
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
ffmpeg # FFmpeg decode (pf-client-core) + pf-ffvk links libavutil
|
ffmpeg # FFmpeg decode (pf-client-core) + pf-ffvk links libavutil
|
||||||
pipewire # PipeWire audio playback + mic capture
|
pipewire # PipeWire audio playback + mic capture
|
||||||
libopus # audiopus_sys → system opus via pkg-config (Opus decode)
|
libopus # audiopus_sys → system opus via pkg-config (Opus decode)
|
||||||
sdl3 # window + gamepads (SDL3 HIDAPI: DualSense touchpad/motion/triggers)
|
sdl3 # window + gamepads (SDL3 HIDAPI: DualSense touchpad/motion/triggers)
|
||||||
gtk4 # the GTK4 shell (clients/linux, relm4)
|
gtk4 # the GTK4 shell (clients/linux, relm4)
|
||||||
libadwaita
|
libadwaita
|
||||||
glib
|
glib
|
||||||
librsvg # gdk-pixbuf SVG loader for symbolic icons
|
librsvg # gdk-pixbuf SVG loader for symbolic icons
|
||||||
gsettings-desktop-schemas
|
gsettings-desktop-schemas
|
||||||
adwaita-icon-theme
|
adwaita-icon-theme
|
||||||
libxkbcommon
|
libxkbcommon
|
||||||
libGL
|
libGL
|
||||||
vulkan-loader # ash presenter + Vulkan-Video decode (loaded at runtime)
|
vulkan-loader # ash presenter + Vulkan-Video decode (loaded at runtime)
|
||||||
];
|
];
|
||||||
|
|
||||||
# wrapGApp needs to run on the real ELF, and addDriverRunpath must run post-shrink — so disable
|
# wrapGApp needs to run on the real ELF, and addDriverRunpath must run post-shrink — so disable
|
||||||
# the hook's blanket auto-wrap and drive both by hand in postFixup (see the host note above).
|
# the hook's blanket auto-wrap and drive both by hand in postFixup (see the host note above).
|
||||||
dontWrapGApps = true;
|
dontWrapGApps = true;
|
||||||
|
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
# hidraw access for the seated user's DualSense (SDL HIDAPI full-fidelity path).
|
# hidraw access for the seated user's DualSense (SDL HIDAPI full-fidelity path).
|
||||||
install -Dm0644 scripts/70-punktfunk-client.rules "$out/lib/udev/rules.d/70-punktfunk-client.rules"
|
install -Dm0644 scripts/70-punktfunk-client.rules "$out/lib/udev/rules.d/70-punktfunk-client.rules"
|
||||||
|
|
||||||
# Desktop launcher — point Exec at the store binary (wrapped below).
|
# Desktop launcher — point Exec at the store binary (wrapped below).
|
||||||
install -Dm0644 packaging/linux/io.unom.Punktfunk.desktop \
|
install -Dm0644 packaging/linux/io.unom.Punktfunk.desktop \
|
||||||
"$out/share/applications/io.unom.Punktfunk.desktop"
|
"$out/share/applications/io.unom.Punktfunk.desktop"
|
||||||
substituteInPlace "$out/share/applications/io.unom.Punktfunk.desktop" \
|
substituteInPlace "$out/share/applications/io.unom.Punktfunk.desktop" \
|
||||||
--replace-fail "Exec=punktfunk-client" "Exec=$out/bin/punktfunk-client"
|
--replace-fail "Exec=punktfunk-client" "Exec=$out/bin/punktfunk-client"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
postFixup = ''
|
postFixup = ''
|
||||||
addDriverRunpath "$out/bin/punktfunk-client" "$out/bin/punktfunk-session"
|
addDriverRunpath "$out/bin/punktfunk-client" "$out/bin/punktfunk-session"
|
||||||
# Only the GTK shell needs the GApps wrapper (GSETTINGS_SCHEMA_DIR, icon themes, typelibs);
|
# Only the GTK shell needs the GApps wrapper (GSETTINGS_SCHEMA_DIR, icon themes, typelibs);
|
||||||
# the ash session binary is not a GTK app.
|
# the ash session binary is not a GTK app.
|
||||||
wrapGApp "$out/bin/punktfunk-client"
|
wrapGApp "$out/bin/punktfunk-client"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = meta // {
|
meta = meta // {
|
||||||
description = "Native Linux punktfunk/1 streaming client (GTK4 shell + Vulkan session)";
|
description = "Native Linux punktfunk/1 streaming client (GTK4 shell + Vulkan session)";
|
||||||
mainProgram = "punktfunk-client";
|
mainProgram = "punktfunk-client";
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
# --- management web console (punktfunk-web) ------------------------------------------------------
|
# --- management web console (punktfunk-web) ------------------------------------------------------
|
||||||
# The browser console every client needs for SPAKE2 PIN pairing + host status: a TanStack Start /
|
# The browser console every client needs for SPAKE2 PIN pairing + host status: a TanStack Start /
|
||||||
@@ -291,7 +302,10 @@ in
|
|||||||
pname = "punktfunk-web-deps";
|
pname = "punktfunk-web-deps";
|
||||||
inherit version;
|
inherit version;
|
||||||
src = src + "/web";
|
src = src + "/web";
|
||||||
nativeBuildInputs = [ bun cacert ];
|
nativeBuildInputs = [
|
||||||
|
bun
|
||||||
|
cacert
|
||||||
|
];
|
||||||
dontConfigure = true;
|
dontConfigure = true;
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
runHook preBuild
|
runHook preBuild
|
||||||
@@ -322,7 +336,11 @@ in
|
|||||||
# nodejs: the JS build tools' `.bin` shims are `#!/usr/bin/env node`; patchShebangs (below)
|
# nodejs: the JS build tools' `.bin` shims are `#!/usr/bin/env node`; patchShebangs (below)
|
||||||
# repoints them at this node so they run in the sandbox. bun is still the RUNTIME (the launcher
|
# repoints them at this node so they run in the sandbox. bun is still the RUNTIME (the launcher
|
||||||
# execs it); node is build-time only, for orval/paraglide/vite.
|
# execs it); node is build-time only, for orval/paraglide/vite.
|
||||||
nativeBuildInputs = [ bun nodejs makeWrapper ];
|
nativeBuildInputs = [
|
||||||
|
bun
|
||||||
|
nodejs
|
||||||
|
makeWrapper
|
||||||
|
];
|
||||||
|
|
||||||
# No cross-derivation dep cache: codegen + the vite build are fully offline (every input is in
|
# No cross-derivation dep cache: codegen + the vite build are fully offline (every input is in
|
||||||
# the vendored node_modules, the checked-in api/openapi.json, and web/project.inlang).
|
# the vendored node_modules, the checked-in api/openapi.json, and web/project.inlang).
|
||||||
@@ -401,7 +419,10 @@ in
|
|||||||
pname = "punktfunk-scripting-deps";
|
pname = "punktfunk-scripting-deps";
|
||||||
inherit version;
|
inherit version;
|
||||||
src = src + "/sdk";
|
src = src + "/sdk";
|
||||||
nativeBuildInputs = [ bun cacert ];
|
nativeBuildInputs = [
|
||||||
|
bun
|
||||||
|
cacert
|
||||||
|
];
|
||||||
dontConfigure = true;
|
dontConfigure = true;
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
runHook preBuild
|
runHook preBuild
|
||||||
@@ -427,7 +448,10 @@ in
|
|||||||
stdenvNoCC.mkDerivation {
|
stdenvNoCC.mkDerivation {
|
||||||
pname = "punktfunk-scripting";
|
pname = "punktfunk-scripting";
|
||||||
inherit src version;
|
inherit src version;
|
||||||
nativeBuildInputs = [ bun makeWrapper ];
|
nativeBuildInputs = [
|
||||||
|
bun
|
||||||
|
makeWrapper
|
||||||
|
];
|
||||||
|
|
||||||
# `bun build --target=bun` bundles the runner CLI to ONE self-contained JS: effect + the SDK
|
# `bun build --target=bun` bundles the runner CLI to ONE self-contained JS: effect + the SDK
|
||||||
# are inlined, and the runner's dynamic `import()` of the operator's plugin files is left as a
|
# are inlined, and the runner's dynamic `import()` of the operator's plugin files is left as a
|
||||||
|
|||||||
Reference in New Issue
Block a user