self: super: let inherit (super) lib mylib; # Merges an override into attrs. The override is attrs, or a function from # the original attrs to attrs, like the argument of nixpkgs' .override. applyOverride = override: attrs: attrs // lib.toFunction override attrs; explicitPackages = mylib.mapNixDir' (pname: path: path) [ ./. ]; automaticPackages = let root = /home/tv/sync/src; in lib.optionalAttrs (builtins.pathExists root) (lib.mapAttrs (pname: _type: root + "/${pname}") (lib.filterAttrs (pname: type: type == "directory" && builtins.pathExists (root + "/${pname}/Cargo.toml")) (builtins.readDir root))); # callPackage adds override and overrideDerivation to the returned attrset, # which crate2nix-package.nix would reject as unexpected arguments. callArgs = path: builtins.removeAttrs (self.callPackage path {}) [ "override" "overrideDerivation" ]; # A plan kept next to the package in hrm: pkgs/rust//Cargo.json. # Settings in the package file itself take precedence. hrmPlan = path: lib.optionalAttrs (builtins.pathExists (path + "/Cargo.json")) { resolvedJson = path + "/Cargo.json"; }; # Checks the JSON plan against the checkout's Cargo.lock and Cargo.toml. # These come from dir, not src, because cleanCargoSource drops Cargo.lock # next to a Cargo.json. planChecks = dir: lib.optionalAttrs (builtins.pathExists (dir + "/Cargo.lock")) { cargoLock = dir + "/Cargo.lock"; } // lib.optionalAttrs (builtins.pathExists (dir + "/Cargo.toml")) { cargoToml = dir + "/Cargo.toml"; }; in { # Builds a crate2nix workspace. crate2nixPackage = args: import ./lib/crate2nix-package.nix ({ inherit applyOverride; pkgs = self; } // args); # Applied to our own crates: debug builds, but dependencies in release. rustDevCrateAttrs = args: { release = false; codegenUnits = 256; extraRustcOpts = args.extraRustcOpts or [] ++ [ "-C debuginfo=line-tables-only" "-C link-arg=-fuse-ld=mold" ]; nativeBuildInputs = args.nativeBuildInputs or [] ++ [ self.mold ]; }; # Builds a crate from rustCrateArgs. merged with an override: attrs, # or a function from the stored arguments to attrs, e.g. # rustCrateWith "continuum" { features = [ "tor" ]; } # With {}, that's the package itself. rustCrateWith = pname: f: (self.crate2nixPackage (applyOverride f self.rustCrateArgs.${pname})).build; # crate2nixPackage arguments per package. Change them in a later overlay: # self: super: { # rustCrateArgs = super.rustCrateArgs // { # continuum = super.rustCrateArgs.continuum // { resolvedJson = ./continuum.json; }; # }; # } rustCrateArgs = lib.mapAttrs (pname: path: hrmPlan path // callArgs path) explicitPackages // lib.mapAttrs (pname: dir: let src = self.cleanCargoSource pname dir; in if explicitPackages ? ${pname} then assert mylib.debug "pkgs/rust: overriding ${pname}.src with ${mylib.pretty dir}"; hrmPlan explicitPackages.${pname} // callArgs explicitPackages.${pname} // { inherit src; } // planChecks dir else assert mylib.debug "pkgs/rust: automatic package ${pname} from ${mylib.pretty dir}"; { name = pname; inherit src; } // planChecks dir ) automaticPackages; # Copies a Cargo workspace into the store, leaving out what the build # doesn't need. cleanCargoSource = name: src: builtins.path { inherit name; path = src; filter = path: type: !builtins.any lib.id [ (type == "directory" && builtins.elem (baseNameOf path) [ ".git" ".graveyard" ]) # Cargo.json is the resolved lock. (type == "regular" && baseNameOf path == "Cargo.lock" && builtins.pathExists (builtins.dirOf path + "/Cargo.json")) ]; }; } // lib.mapAttrs (pname: _path: assert mylib.debugIf (super ? ${pname}) "pkgs/rust: overriding ${pname}"; self.rustCrateWith pname {}) (explicitPackages // automaticPackages)