253 lines
9.7 KiB
Nix
253 lines
9.7 KiB
Nix
{
|
|
description = "crabidy — a client/server music player";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
|
crane.url = "github:ipetkov/crane";
|
|
fenix = {
|
|
url = "github:nix-community/fenix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
flake-utils.url = "github:numtide/flake-utils";
|
|
};
|
|
|
|
outputs =
|
|
{
|
|
self,
|
|
nixpkgs,
|
|
crane,
|
|
fenix,
|
|
flake-utils,
|
|
}:
|
|
flake-utils.lib.eachDefaultSystem (
|
|
system:
|
|
let
|
|
pkgs = import nixpkgs { inherit system; };
|
|
lib = pkgs.lib;
|
|
fenixPkgs = fenix.packages.${system};
|
|
|
|
# Source that keeps the .proto files crabidy-core/build.rs compiles —
|
|
# crane's default cargo-source cleaning would drop them.
|
|
src = lib.cleanSourceWith {
|
|
src = ./.;
|
|
name = "crabidy-source";
|
|
filter =
|
|
path: type:
|
|
(builtins.match ".*\\.proto$" path != null) || (crane.mkLib pkgs).filterCargoSources path type;
|
|
};
|
|
|
|
# trunk needs cbd-web's non-cargo assets (index.html, style.css,
|
|
# Trunk.toml) which filterCargoSources drops. Keep everything under
|
|
# cbd-web/ (except a stale prebuilt dist/) plus the usual cargo/proto
|
|
# sources.
|
|
webSrc = lib.cleanSourceWith {
|
|
src = ./.;
|
|
name = "crabidy-web-source";
|
|
filter =
|
|
path: type:
|
|
(
|
|
(builtins.match ".*\\.proto$" path != null)
|
|
|| (lib.hasInfix "/cbd-web/" path)
|
|
|| (crane.mkLib pkgs).filterCargoSources path type
|
|
)
|
|
&& !(lib.hasInfix "/cbd-web/dist" path);
|
|
};
|
|
|
|
# Only the real binary crates; never build cbd-web (a wasm crate) for a
|
|
# host or aarch64 target.
|
|
workspaceBins = "-p crabidy-server -p cbd -p cbd-tui";
|
|
|
|
# Headless: everything except the embedded web UI. Spelled out rather
|
|
# than "--no-default-features" alone, which means *no providers at
|
|
# all* (see docs/src/build-features.md) — the features must be named
|
|
# or this package ships an empty server. The
|
|
# aarch64 server (below) takes the full defaults and stages the wasm
|
|
# bundle. `notifications` is cbd-tui's own default and needs no
|
|
# mention here.
|
|
headlessFeatures = "all-providers,opus,spectrum,notifications";
|
|
|
|
# --- Web UI (wasm) bundle ---------------------------------------------
|
|
# cbd-web is compiled to wasm by trunk; the output dist/ is what
|
|
# crabidy-server's build.rs embeds (feature `web-ui`). The bundle is
|
|
# architecture-independent — the same wasm runs in the browser whatever
|
|
# the server's CPU — so one derivation feeds every server build.
|
|
#
|
|
# The wasm-bindgen CLI version must match the wasm-bindgen crate
|
|
# (0.2.126) exactly. nixpkgs ships an older CLI and, in the dev shell,
|
|
# trunk downloads the matching one at build time — impossible in a
|
|
# sealed Nix build, so we pin an overridden CLI here.
|
|
wasmBindgenCli = pkgs.wasm-bindgen-cli.overrideAttrs (_: rec {
|
|
version = "0.2.126";
|
|
src = pkgs.fetchCrate {
|
|
pname = "wasm-bindgen-cli";
|
|
inherit version;
|
|
hash = "sha256-H6Is3fiZVxZCfOMWK5dWMSrtn50VGv0sfdnsT+cTtyk=";
|
|
};
|
|
cargoDeps = pkgs.rustPlatform.fetchCargoVendor {
|
|
inherit src;
|
|
name = "wasm-bindgen-cli-${version}-vendor";
|
|
hash = "sha256-VucqkXbCi4qtQzY/HrXiDnbSURsagPsdNVMn1Tw3UiY=";
|
|
};
|
|
});
|
|
|
|
wasmToolchain = fenixPkgs.combine [
|
|
fenixPkgs.stable.rustc
|
|
fenixPkgs.stable.cargo
|
|
fenixPkgs.targets.wasm32-unknown-unknown.stable.rust-std
|
|
];
|
|
craneLibWasm = (crane.mkLib pkgs).overrideToolchain (_: wasmToolchain);
|
|
|
|
webArgs = {
|
|
src = webSrc;
|
|
strictDeps = true;
|
|
cargoExtraArgs = "--locked -p cbd-web";
|
|
CARGO_BUILD_TARGET = "wasm32-unknown-unknown";
|
|
doCheck = false;
|
|
# crabidy-core's build.rs (a transitive dep of cbd-web) needs protoc.
|
|
nativeBuildInputs = [ pkgs.protobuf ];
|
|
};
|
|
webDeps = craneLibWasm.buildDepsOnly webArgs;
|
|
webBundle = craneLibWasm.buildTrunkPackage (
|
|
webArgs
|
|
// {
|
|
pname = "cbd-web";
|
|
version = "0.1.0";
|
|
cargoArtifacts = webDeps;
|
|
wasm-bindgen-cli = wasmBindgenCli;
|
|
# wasm-opt for the release bundle.
|
|
wasm-opt = pkgs.binaryen;
|
|
# This is a virtual workspace, so trunk run from the root can't
|
|
# resolve the cbd-web member (it reports "could not find the root
|
|
# package"). Build from inside cbd-web, exactly like the dev-shell
|
|
# `build-web` script. The vendored cargo config already pins cargo
|
|
# to the offline vendor dir, so no network is needed.
|
|
buildPhaseCargoCommand = ''
|
|
( cd cbd-web && trunk build index.html --release )
|
|
'';
|
|
installPhaseCommand = ''
|
|
cp -r cbd-web/dist $out
|
|
'';
|
|
}
|
|
);
|
|
|
|
# --- Native toolchain / build (for `nix profile install` on x86_64,
|
|
# aarch64, etc.) ---
|
|
craneLib = (crane.mkLib pkgs).overrideToolchain (_: fenixPkgs.stable.toolchain);
|
|
|
|
nativeArgs = {
|
|
inherit src;
|
|
strictDeps = true;
|
|
cargoExtraArgs = "--locked --no-default-features --features ${headlessFeatures} ${workspaceBins}";
|
|
# protoc + pkg-config are build-host tools (run during the build);
|
|
# with strictDeps they must be nativeBuildInputs or alsa-sys cannot
|
|
# find pkg-config. alsa-lib is the actual linked library. cmake
|
|
# builds the bundled libopus (opusic-sys, via the `opus` feature) —
|
|
# deliberately without ninja, whose mere presence flips cmake's
|
|
# generator and then clashes with a cached build dir.
|
|
nativeBuildInputs = [
|
|
pkgs.protobuf
|
|
pkgs.pkg-config
|
|
pkgs.cmake
|
|
];
|
|
buildInputs = [ pkgs.alsa-lib ];
|
|
# audio-player links libasound; yt-dlp for /youtube stays a runtime
|
|
# dependency, not wired here.
|
|
};
|
|
nativeDeps = craneLib.buildDepsOnly nativeArgs;
|
|
crabidy = craneLib.buildPackage (
|
|
nativeArgs
|
|
// {
|
|
cargoArtifacts = nativeDeps;
|
|
doCheck = false; # tests need a config/network; `nix flake check` can run them later
|
|
}
|
|
);
|
|
|
|
# --- Cross toolchain / build: static aarch64 musl (a portable binary
|
|
# that runs on any aarch64 Linux, incl. a Raspberry Pi) ---
|
|
muslTarget = "aarch64-unknown-linux-musl";
|
|
crossPkgs = pkgs.pkgsCross.aarch64-multiplatform-musl;
|
|
crossCc = "${crossPkgs.stdenv.cc}/bin/${crossPkgs.stdenv.cc.targetPrefix}cc";
|
|
# Static alsa-lib for the target, linked into the binary.
|
|
crossAlsa = crossPkgs.pkgsStatic.alsa-lib;
|
|
|
|
crossToolchain = fenixPkgs.combine [
|
|
fenixPkgs.stable.rustc
|
|
fenixPkgs.stable.cargo
|
|
fenixPkgs.targets.${muslTarget}.stable.rust-std
|
|
];
|
|
craneLibCross = (crane.mkLib pkgs).overrideToolchain (_: crossToolchain);
|
|
|
|
crossEnvTarget = "AARCH64_UNKNOWN_LINUX_MUSL";
|
|
crossArgs = {
|
|
inherit src;
|
|
strictDeps = true;
|
|
# web-ui is a default feature; keep it on so the embedded UI ships.
|
|
cargoExtraArgs = "--locked -p crabidy-server";
|
|
CARGO_BUILD_TARGET = muslTarget;
|
|
|
|
# crabidy-server's build.rs embeds cbd-web/dist (feature `web-ui`).
|
|
# Stage the prebuilt wasm bundle there before the crate compiles.
|
|
preBuild = ''
|
|
rm -rf cbd-web/dist
|
|
cp -rL --no-preserve=mode,ownership ${webBundle} cbd-web/dist
|
|
'';
|
|
|
|
# Build scripts / proc-macros compile for the build host; deps for the
|
|
# target use the cross toolchain. protoc, pkg-config, and cmake (for
|
|
# the bundled libopus) are host tools.
|
|
nativeBuildInputs = [
|
|
pkgs.protobuf
|
|
pkgs.pkg-config
|
|
pkgs.cmake
|
|
];
|
|
buildInputs = [ crossAlsa ];
|
|
depsBuildBuild = [ crossPkgs.stdenv.cc ];
|
|
|
|
# cc-rs (aws-lc-sys, rustls's crypto backend) needs the cross C
|
|
# compiler; the linker is the same cross cc. Static CRT + -static so
|
|
# the binary has no interpreter and runs standalone.
|
|
"CC_aarch64_unknown_linux_musl" = crossCc;
|
|
"CARGO_TARGET_${crossEnvTarget}_LINKER" = crossCc;
|
|
"CARGO_TARGET_${crossEnvTarget}_RUSTFLAGS" = "-C target-feature=+crt-static -C link-arg=-static";
|
|
|
|
# pkg-config resolves the target's static alsa-lib for alsa-sys.
|
|
PKG_CONFIG_ALLOW_CROSS = "1";
|
|
PKG_CONFIG_PATH_aarch64_unknown_linux_musl = "${crossAlsa.dev}/lib/pkgconfig";
|
|
};
|
|
crossDeps = craneLibCross.buildDepsOnly crossArgs;
|
|
crabidy-server-aarch64 = craneLibCross.buildPackage (
|
|
crossArgs
|
|
// {
|
|
cargoArtifacts = crossDeps;
|
|
doCheck = false; # cannot run aarch64 tests on an x86_64 builder
|
|
}
|
|
);
|
|
in
|
|
{
|
|
packages = {
|
|
default = crabidy;
|
|
inherit crabidy crabidy-server-aarch64;
|
|
};
|
|
|
|
apps = {
|
|
cbd = flake-utils.lib.mkApp {
|
|
drv = crabidy;
|
|
name = "cbd";
|
|
};
|
|
cbd-tui = flake-utils.lib.mkApp {
|
|
drv = crabidy;
|
|
name = "cbd-tui";
|
|
};
|
|
crabidy-server = flake-utils.lib.mkApp {
|
|
drv = crabidy;
|
|
name = "crabidy-server";
|
|
};
|
|
default = flake-utils.lib.mkApp {
|
|
drv = crabidy;
|
|
name = "cbd";
|
|
};
|
|
};
|
|
}
|
|
);
|
|
}
|