Embed the web UI in the aarch64 (Raspberry Pi) flake build

The static aarch64 crabidy-server now ships the browser UI. crane builds
the cbd-web wasm bundle with trunk, then stages it into the server's
`web-ui` feature (build.rs embeds cbd-web/dist).

- webSrc: a source variant that keeps cbd-web's non-cargo assets
  (index.html, style.css, Trunk.toml) that filterCargoSources drops,
  minus any stale prebuilt dist/.
- wasmBindgenCli: nixpkgs ships an older wasm-bindgen CLI and the dev
  shell lets trunk download the matching one at build time, which a
  sealed Nix build can't do — so pin an overridden CLI at 0.2.126 to
  match the wasm-bindgen crate.
- webBundle: buildTrunkPackage over a wasm32 toolchain; build from
  inside cbd-web (virtual workspace ⇒ trunk can't resolve the member
  from the root) and index.html-first so trunk's optional-valued
  --release doesn't swallow the positional.
- The aarch64 server drops --no-default-features (web-ui back on) and a
  preBuild stages the bundle into cbd-web/dist before the crate compiles.

Verified: nix build .#crabidy-server-aarch64 produces a static aarch64
ELF whose embedded index.html carries the real hashed wasm/js assets
(not the headless placeholder). Native .#crabidy stays headless.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Test User 2026-07-23 14:26:36 +02:00
parent 89d5fffd48
commit 5bcddb9027
2 changed files with 97 additions and 4 deletions

View File

@ -296,8 +296,11 @@ 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.
pitfalls of cross-compiling in a plain shell. The aarch64 server **includes
the embedded web UI**: the flake builds the `cbd-web` wasm bundle with trunk
(pinning a `wasm-bindgen` CLI that matches the crate) and stages it into the
server's `web-ui` feature. The native `.#crabidy` package stays headless; use
a normal `cargo build` there if you want 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

View File

@ -36,11 +36,93 @@
(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. Headless: --no-default-features drops the
# embedded web UI (its own wasm-bundle derivation is future work).
# embedded web UI. The aarch64 server (below) re-enables it and stages
# the wasm bundle.
workspaceBins = "-p crabidy-server -p cbd -p cbd-tui";
# --- 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);
@ -88,9 +170,17 @@
crossArgs = {
inherit src;
strictDeps = true;
cargoExtraArgs = "--locked --no-default-features -p crabidy-server";
# 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 are host tools.
nativeBuildInputs = [