{ inputs = { nixpkgs.url = github:nixos/nixpkgs; nix-systems = { url = github:nix-systems/default; }; flake-utils = { url = github:numtide/flake-utils; inputs.systems.follows = "nix-systems"; }; rust-overlay = { url = github:oxalica/rust-overlay; inputs.nixpkgs.follows = "nixpkgs"; }; crane = { url = "github:ipetkov/crane"; }; }; outputs = { self, flake-utils, ... }@inputs: flake-utils.lib.eachDefaultSystem (system: let pkgs = import inputs.nixpkgs { inherit system; overlays = [ inputs.rust-overlay.overlays.default ]; }; rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; craneLib = (inputs.crane.mkLib pkgs).overrideToolchain rustToolchain; cargoMeta = craneLib.crateNameFromCargoToml { cargoToml = ./crates/server/Cargo.toml; }; commonEnv = { LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; }; nightlyRustFlags = [ # TODO this should be in a config file (by profile, maybe not in released software?), not in environment; also want stabilized #dev #waiting #ecosystem/rust #severity/low #urgency/low # background: "-Zrandomize-layout" ]; commonNightlyEnv = { RUSTFLAGS = pkgs.lib.strings.concatStringsSep " " nightlyRustFlags; }; miriFlags = [ ## necessary # rkyv v0.8.10 does not fit the assumptions of the Stacked Borrows checker; Tree Borrows seems to considered less like actual Rust? #ecosystem # TODO this should be in a config file, not in environment #waiting #ecosystem/miri #severity/low #urgency/low "-Zmiri-tree-borrows" ## optional # detect more alignment issues "-Zmiri-symbolic-alignment-check" # detect more pointer issues "-Zmiri-strict-provenance" # simulate a larger computer, so we expose more concurrency issues "-Zmiri-num-cpus=16" # test more nondeterministic paths "-Zmiri-many-seeds=..8" ]; miriEnv = { MIRIFLAGS = pkgs.lib.strings.concatStringsSep " " miriFlags; }; src = craneLib.cleanCargoSource ./.; commonArgs = commonEnv // { inherit src; strictDeps = true; nativeBuildInputs = with pkgs; [ pkg-config clang ]; buildInputs = with pkgs; [ liburing ]; }; cargoArtifacts = craneLib.buildDepsOnly (commonArgs); individualCrateArgs = commonArgs // { inherit cargoArtifacts; inherit (craneLib.crateNameFromCargoToml { inherit src; }) version; # NOTE: we disable tests since we'll run them all via cargo-nextest doCheck = false; }; fileSetForCrate = crate: pkgs.lib.fileset.toSource { root = ./.; fileset = pkgs.lib.fileset.unions [ (craneLib.fileset.cargoTomlAndLock ./.) # TODO maybe use craneLib.fileset.commonCargoSources on all ./crates/arbitrary-arrow ./crates/backend-rocksdb ./crates/index-format-v1 ./crates/kanto ./crates/key-format-v1 ./crates/maybe-tracing ./crates/meta-format-v1 ./crates/protocol-postgres ./crates/record-format-v1 ./crates/rocky ./crates/testutil ./crates/tunables # These are undesirable, but cargo fails to start if a workspace-members glob doesn't match anything. ./task/lint-unimplemented-sql ./task/lint-unique-error-codes (craneLib.fileset.commonCargoSources crate) ]; }; crate-kanto-server = craneLib.buildPackage (individualCrateArgs // { inherit (cargoMeta) pname version; cargoExtraArgs = "-p kanto-server"; src = fileSetForCrate ./crates/server; # We'll run workspace-wide nextest instead. doCheck = false; }); devShellPackages = with pkgs; [ nixpkgs-fmt taplo rust-analyzer cargo-deny cargo-shear cargo-nextest cargo-llvm-cov cargo-mutants cargo-spellcheck typos typos-lsp mdbook valgrind cargo-valgrind rr # used for `llvm-symbolizer` for libllvm ]; in rec { # `nix build` packages = { inherit crate-kanto-server; default = crate-kanto-server; doc-manual = let src = pkgs.lib.fileset.toSource { root = ./.; fileset = pkgs.lib.fileset.unions [ ./doc/manual ]; }; in pkgs.runCommand "kantodb-manual" { } '' # TODO mdbook breaks when source is read-only #waiting #ecosystem/mdbook cp --recursive --no-dereference --preserve=links --no-preserve=mode -- "${src}/doc/manual" /tmp/mdbook-build "${pkgs.mdbook}/bin/mdbook" build --dest-dir "$out" "/tmp/mdbook-build" ''; doc-developer-guide = let src = pkgs.lib.fileset.toSource { root = ./.; fileset = pkgs.lib.fileset.unions [ ./doc/dev ]; }; in pkgs.runCommand "kantodb-developer-guide" { } '' # TODO mdbook breaks when source is read-only #waiting #ecosystem/mdbook cp --recursive --no-dereference --preserve=links --no-preserve=mode -- "${src}/doc/dev" /tmp/mdbook-build "${pkgs.mdbook}/bin/mdbook" build --dest-dir "$out" "/tmp/mdbook-build" ''; }; # `nix run` apps = rec { kantodb = flake-utils.lib.mkApp { drv = crate-kanto-server; }; default = kantodb; }; # `nix flake check` checks = { inherit crate-kanto-server; clippy = craneLib.cargoClippy (commonArgs // { inherit cargoArtifacts; cargoClippyExtraArgs = "--all-targets -- --deny warnings"; }); rustdoc = craneLib.cargoDoc (commonArgs // { inherit cargoArtifacts; }); lint-rustfmt = let rustToolchain = (p: p.rust-bin.nightly.latest.default); craneLibNightly = (inputs.crane.mkLib pkgs).overrideToolchain rustToolchain; in craneLibNightly.cargoFmt { inherit src; rustFmtExtraArgs = "--unstable-features --config-path=./rustfmt-unstable.toml"; }; lint-cargo-deny = craneLib.cargoDeny { inherit src; }; nextest = craneLib.cargoNextest (commonArgs // { inherit cargoArtifacts; partitions = 10; partitionType = "hash"; }); # TODO nextest does not support `cargo test --doc`, so run it separately #ecosystem doctest = craneLib.cargoDocTest (individualCrateArgs // { doCheck = true; }); lint-toml-fmt = craneLib.taploFmt { src = pkgs.lib.sources.sourceFilesBySuffices src [ ".toml" ]; taploExtraArgs = "--config ./taplo.toml --diff"; }; coverage-llvm = craneLib.cargoLlvmCov (commonArgs // { inherit cargoArtifacts; }); }; # `nix develop` devShells.default = craneLib.devShell (commonEnv // { inputsFrom = [ crate-kanto-server ]; packages = devShellPackages; }); devShells.fuzz = let rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain-fuzz.toml; craneLib = (inputs.crane.mkLib pkgs).overrideToolchain rustToolchain; in craneLib.devShell (commonEnv // commonNightlyEnv // { inputsFrom = [ crate-kanto-server ]; packages = devShellPackages ++ (with pkgs; [ cargo-fuzz libllvm ]); # TODO `cargo-fuzz` fails to build or is very slow with lto #waiting #ecosystem/cargo-fuzz CARGO_PROFILE_RELEASE_LTO = "false"; # TODO hopefully speed up `cargo fuzz build` #waiting #ecosystem/cargo-fuzz CARGO_INCREMENTAL = "0"; }); devShells.miri = let rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain-miri.toml; craneLib = (inputs.crane.mkLib pkgs).overrideToolchain rustToolchain; in craneLib.devShell (commonEnv // commonNightlyEnv // miriEnv // { inputsFrom = [ crate-kanto-server ]; packages = with pkgs; [ cargo-nextest ]; }); }); }