# buildEnv creates a tree of symlinks to the specified paths. This is # a fork of the hardcoded buildEnv in the Nix distribution. { buildPackages, runCommand, lib, substituteAll, writeClosure, }: let builder = substituteAll { src = ./builder.pl; inherit (builtins) storeDir; }; in lib.makeOverridable ( { name, # The manifest file (if any). A symlink $out/manifest will be # created to it. manifest ? "", # The paths to symlink. paths, # Whether to ignore collisions or abort. ignoreCollisions ? false, # Whether to include closures of all input paths. includeClosures ? false, # If there is a collision, check whether the contents and permissions match # and only if not, throw a collision error. checkCollisionContents ? true, # The paths (relative to each element of `paths') that we want to # symlink (e.g., ["/bin"]). Any file not inside any of the # directories in the list is not symlinked. pathsToLink ? [ "/" ], # The package outputs to include. By default, only the default # output is included. extraOutputsToInstall ? [ ], # Root the result in directory "$out${extraPrefix}", e.g. "/share". extraPrefix ? "", # Shell commands to run after building the symlink tree. postBuild ? "", # Additional inputs nativeBuildInputs ? [ ], # Handy e.g. if using makeWrapper in `postBuild`. buildInputs ? [ ], passthru ? { }, meta ? { }, }: let chosenOutputs = map (drv: { paths = # First add the usual output(s): respect if user has chosen explicitly, # and otherwise use `meta.outputsToInstall`. The attribute is guaranteed # to exist in mkDerivation-created cases. The other cases (e.g. runCommand) # aren't expected to have multiple outputs. ( if (!drv ? outputSpecified || !drv.outputSpecified) && drv.meta.outputsToInstall or null != null then map (outName: drv.${outName}) drv.meta.outputsToInstall else [ drv ] ) # Add any extra outputs specified by the caller of `buildEnv`. ++ lib.filter (p: p != null) (builtins.map (outName: drv.${outName} or null) extraOutputsToInstall); priority = drv.meta.priority or lib.meta.defaultPriority; }) paths; pathsForClosure = lib.pipe chosenOutputs [ (map (p: p.paths)) lib.flatten (lib.remove null) ]; in runCommand name rec { inherit manifest ignoreCollisions checkCollisionContents passthru meta pathsToLink extraPrefix postBuild nativeBuildInputs buildInputs ; pkgs = builtins.toJSON chosenOutputs; extraPathsFrom = lib.optional includeClosures (writeClosure pathsForClosure); preferLocalBuild = true; allowSubstitutes = false; # XXX: The size is somewhat arbitrary passAsFile = if builtins.stringLength pkgs >= 128 * 1024 then [ "pkgs" ] else [ ]; } '' ${buildPackages.perl}/bin/perl -w ${builder} eval "$postBuild" '' )