Files
peerspeak/flake.nix
T
mollusk 0e395e5c0c
CI / check (push) Canceled after 0s
build(nix): pin the Rust toolchain to 1.97.1 via rust-overlay
nixpkgs 26.05 ships rustc 1.95.0, but this crate was developed and verified on
1.97.1 (what CachyOS had, installed 2026-07-17). Taking the compiler from
oxalica/rust-overlay decouples "which Rust the project targets" from "which
release the audio stack came from", so a nixpkgs bump can no longer move the
compiler under the lint gate as a side effect.

Chosen over rustup, which would also have worked here (nix-ld is enabled, so
its prebuilt binaries run) and would have let one rust-toolchain.toml cover the
packaging distroboxes too. The deciding factor is purity: rustup records
nothing in flake.lock, so a fresh clone or darp5 would resolve whatever it
fetched that day. rust-overlay gives the same exact-version control with the
choice pinned in the lock.

`.default` is the rustup "default" profile — rustc, cargo, rust-std, rustfmt
and clippy — so those are no longer listed individually. rust-src and the
x86_64-pc-windows-gnu target are added for win-cross-build.sh, which needs
`-Z build-std=std,panic_abort`; that script still expects the peerspeak-win
distrobox for the mingw half.

Verified on 1.97.1: 640 lib tests pass, fmt clean.

NOT fixed here, and pre-existing rather than a migration artifact:
`cargo clippy --all-targets -- -D warnings` fails with 15 warnings — 13
`float_literal_f32_fallback` (bare 0.05/0.01 into `.step()`, wants `0.05_f32`),
one `manual implementation of Option::filter`, one `redundant reference in
format!`, all in src/app/mod.rs. The f32 lint is `future_incompatible` and is
slated to become a hard error, so it needs fixing regardless of platform.
CachyOS was already on 1.97.1 well before the 2026-07-31 S2 merge logged as
"clippy clean", so that claim reflects a plain `cargo clippy` run, which exits
0 on warnings. `cargo clippy --fix` applies all 15 automatically.
2026-08-07 14:03:35 -04:00

172 lines
7.5 KiB
Nix

{
description = "PeerSpeak — decentralized P2P voice chat (Rust/iroh/PipeWire/Opus/iced)";
inputs = {
# Pinned to the same channel the hosts run (nixos-config tracks
# nixos-26.05), so the libraries this shell links and dlopens are built
# against the same release as the PipeWire daemon and Vulkan ICD actually
# running on the machine. Floating to unstable here would reintroduce
# precisely the client/server version skew the pin exists to prevent.
nixpkgs.url = "github:nixos/nixpkgs/nixos-26.05";
# The Rust toolchain is pinned SEPARATELY from the system libraries, and
# deliberately so. nixpkgs 26.05 ships rustc 1.95.0, but this crate was
# developed and verified against 1.97.1 — close enough to build and pass
# every test, but not close enough for clippy, which flags a
# `collapsible_match` on 1.95 that 1.97 does not. Taking the compiler from
# here decouples "which Rust the project targets" from "which release the
# audio stack came from", so a nixpkgs bump can never silently move the
# compiler under the lint gate again.
#
# This is the reproducible alternative to rustup: same exact-version
# control, but the choice is recorded in flake.lock, so darp5 or a fresh
# clone resolves the identical toolchain instead of whatever rustup happens
# to fetch that day.
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{ nixpkgs, rust-overlay, ... }:
let
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
overlays = [ rust-overlay.overlays.default ];
};
# Matches what CachyOS shipped (rust 1:1.97.1-1), which is the toolchain
# every green result in the handoff was produced with.
#
# `default` is the rustup "default" profile — rustc, cargo, rust-std,
# rustfmt and clippy — so those are NOT listed separately below.
#
# rust-src and the windows-gnu target exist for win-cross-build.sh, which
# needs `-Z build-std=std,panic_abort` for the self-contained .exe. That
# script still expects to run in the peerspeak-win distrobox for the
# mingw toolchain; carrying the target here just means the Rust half is
# already in place if it is ever driven from the host.
rustToolchain = pkgs.rust-bin.stable."1.97.1".default.override {
extensions = [ "rust-src" ];
targets = [ "x86_64-pc-windows-gnu" ];
};
# Libraries that iced/winit/wgpu open with dlopen at RUNTIME rather than
# linking at build time. Because nothing links them, they never land in
# the binary's rpath — under `cargo run` the loader finds them only
# through LD_LIBRARY_PATH. Leaving them out builds fine and then panics
# at window creation, which is a genuinely confusing failure, so they are
# listed explicitly instead of discovered the hard way.
runtimeLibs = with pkgs; [
vulkan-loader # wgpu's Vulkan backend (iced's renderer)
libxkbcommon # winit keyboard handling
wayland # wayland-sys, dlopen'd on a Wayland session
libx11 # x11-dl, dlopen'd on the X11 fallback path
libxcursor
libxrandr
libxi
];
# Screen sharing spawns pixelpass as a CHILD PROCESS, and pixelpass in
# turn drives GStreamer as a subprocess. That makes these tools a
# dependency of peerspeak's own test suite, not just of pixelpass:
# `tests/screenshare_host_fault.rs` starts a real pixelpass host, which
# aborts at its preflight if gst-launch-1.0 is missing.
#
# Deliberately duplicated from pixelpass's flake rather than importing it
# as an input. The two projects are mutually optional by design — neither
# is a dependency of the other, and the coupling is a runtime subprocess
# contract. Making one flake consume the other would quietly reintroduce
# exactly the build-level dependency that rule exists to prevent.
screenshareTools = with pkgs; [
gst_all_1.gstreamer
gst_all_1.gst-plugins-base
gst_all_1.gst-plugins-good
gst_all_1.gst-plugins-bad
gst_all_1.gst-plugins-ugly
gst_all_1.gst-libav
pipewire # pipewiresrc (Wayland capture; ships in this pkg)
];
in
{
devShells.${system}.default = pkgs.mkShell {
nativeBuildInputs = [
rustToolchain
]
++ (with pkgs; [
# The supply-chain gates .gitea/workflows/ci.yml runs, so the same
# checks are reproducible locally before a push. These were `cargo
# install`ed on the CachyOS side, which does not carry over — those
# binaries link that distro's glibc and will not run here.
# cargo-deny reads deny.toml; cargo-audit reads .cargo/audit.toml.
cargo-audit
cargo-deny
# Debian packaging (`cargo deb --no-build`). Note the .deb itself
# should still be built inside a Debian/Ubuntu distrobox so the
# binary links that distro's glibc — see the packaging notes in
# Cargo.toml.
cargo-deb
pkg-config
# pipewire-sys and libspa-sys generate their bindings with bindgen,
# which needs a real libclang present at build time.
clang
# audiopus_sys prefers the system libopus via pkg-config but falls
# back to a vendored CMake build; cmake keeps that fallback working
# rather than failing obscurely inside a build script.
cmake
# build.rs shells out to `git rev-parse --short=8 HEAD` to stamp
# PEERSPEAK_GIT_SHORT into the binary (surfaced in Settings).
git
])
++ screenshareTools
++ [
pkgs.pulseaudio # `pactl`, used by pixelpass's audio routing
pkgs.mpv # the screen-share viewer
];
buildInputs =
with pkgs;
[
alsa-lib # alsa-sys, pulled in by rodio/cpal
libopus # audiopus_sys, linked dynamically
pipewire # pipewire-sys + libspa-sys: the Linux audio backend
]
++ runtimeLibs;
# bindgen finds libclang through this variable specifically — having
# clang on PATH is not sufficient.
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath runtimeLibs;
# NixOS keeps every GStreamer plugin in its own store path, so the
# gst-launch-1.0 that pixelpass spawns discovers them ONLY through this
# search path. Same reasoning as hosts/darp5 and hosts/cazen in
# nixos-config.
GST_PLUGIN_SYSTEM_PATH_1_0 =
pkgs.lib.makeSearchPathOutput "lib" "lib/gstreamer-1.0" screenshareTools;
# Only greet an interactive shell. shellHook also runs under
# `nix develop --command …`, where printing this would interleave the
# banner with the command's own output.
shellHook = ''
if [ -t 1 ]; then
echo "peerspeak — rustc $(rustc --version | cut -d' ' -f2) / cargo $(cargo --version | cut -d' ' -f2)"
echo " cargo build --release build"
echo " cargo test lib tests"
echo " cargo clippy --all-targets -- -D warnings lint"
echo
echo "Screen sharing spawns pixelpass as a child process — it must be"
echo "on PATH. Build it from ../pixelpass and add its target/release."
fi
'';
};
};
}