From b679bb78f591e0663e7b0aed41b8884a3680115d Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Wed, 21 Dec 2022 00:23:52 +0300 Subject: [PATCH] refactor: use nixpkgs' mkShell for rust devshells, dont create separate shells for each package --- .../builders/build-rust-package/default.nix | 24 ++- .../rust/builders/crane/default.nix | 39 ++--- src/subsystems/rust/builders/devshell.nix | 152 +++++------------- 3 files changed, 70 insertions(+), 145 deletions(-) diff --git a/src/subsystems/rust/builders/build-rust-package/default.nix b/src/subsystems/rust/builders/build-rust-package/default.nix index 95d61a52..530efe49 100644 --- a/src/subsystems/rust/builders/build-rust-package/default.nix +++ b/src/subsystems/rust/builders/build-rust-package/default.nix @@ -71,27 +71,23 @@ args = buildArgs; }); - mkShellForPkg = pkg: - pkgs.callPackage ../devshell.nix { - inherit externals; - drv = pkg; - }; - allPackages = l.mapAttrs (name: version: {"${version}" = buildPackage name version;}) args.packages; - allDevshells = - l.mapAttrs - (name: version: mkShellForPkg allPackages.${name}.${version}) + allPackagesList = + l.mapAttrsToList + (name: version: allPackages.${name}.${version}) args.packages; + shell = pkgs.callPackage ../devshell.nix { + name = "devshell"; + drvs = allPackagesList; + }; in { packages = allPackages; - devShells = - allDevshells - // { - default = allDevshells.${defaultPackageName}; - }; + devShells = { + default = shell; + }; }; } diff --git a/src/subsystems/rust/builders/crane/default.nix b/src/subsystems/rust/builders/crane/default.nix index f02463db..ddea6f33 100644 --- a/src/subsystems/rust/builders/crane/default.nix +++ b/src/subsystems/rust/builders/crane/default.nix @@ -131,35 +131,28 @@ in build; - mkShellForPkg = pkg: let - pkgDeps = pkg.passthru.dependencies; - depsShell = pkgs.callPackage ../devshell.nix { - inherit externals; - drv = pkgDeps; - }; - mainShell = pkgs.callPackage ../devshell.nix { - inherit externals; - drv = pkg; - }; - shell = depsShell.combineWith mainShell; - in - shell; - allPackages = l.mapAttrs (name: version: {"${version}" = buildPackage name version;}) args.packages; - allDevshells = - l.mapAttrs - (name: version: mkShellForPkg allPackages.${name}.${version}) - args.packages; + allPackagesList = l.flatten ( + l.mapAttrsToList + ( + name: version: let + pkg = allPackages.${name}.${version}; + in [pkg.passthru.dependencies pkg] + ) + args.packages + ); + shell = pkgs.callPackage ../devshell.nix { + name = "devshell"; + drvs = allPackagesList; + }; in { packages = allPackages; - devShells = - allDevshells - // { - default = allDevshells.${defaultPackageName}; - }; + devShells = { + default = shell; + }; }; } diff --git a/src/subsystems/rust/builders/devshell.nix b/src/subsystems/rust/builders/devshell.nix index 847fc35e..74cf67d1 100644 --- a/src/subsystems/rust/builders/devshell.nix +++ b/src/subsystems/rust/builders/devshell.nix @@ -1,129 +1,65 @@ { # args - drv, - # d2n - externals, + drvs, + name, # nixpkgs lib, - stdenv, libiconv, + mkShell, ... }: let l = lib // builtins; - # function to merge two devshells - mergeShellConfig = base: other: let - c = base.config; - oc = other.config; - i = base.imports or []; - oi = other.imports or []; - hasCConfig = config: (config ? language) && (config.language ? c); - in { - config = - c - // oc - // { - packages = l.unique ((c.packages or []) ++ (oc.packages or [])); - commands = l.unique ((c.commands or []) ++ (oc.commands or [])); - env = l.unique ((c.env or []) ++ (oc.env or [])); - devshell = - (c.devshell or {}) - // (oc.devshell or {}) - // { - startup = (c.devshell.startup or {}) // (oc.devshell.startup or {}); - }; - } - // l.optionalAttrs (hasCConfig c || hasCConfig oc) { - language.c = let - cConf = c.language.c or {}; - ocConf = oc.language.c or {}; - in { - compiler = ocConf.compiler or cConf.compiler; - libraries = - l.unique ((cConf.libraries or []) ++ (ocConf.libraries or [])); - includes = - l.unique ((cConf.includes or []) ++ (ocConf.includes or [])); - }; - }; - imports = l.unique (i ++ oi); - }; - # creates a shell from a config - mkShell = config: let - shell = (externals.devshell.makeShell {configuration = config;}).shell; - in - shell - // { - passthru.config = config; - combineWith = other: - mkShell (mergeShellConfig config other.passthru.config); - addConfig = otherConfig: - mkShell (mergeShellConfig config {config = otherConfig;}); - }; - # convenience utils for converting a nix attribute to a shell env - # TODO: we could probably replace this with something from nixpkgs? - toStr = v: - if l.isBool v - then l.boolToString v - else l.toString v; - toShellEnv = v: - if l.isList v - then "( ${l.concatStringsSep " " (l.map (v: ''"${toStr v}"'') v)} )" - else l.toString v; # illegal env names to be removed and not be added to the devshell illegalEnvNames = [ + "name" + "pname" + "version" "all" "args" "drvPath" + "drvAttrs" "outPath" "stdenv" "cargoArtifacts" "dream2nixVendorDir" "cargoVendorDir" ]; - isIllegalEnv = name: l.any (oname: name == oname) illegalEnvNames; - inputs = (drv.buildInputs or []) ++ (drv.nativeBuildInputs or []); - rustToolchain = drv.passthru.rustToolchain; - # the config we will use - conf = { - config = - { - packages = inputs; - commands = [ - { - package = rustToolchain.cargoHostTarget or rustToolchain.cargo; - name = "cargo"; - category = "rust"; - help = "Rust build tool"; - } - ]; - env = - # filter out attrsets, functions and illegal environment vars - l.filter - (env: (env != null) && (! isIllegalEnv env.name)) - ( - l.mapAttrsToList - ( - n: v: - if ! (l.isAttrs v || l.isFunction v) - then { - name = n; - value = toShellEnv v; - } - else null - ) - drv - ); - } - # only add c stuff *if* the stdenv has a c compiler - # if the user wants to use stdenvNoCC this allows them to do it easily - // l.optionalAttrs (drv.stdenv ? cc) { - language.c = { - compiler = drv.stdenv.cc; - libraries = inputs ++ (lib.optional stdenv.isDarwin libiconv); - includes = inputs; - }; - }; - imports = [externals.devshell.imports.c]; - }; + isIllegalEnv = name: l.elem name illegalEnvNames; + getEnvs = drv: + # filter out attrsets, functions and illegal environment vars + l.filterAttrs + (name: env: (env != null) && (! isIllegalEnv name)) + ( + l.mapAttrs + ( + n: v: + if ! (l.isAttrs v || l.isFunction v) + then v + else null + ) + drv + ); + combineEnvs = envs: + l.foldl' + ( + all: env: + all + // env + // { + packages = (all.packages or []) ++ (env.packages or []); + buildInputs = (all.buildInputs or []) ++ (env.buildInputs or []); + nativeBuildInputs = (all.nativeBuildInputs or []) ++ (env.nativeBuildInputs or []); + propagatedBuildInputs = (all.propagatedBuildInputs or []) ++ (env.propagatedBuildInputs or []); + propagatedNativeBuildInputs = (all.propagatedNativeBuildInputs or []) ++ (env.propagatedNativeBuildInputs or []); + } + ) + {} + envs; + shellEnv = + (combineEnvs (l.map getEnvs drvs)) + // { + inherit name; + }; in - mkShell conf + (mkShell.override {stdenv = (l.head drvs).stdenv;}) shellEnv