Add a crane flake: native packages + static aarch64 cross build
`flake.nix` packages the binaries with crane, no Docker: - `nix build .#crabidy` / `nix profile install .#crabidy` — native cbd, cbd-tui, crabidy-server for any machine with Nix; `nix run .#cbd-tui`. - `nix build .#crabidy-server-aarch64` — a fully static aarch64 musl server (no glibc/loader dependency), so it runs on stock Raspberry Pi OS. Nix cross-compiles the Rust and the C deps (ALSA, aws-lc) hermetically on an x86_64 host; the isolated derivation avoids the host-linker contamination that plagues cross-linking in a plain devenv shell. The source filter keeps crabidy-core's *.proto (crane would otherwise drop it); builds are limited to the real bin crates with -p so the wasm cbd-web crate is never built for a host/aarch64 target. Packages are headless (--no-default-features) — the embedded web UI stays a normal cargo build. The legacy container `cross` path (Cross.toml + *-Dockerfile) is left as-is; the flake is the recommended cross path. README documents both. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d078e65a7d
commit
89d5fffd48
32
README.md
32
README.md
|
|
@ -271,6 +271,38 @@ Build the server with `--no-default-features` for a headless,
|
||||||
gRPC-only binary. See [cbd-web/README.md](cbd-web/README.md) for the
|
gRPC-only binary. See [cbd-web/README.md](cbd-web/README.md) for the
|
||||||
dev loop and details.
|
dev loop and details.
|
||||||
|
|
||||||
|
## Nix packages and cross-compiling
|
||||||
|
|
||||||
|
`flake.nix` (built with [crane](https://github.com/ipetkov/crane)) packages
|
||||||
|
the binaries as Nix derivations — for your own machines, and cross-compiled
|
||||||
|
for a Raspberry Pi. No Docker required.
|
||||||
|
|
||||||
|
Native — install on any machine with Nix:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix run .#cbd-tui # run without installing
|
||||||
|
nix build .#crabidy # cbd, cbd-tui, crabidy-server → ./result/bin
|
||||||
|
nix profile install .#crabidy # or github:OWNER/crabidy once pushed
|
||||||
|
```
|
||||||
|
|
||||||
|
Raspberry Pi (or any aarch64 Linux) — a fully **static musl** binary, so it
|
||||||
|
has no glibc-version or loader dependency and runs on stock Raspberry Pi OS
|
||||||
|
(bookworm and newer):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix build .#crabidy-server-aarch64
|
||||||
|
scp ./result/bin/crabidy-server pi:/usr/local/bin/
|
||||||
|
```
|
||||||
|
|
||||||
|
Nix cross-compiles the Rust *and* the C dependencies (ALSA, aws-lc)
|
||||||
|
hermetically on an x86_64 host — the isolated build avoids the host-linker
|
||||||
|
pitfalls of cross-compiling in a plain shell. The flake packages are headless
|
||||||
|
(no embedded web UI); use a normal `cargo build` if you need the bundle.
|
||||||
|
|
||||||
|
A container-based `cross` setup also exists (`Cross.toml` + the
|
||||||
|
`*-Dockerfile`s) for building against Debian's glibc, but the flake is the
|
||||||
|
recommended path.
|
||||||
|
|
||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
`cbd` and `cbd-tui` log to `~/.local/state/crabidy/` (daily files);
|
`cbd` and `cbd-tui` log to `~/.local/state/crabidy/` (daily files);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"crane": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1784564969,
|
||||||
|
"narHash": "sha256-TkTWNhJV/8Wk3czlbz4bwHZkFCaCHPsOy+oJe4PUiXg=",
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"rev": "7930f6c291de6f83c257839d434592aa085f290a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fenix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1784795840,
|
||||||
|
"narHash": "sha256-Z5cDTnG/+k7lNMMyuNH2RDWmSuGw2d3nV9AlVrpGnNE=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"rev": "85164e3aaadbc35cbbb4a9fef6d358b607da09fc",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1784555310,
|
||||||
|
"narHash": "sha256-/FCliTPgiuV1owejZFNx3Ch9irdvkOfOFl+HHZ+DrtM=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "421eebfd0ec7bccd4abe826ce62d7e6e83129493",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"crane": "crane",
|
||||||
|
"fenix": "fenix",
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-analyzer-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1784667699,
|
||||||
|
"narHash": "sha256-853teJQOgTTKRfNxcIJ53ziJOGNeg3c74PvQl5l61Jc=",
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"rev": "1174734d9c6453d13d2b5e3d578512c579ca37f1",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"ref": "nightly",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Only the real binary crates; never build cbd-web (a wasm crate) for a
|
||||||
|
# host or aarch64 target. Headless: --no-default-features drops the
|
||||||
|
# embedded web UI (its own wasm-bundle derivation is future work).
|
||||||
|
workspaceBins = "-p crabidy-server -p cbd -p cbd-tui";
|
||||||
|
|
||||||
|
# --- 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 ${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.
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.protobuf
|
||||||
|
pkgs.pkg-config
|
||||||
|
];
|
||||||
|
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;
|
||||||
|
cargoExtraArgs = "--locked --no-default-features -p crabidy-server";
|
||||||
|
CARGO_BUILD_TARGET = muslTarget;
|
||||||
|
|
||||||
|
# Build scripts / proc-macros compile for the build host; deps for the
|
||||||
|
# target use the cross toolchain. protoc + pkg-config are host tools.
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.protobuf
|
||||||
|
pkgs.pkg-config
|
||||||
|
];
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue