{ description = "RDBMS Playground — Rust TUI dev environment + reproducible build"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; }; flake-utils.url = "github:numtide/flake-utils"; }; outputs = { self, nixpkgs, rust-overlay, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; overlays = [ (import rust-overlay) ]; }; # Single source of the Rust toolchain: the rustup toolchain file. # rust-overlay provisions the exact channel + components declared there, # so the dev shell and the build package share one pinned toolchain. rust = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; # Read the package version straight from Cargo.toml so it never drifts # from the crate metadata (no hand-maintained duplicate here). cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); # musl-targeting C compiler for the static release build: rusqlite's # `bundled` SQLite is compiled from C, so a `--target …-musl` cargo build # needs a musl `cc` for that C, plus a musl linker. `targetPrefix` is # "x86_64-unknown-linux-musl-", so the wrapped binary is # `${muslCC}/bin/x86_64-unknown-linux-musl-cc`. muslCC = pkgs.pkgsCross.musl64.stdenv.cc; # System build inputs are deliberately tiny — this is a pure-Rust TUI: # * libsqlite3-sys is built with the `bundled` feature, so SQLite is # compiled from vendored C. That needs a C compiler, which the # stdenv provides automatically (no entry required here). # * arboard's clipboard backend is `x11rb` — a pure-Rust socket XCB # client. It links no C X11 libraries, so none appear below. A live # X server is only needed at *runtime* to copy; headless sessions # fall back to OSC 52. # If a future dependency introduces a pkg-config / native-lib link, add # it here (and document why) rather than leaking it into the host env. nativeBuildInputs = [ ]; buildInputs = [ ]; # `nix build` → the release binary, built reproducibly from the pinned # toolchain and the committed Cargo.lock (importCargoLock fetches each # dependency by its lockfile checksum — offline, no cargoHash to churn). # CI's release job consumes this artifact; the gate's tests run # separately via `nix develop -c cargo test` (see below), so the package # build skips the suite — the nix sandbox has no HOME/X server and would # fight the project-dirs / clipboard paths the tests touch. rdbms-playground = pkgs.rustPlatform.buildRustPackage { pname = cargoToml.package.name; version = cargoToml.package.version; src = ./.; cargoLock.lockFile = ./Cargo.lock; inherit nativeBuildInputs buildInputs; doCheck = false; }; in { packages.default = rdbms-playground; packages.rdbms-playground = rdbms-playground; devShells.default = pkgs.mkShell { inherit buildInputs; nativeBuildInputs = nativeBuildInputs ++ [ rust # Dev-disk maintenance: cargo never garbage-collects stale per-hash # build artifacts, so target/ creeps into the tens of GB (see # CLAUDE.md "Build hygiene"). cargo-sweep prunes them; run it # periodically between milestones. pkgs.cargo-sweep # musl cc/linker for the static release build (see muslCC above). muslCC ]; # Point cargo's musl target at the musl cc for both the bundled-C # compile (CC_, consumed by the `cc` crate) and the final link # (CARGO_TARGET__LINKER). Harmless for normal glibc builds — # these only take effect when building `--target x86_64-…-musl`. shellHook = '' export CC_x86_64_unknown_linux_musl="${muslCC}/bin/${muslCC.targetPrefix}cc" export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER="${muslCC}/bin/${muslCC.targetPrefix}cc" echo "RDBMS Playground dev shell ($(uname -s))" echo " rust: $(rustc --version | cut -d' ' -f1-2)" echo " cargo: $(cargo --version | cut -d' ' -f1-2)" ''; }; }); }