{ pkgs, lib, depot, ... }: { mkFeaturePowerset = { crateName, features, override ? { } }: let powerset = xs: let addElement = set: element: set ++ map (e: [ element ] ++ e) set; in lib.foldl' addElement [ [ ] ] xs; in lib.listToAttrs (map (featuresPowerset: { name = if featuresPowerset != [ ] then "with-features-${lib.concatStringsSep "-" featuresPowerset}" else "no-features"; value = depot.tvix.crates.workspaceMembers.${crateName}.build.override (old: { runTests = true; features = featuresPowerset; } // (if lib.isFunction override then override old else override) ); }) (powerset features)); # Filters the given source, only keeping files related to the build, preventing unnecessary rebuilds. # Includes src in the root, all other .rs files and optionally Cargo specific files. # Additional files to be included can be specified in extraFileset. filterRustCrateSrc = { root # The original src , extraFileset ? null # Additional filesets to include (e.g. fileFilter for proto files) , cargoSupport ? false }: lib.fileset.toSource { inherit root; fileset = lib.fileset.intersection (lib.fileset.fromSource root) # We build our final fileset from the original src (lib.fileset.unions ([ (lib.fileset.maybeMissing (root + "/src")) # src may be missing if the crate just has tests for example (lib.fileset.fileFilter (f: f.hasExt "rs") root) ] ++ lib.optionals cargoSupport [ (lib.fileset.fileFilter (f: f.name == "Cargo.toml") root) (lib.fileset.maybeMissing (root + "/Cargo.lock")) ] ++ lib.optional (extraFileset != null) extraFileset)); }; # A function which takes a pkgs instance and returns an overriden defaultCrateOverrides with support for tvix crates. # This can be used throughout the rest of the repo. defaultCrateOverridesForPkgs = pkgs: let commonDarwinDeps = with pkgs.darwin.apple_sdk.frameworks; [ Security SystemConfiguration ]; in pkgs.defaultCrateOverrides // { nar-bridge = prev: { src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; nix-compat = prev: { src = depot.tvix.utils.filterRustCrateSrc rec { root = prev.src.origSrc; extraFileset = root + "/testdata"; }; }; nix-compat-derive = prev: { src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; nix-compat-derive-tests = prev: { src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; tvix-build = prev: { src = depot.tvix.utils.filterRustCrateSrc rec { root = prev.src.origSrc; extraFileset = lib.fileset.fileFilter (f: f.hasExt "proto") root; }; PROTO_ROOT = depot.tvix.build.protos.protos; nativeBuildInputs = [ pkgs.protobuf ]; buildInputs = lib.optional pkgs.stdenv.isDarwin commonDarwinDeps; TVIX_BUILD_SANDBOX_SHELL = "${pkgs.pkgsStatic.busybox}/bin/sh"; }; tvix-castore = prev: { src = depot.tvix.utils.filterRustCrateSrc rec { root = prev.src.origSrc; extraFileset = lib.fileset.fileFilter (f: f.hasExt "proto") root; }; PROTO_ROOT = depot.tvix.castore.protos.protos; nativeBuildInputs = [ pkgs.protobuf ]; }; tvix-cli = prev: { src = depot.tvix.utils.filterRustCrateSrc rec { root = prev.src.origSrc; extraFileset = root + "/tests"; }; buildInputs = lib.optional pkgs.stdenv.isDarwin commonDarwinDeps; }; tvix-store = prev: { src = depot.tvix.utils.filterRustCrateSrc rec { root = prev.src.origSrc; extraFileset = lib.fileset.fileFilter (f: f.hasExt "proto") root; }; PROTO_ROOT = depot.tvix.store.protos.protos; nativeBuildInputs = [ pkgs.protobuf ]; # fuse-backend-rs uses DiskArbitration framework to handle mount/unmount on Darwin buildInputs = lib.optional pkgs.stdenv.isDarwin (commonDarwinDeps ++ pkgs.darwin.apple_sdk.frameworks.DiskArbitration); }; tvix-eval-builtin-macros = prev: { src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; tvix-eval = prev: { src = depot.tvix.utils.filterRustCrateSrc rec { root = prev.src.origSrc; extraFileset = root + "/proptest-regressions"; }; }; tvix-glue = prev: { src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; tvix-serde = prev: { src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; tvix-tracing = prev: { src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; }; # This creates an extraStep in CI to check whether the Cargo.nix file is up-to-date. mkCrate2nixCheck = path: # The path to the Cargo.nix to be checked. let relCrateRoot = lib.removePrefix "./" (builtins.dirOf (lib.path.removePrefix depot.path.origSrc path)); in { label = "crate2nix check for ${relCrateRoot}"; needsOutput = true; alwaysRun = true; command = pkgs.writeShellScript "crate2nix-check-for-${lib.replaceStrings [ "/" ] ["-"] relCrateRoot}" '' (cd $(git rev-parse --show-toplevel)/${relCrateRoot} && ${depot.tools.crate2nix-generate}/bin/crate2nix-generate && if [[ -n "$(git status --porcelain -unormal Cargo.nix)" ]]; then echo "----------------------------------------------------------------------------------------------------" echo "Cargo.nix needs to be updated, run 'mg run //tools/crate2nix-generate' in ${relCrateRoot}" echo "----------------------------------------------------------------------------------------------------" exit 1 fi ) ''; }; }