diff --git a/generic/make-derivation.nix b/generic/make-derivation.nix index 372f4f7..8e86422 100644 --- a/generic/make-derivation.nix +++ b/generic/make-derivation.nix @@ -635,6 +635,12 @@ extendDerivation disallowedRequisites = [ ]; }); + toDevShell = let + originalArgs = deleteFixedOutputRelatedAttrs derivationArg; + toShell = import ./to-dev-shell.nix lib originalArgs; + shellFunc = f: if builtins.isFunction f then f stdenv else f; + in f: derivation (toShell (shellFunc f)); + inherit passthru overrideAttrs; inherit meta; } // diff --git a/generic/to-dev-shell.nix b/generic/to-dev-shell.nix new file mode 100644 index 0000000..f0c7538 --- /dev/null +++ b/generic/to-dev-shell.nix @@ -0,0 +1,64 @@ +lib: + +originalArgs: + +# A special kind of derivation that is only meant to be consumed by the +# nix-shell. +{ name ? if originalArgs ? name then "${originalArgs.name}-dev-shell" else "nix-shell" +, # a list of packages to add to the shell environment + packages ? [ ] +, # propagate all the inputs from the given derivations + inputsFrom ? [ ] +, buildInputs ? [ ] +, nativeBuildInputs ? [ ] +, propagatedBuildInputs ? [ ] +, propagatedNativeBuildInputs ? [ ] +, ... +}@attrs: +let + mergeInputs = name: + (originalArgs.${name} or [ ]) ++ + (attrs.${name} or [ ]) ++ + # 1. get all `{build,nativeBuild,...}Inputs` from the elements of `inputsFrom` + # 2. since that is a list of lists, `flatten` that into a regular list + # 3. filter out of the result everything that's in `inputsFrom` itself + # this leaves actual dependencies of the derivations in `inputsFrom`, but never the derivations themselves + (lib.subtractLists inputsFrom (lib.flatten (lib.catAttrs name inputsFrom))); + + rest = builtins.removeAttrs attrs [ + "name" + "packages" + "inputsFrom" + "buildInputs" + "nativeBuildInputs" + "propagatedBuildInputs" + "propagatedNativeBuildInputs" + "shellHook" + ]; +in { + inherit name; + + buildInputs = mergeInputs "buildInputs"; + nativeBuildInputs = packages ++ (mergeInputs "nativeBuildInputs"); + propagatedBuildInputs = mergeInputs "propagatedBuildInputs"; + propagatedNativeBuildInputs = mergeInputs "propagatedNativeBuildInputs"; + + shellHook = lib.concatStringsSep "\n" (lib.catAttrs "shellHook" + (lib.reverseList inputsFrom ++ [ attrs ])); + + phases = [ "buildPhase" ]; + + buildPhase = '' + { echo "------------------------------------------------------------"; + echo " WARNING: the existence of this path is not guaranteed."; + echo " It is an internal implementation detail for pkgs.mkShell."; + echo "------------------------------------------------------------"; + echo; + # Record all build inputs as runtime dependencies + export; + } >> "$out" + ''; + + preferLocalBuild = true; +} // rest +