{ lib, config, stdenv, stdenvNoCC, jq, lndir, runtimeShell, shellcheck-minimal }: let inherit (lib) optionalAttrs warn; in rec { # Docs in doc/build-helpers/trivial-build-helpers.chapter.md # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommand runCommand = name: env: runCommandWith { stdenv = stdenvNoCC; runLocal = false; inherit name; derivationArgs = env; }; # Docs in doc/build-helpers/trivial-build-helpers.chapter.md # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommandLocal runCommandLocal = name: env: runCommandWith { stdenv = stdenvNoCC; runLocal = true; inherit name; derivationArgs = env; }; # Docs in doc/build-helpers/trivial-build-helpers.chapter.md # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommandCC runCommandCC = name: env: runCommandWith { stdenv = stdenv; runLocal = false; inherit name; derivationArgs = env; }; # `runCommandCCLocal` left out on purpose. # We shouldn’t force the user to have a cc in scope. # TODO: Move documentation for runCommandWith to the Nixpkgs manual /* Generalized version of the `runCommand`-variants which does customized behavior via a single attribute set passed as the first argument instead of having a lot of variants like `runCommand*`. Additionally it allows changing the used `stdenv` freely and has a more explicit approach to changing the arguments passed to `stdenv.mkDerivation`. */ runCommandWith = let # prevent infinite recursion for the default stdenv value defaultStdenv = stdenv; in { # which stdenv to use, defaults to a stdenv with a C compiler, pkgs.stdenv stdenv ? defaultStdenv # whether to build this derivation locally instead of substituting , runLocal ? false # extra arguments to pass to stdenv.mkDerivation , derivationArgs ? { } # name of the resulting derivation , name # TODO(@Artturin): enable strictDeps always }: buildCommand: stdenv.mkDerivation ({ enableParallelBuilding = true; inherit buildCommand name; passAsFile = [ "buildCommand" ] ++ (derivationArgs.passAsFile or [ ]); } // lib.optionalAttrs (!derivationArgs ? meta) { pos = let args = builtins.attrNames derivationArgs; in if builtins.length args > 0 then builtins.unsafeGetAttrPos (builtins.head args) derivationArgs else null; } // (lib.optionalAttrs runLocal { preferLocalBuild = true; allowSubstitutes = false; }) // builtins.removeAttrs derivationArgs [ "passAsFile" ]); # Docs in doc/build-helpers/trivial-build-helpers.chapter.md # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeTextFile writeTextFile = { name, text, executable ? false, destination ? "" , checkPhase ? "", meta ? { }, allowSubstitutes ? false , preferLocalBuild ? true, derivationArgs ? { } }: let matches = builtins.match "/bin/([^/]+)" destination; in runCommand name ({ inherit text executable checkPhase allowSubstitutes preferLocalBuild; passAsFile = [ "text" ] ++ derivationArgs.passAsFile or [ ]; meta = lib.optionalAttrs (executable && matches != null) { mainProgram = lib.head matches; } // meta // derivationArgs.meta or { }; } // removeAttrs derivationArgs [ "passAsFile" "meta" ]) '' target=$out${lib.escapeShellArg destination} mkdir -p "$(dirname "$target")" if [ -e "$textPath" ]; then mv "$textPath" "$target" else echo -n "$text" > "$target" fi if [ -n "$executable" ]; then chmod +x "$target" fi eval "$checkPhase" ''; # See doc/build-helpers/trivial-build-helpers.chapter.md # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing writeText = name: text: writeTextFile { inherit name text; }; # See doc/build-helpers/trivial-build-helpers.chapter.md # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing writeTextDir = path: text: writeTextFile { inherit text; name = builtins.baseNameOf path; destination = "/${path}"; }; # See doc/build-helpers/trivial-build-helpers.chapter.md # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing writeScript = name: text: writeTextFile { inherit name text; executable = true; }; # See doc/build-helpers/trivial-build-helpers.chapter.md # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing writeScriptBin = name: text: writeTextFile { inherit name text; executable = true; destination = "/bin/${name}"; }; # See doc/build-helpers/trivial-build-helpers.chapter.md # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing writeShellScript = name: text: writeTextFile { inherit name; executable = true; text = '' #!${runtimeShell} ${text} ''; checkPhase = '' ${stdenv.shellDryRun} "$target" ''; }; # See doc/build-helpers/trivial-build-helpers.chapter.md # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing writeShellScriptBin = name: text: writeTextFile { inherit name; executable = true; destination = "/bin/${name}"; text = '' #!${runtimeShell} ${text} ''; checkPhase = '' ${stdenv.shellDryRun} "$target" ''; meta.mainProgram = name; }; # TODO: move parameter documentation to the Nixpkgs manual # See doc/build-helpers/trivial-build-helpers.chapter.md # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeShellApplication writeShellApplication = { /* The name of the script to write. Type: String */ name, /* The shell script's text, not including a shebang. Type: String */ text, /* Inputs to add to the shell script's `$PATH` at runtime. Type: [String|Derivation] */ runtimeInputs ? [ ], /* Extra environment variables to set at runtime. Type: AttrSet */ runtimeEnv ? null, /* `stdenv.mkDerivation`'s `meta` argument. Type: AttrSet */ meta ? { }, /* The `checkPhase` to run. Defaults to `shellcheck` on supported platforms and `bash -n`. The script path will be given as `$target` in the `checkPhase`. Type: String */ checkPhase ? null, /* Checks to exclude when running `shellcheck`, e.g. `[ "SC2016" ]`. See for a list of checks. Type: [String] */ excludeShellChecks ? [ ], /* Extra command-line flags to pass to ShellCheck. Type: [String] */ extraShellCheckFlags ? [ ], /* Bash options to activate with `set -o` at the start of the script. Defaults to `[ "errexit" "nounset" "pipefail" ]`. Type: [String] */ bashOptions ? [ "errexit" "nounset" "pipefail" ], /* Extra arguments to pass to `stdenv.mkDerivation`. :::{.caution} Certain derivation attributes are used internally, overriding those could cause problems. ::: Type: AttrSet */ derivationArgs ? { }, }: writeTextFile { inherit name meta derivationArgs; executable = true; destination = "/bin/${name}"; allowSubstitutes = true; preferLocalBuild = false; text = '' #!${runtimeShell} ${lib.concatMapStringsSep "\n" (option: "set -o ${option}") bashOptions} '' + lib.optionalString (runtimeEnv != null) (lib.concatStrings (lib.mapAttrsToList (name: value: '' ${lib.toShellVar name value} export ${name} '') runtimeEnv)) + lib.optionalString (runtimeInputs != [ ]) '' export PATH="${lib.makeBinPath runtimeInputs}:$PATH" '' + '' ${text} ''; checkPhase = # GHC (=> shellcheck) isn't supported on some platforms (such as risc-v) # but we still want to use writeShellApplication on those platforms let shellcheckSupported = lib.meta.availableOn stdenv.buildPlatform shellcheck-minimal.compiler; excludeFlags = lib.optionals (excludeShellChecks != [ ]) [ "--exclude" (lib.concatStringsSep "," excludeShellChecks) ]; shellcheckCommand = lib.optionalString shellcheckSupported '' # use shellcheck which does not include docs # pandoc takes long to build and documentation isn't needed for just running the cli ${lib.getExe shellcheck-minimal} ${ lib.escapeShellArgs (excludeFlags ++ extraShellCheckFlags) } "$target" ''; in if checkPhase == null then '' runHook preCheck ${stdenv.shellDryRun} "$target" ${shellcheckCommand} runHook postCheck '' else checkPhase; }; # Create a C binary # TODO: add to writers? pkgs/build-support/writers writeCBin = pname: code: runCommandCC pname { inherit pname code; executable = true; passAsFile = [ "code" ]; # Pointless to do this on a remote machine. preferLocalBuild = true; allowSubstitutes = false; meta = { mainProgram = pname; }; } '' n=$out/bin/${pname} mkdir -p "$(dirname "$n")" mv "$codePath" code.c $CC -x c code.c -o "$n" ''; # TODO: deduplicate with documentation in doc/build-helpers/trivial-build-helpers.chapter.md # see also https://github.com/NixOS/nixpkgs/pull/249721 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-concatText /* concat a list of files to the nix store. The contents of files are added to the file in the store. Example: # Writes my-file to /nix/store/ concatTextFile { name = "my-file"; files = [ drv1 "${drv2}/path/to/file" ]; } See also the `concatText` helper function below. # Writes executable my-file to /nix/store//bin/my-file concatTextFile { name = "my-file"; files = [ drv1 "${drv2}/path/to/file" ]; executable = true; destination = "/bin/my-file"; } */ concatTextFile = { name # the name of the derivation , files, executable ? false # run chmod +x ? , destination ? "" # relative path appended to $out eg "/bin/foo" , checkPhase ? "" # syntax checks, e.g. for scripts , meta ? { } }: runCommandLocal name { inherit files executable checkPhase meta destination; } '' file=$out$destination mkdir -p "$(dirname "$file")" cat $files > "$file" if [ -n "$executable" ]; then chmod +x "$file" fi eval "$checkPhase" ''; # TODO: deduplicate with documentation in doc/build-helpers/trivial-build-helpers.chapter.md # see also https://github.com/NixOS/nixpkgs/pull/249721 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-concatText /* Writes a text file to nix store with no optional parameters available. Example: # Writes contents of files to /nix/store/ concatText "my-file" [ file1 file2 ] */ concatText = name: files: concatTextFile { inherit name files; }; # TODO: deduplicate with documentation in doc/build-helpers/trivial-build-helpers.chapter.md # see also https://github.com/NixOS/nixpkgs/pull/249721 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-concatText /* Writes a text file to nix store with and mark it as executable. Example: # Writes contents of files to /nix/store/ concatScript "my-file" [ file1 file2 ] */ concatScript = name: files: concatTextFile { inherit name files; executable = true; }; /* TODO: Deduplicate this documentation. More docs in doc/build-helpers/trivial-build-helpers.chapter.md See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-symlinkJoin Create a forest of symlinks to the files in `paths`. This creates a single derivation that replicates the directory structure of all the input paths. BEWARE: it may not "work right" when the passed paths contain symlinks to directories. Example: # adds symlinks of hello to current build. symlinkJoin { name = "myhello"; paths = [ pkgs.hello ]; } # adds symlinks of hello and stack to current build and prints "links added" symlinkJoin { name = "myexample"; paths = [ pkgs.hello pkgs.stack ]; postBuild = "echo links added"; } This creates a derivation with a directory structure like the following: /nix/store/sglsr5g079a5235hy29da3mq3hv8sjmm-myexample |-- bin | |-- hello -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10/bin/hello | `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/bin/stack `-- share |-- bash-completion | `-- completions | `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/bash-completion/completions/stack |-- fish | `-- vendor_completions.d | `-- stack.fish -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/fish/vendor_completions.d/stack.fish ... symlinkJoin and linkFarm are similar functions, but they output derivations with different structure. symlinkJoin is used to create a derivation with a familiar directory structure (top-level bin/, share/, etc), but with all actual files being symlinks to the files in the input derivations. symlinkJoin is used many places in nixpkgs to create a single derivation that appears to contain binaries, libraries, documentation, etc from multiple input derivations. linkFarm is instead used to create a simple derivation with symlinks to other derivations. A derivation created with linkFarm is often used in CI as a easy way to build multiple derivations at once. */ symlinkJoin = args_@{ name, paths, preferLocalBuild ? true , allowSubstitutes ? false, postBuild ? "", ... }: let args = removeAttrs args_ [ "name" "postBuild" ] // { inherit preferLocalBuild allowSubstitutes; passAsFile = [ "paths" ]; }; # pass the defaults in runCommand name args '' mkdir -p $out for i in $(cat $pathsPath); do ${lndir}/bin/lndir -silent $i $out done ${postBuild} ''; # TODO: move linkFarm docs to the Nixpkgs manual /* Quickly create a set of symlinks to derivations. This creates a simple derivation with symlinks to all inputs. entries can be a list of attribute sets like [ { name = "name" ; path = "/nix/store/..."; } ] or an attribute set name -> path like: { name = "/nix/store/..."; other = "/nix/store/..."; } Example: # Symlinks hello and stack paths in store to current $out/hello-test and # $out/foobar. linkFarm "myexample" [ { name = "hello-test"; path = pkgs.hello; } { name = "foobar"; path = pkgs.stack; } ] This creates a derivation with a directory structure like the following: /nix/store/qc5728m4sa344mbks99r3q05mymwm4rw-myexample |-- foobar -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1 `-- hello-test -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10 See the note on symlinkJoin for the difference between linkFarm and symlinkJoin. */ linkFarm = name: entries: let entries' = if (lib.isAttrs entries) then entries # We do this foldl to have last-wins semantics in case of repeated entries else if (lib.isList entries) then lib.foldl (a: b: a // { "${b.name}" = b.path; }) { } entries else throw "linkFarm entries must be either attrs or a list!"; linkCommands = lib.mapAttrsToList (name: path: '' mkdir -p "$(dirname ${lib.escapeShellArg "${name}"})" ln -s ${lib.escapeShellArg "${path}"} ${lib.escapeShellArg "${name}"} '') entries'; in runCommand name { preferLocalBuild = true; allowSubstitutes = false; passthru.entries = entries'; } '' mkdir -p $out cd $out ${lib.concatStrings linkCommands} ''; # TODO: move linkFarmFromDrvs docs to the Nixpkgs manual /* Easily create a linkFarm from a set of derivations. This calls linkFarm with a list of entries created from the list of input derivations. It turns each input derivation into an attribute set like { name = drv.name ; path = drv }, and passes this to linkFarm. Example: # Symlinks the hello, gcc, and ghc derivations in $out linkFarmFromDrvs "myexample" [ pkgs.hello pkgs.gcc pkgs.ghc ] This creates a derivation with a directory structure like the following: /nix/store/m3s6wkjy9c3wy830201bqsb91nk2yj8c-myexample |-- gcc-wrapper-9.2.0 -> /nix/store/fqhjxf9ii4w4gqcsx59fyw2vvj91486a-gcc-wrapper-9.2.0 |-- ghc-8.6.5 -> /nix/store/gnf3s07bglhbbk4y6m76sbh42siym0s6-ghc-8.6.5 `-- hello-2.10 -> /nix/store/k0ll91c4npk4lg8lqhx00glg2m735g74-hello-2.10 */ linkFarmFromDrvs = name: drvs: let mkEntryFromDrv = drv: { name = drv.name; path = drv; }; in linkFarm name (map mkEntryFromDrv drvs); # TODO: move onlyBin docs to the Nixpkgs manual /* Produce a derivation that links to the target derivation's `/bin`, and *only* `/bin`. This is useful when your favourite package doesn't have a separate bin output and other contents of the package's output (e.g. setup hooks) cause trouble when used in your environment. */ onlyBin = drv: runCommand "${drv.name}-only-bin" { } '' mkdir -p $out ln -s ${lib.getBin drv}/bin $out/bin ''; # Docs in doc/builders/special/makesetuphook.section.md # See https://nixos.org/manual/nixpkgs/unstable/#sec-pkgs.makeSetupHook makeSetupHook = { name ? lib.warn "calling makeSetupHook without passing a name is deprecated." "hook", deps ? [ ] # hooks go in nativeBuildInput so these will be nativeBuildInput , propagatedBuildInputs ? [ ] # these will be buildInputs , depsTargetTargetPropagated ? [ ], meta ? { }, passthru ? { } , substitutions ? { } }: script: runCommand name (substitutions // { # TODO(@Artturin:) substitutions should be inside the env attrset # but users are likely passing non-substitution arguments through substitutions # turn off __structuredAttrs to unbreak substituteAll __structuredAttrs = false; inherit meta; inherit depsTargetTargetPropagated; propagatedBuildInputs = # remove list conditionals before 23.11 lib.warnIf (!lib.isList deps) "'deps' argument to makeSetupHook must be a list. content of deps: ${ toString deps }" (lib.warnIf (deps != [ ]) "'deps' argument to makeSetupHook is deprecated and will be removed in release 23.11., Please use propagatedBuildInputs instead. content of deps: ${ toString deps }" propagatedBuildInputs ++ (if lib.isList deps then deps else [ deps ])); strictDeps = true; # TODO 2023-01, no backport: simplify to inherit passthru; passthru = passthru // optionalAttrs (substitutions ? passthru) (warn "makeSetupHook (name = ${ lib.strings.escapeNixString name }): `substitutions.passthru` is deprecated. Please set `passthru` directly." substitutions.passthru); }) ('' mkdir -p $out/nix-support cp ${script} $out/nix-support/setup-hook recordPropagatedDependencies '' + lib.optionalString (substitutions != { }) '' substituteAll ${script} $out/nix-support/setup-hook ''); # Docs in doc/build-helpers/trivial-build-helpers.chapter.md # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeReferencesToFile # TODO: Convert to throw after Nixpkgs 24.05 branch-off. writeReferencesToFile = (if config.allowAliases then lib.warn else throw) "writeReferencesToFile is deprecated in favour of writeClosure" (path: writeClosure [ path ]); # Docs in doc/build-helpers/trivial-build-helpers.chapter.md # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeClosure writeClosure = paths: runCommand "runtime-deps" { # Get the cleaner exportReferencesGraph interface __structuredAttrs = true; exportReferencesGraph.graph = paths; nativeBuildInputs = [ jq ]; } '' jq -r ".graph | map(.path) | sort | .[]" "$NIX_ATTRS_JSON_FILE" > "$out" ''; # Docs in doc/build-helpers/trivial-build-helpers.chapter.md # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeDirectReferencesToFile writeDirectReferencesToFile = path: runCommand "runtime-references" { exportReferencesGraph = [ "graph" path ]; inherit path; } '' touch ./references while read p; do read dummy read nrRefs if [[ $p == $path ]]; then for ((i = 0; i < nrRefs; i++)); do read ref; echo $ref >>./references done else for ((i = 0; i < nrRefs; i++)); do read ref; done fi done < graph sort ./references >$out ''; # TODO: move writeStringReferencesToFile docs to the Nixpkgs manual /* Extract a string's references to derivations and paths (its context) and write them to a text file, removing the input string itself from the dependency graph. This is useful when you want to make a derivation depend on the string's references, but not its contents (to avoid unnecessary rebuilds, for example). Note that this only works as intended on Nix >= 2.3. */ writeStringReferencesToFile = string: /* The basic operation this performs is to copy the string context from `string` to a second string and wrap that string in a derivation. However, that alone is not enough, since nothing in the string refers to the output paths of the derivations/paths in its context, meaning they'll be considered build-time dependencies and removed from the wrapper derivation's closure. Putting the necessary output paths in the new string is however not very straightforward - the attrset returned by `getContext` contains only references to derivations' .drv-paths, not their output paths. In order to "convert" them, we try to extract the corresponding paths from the original string using regex. */ let # Taken from https://github.com/NixOS/nix/blob/130284b8508dad3c70e8160b15f3d62042fc730a/src/libutil/hash.cc#L84 nixHashChars = "0123456789abcdfghijklmnpqrsvwxyz"; context = builtins.getContext string; derivations = lib.filterAttrs (n: v: v ? outputs) context; # Objects copied from outside of the store, such as paths and # `builtins.fetch*`ed ones sources = lib.attrNames (lib.filterAttrs (n: v: v ? path) context); packages = lib.mapAttrs' (name: value: { inherit value; name = lib.head (builtins.match "${builtins.storeDir}/[${nixHashChars}]+-(.*).drv" name); }) derivations; # The syntax of output paths differs between outputs named `out` # and other, explicitly named ones. For explicitly named ones, # the output name is suffixed as `-name`, but `out` outputs # aren't suffixed at all, and thus aren't easily distinguished # from named output paths. Therefore, we find all the named ones # first so we can use them to remove false matches when looking # for `out` outputs (see the definition of `outputPaths`). namedOutputPaths = lib.flatten (lib.mapAttrsToList (name: value: (map (output: lib.filter lib.isList (builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name}-${output})" string)) (lib.remove "out" value.outputs))) packages); # Only `out` outputs outputPaths = lib.flatten (lib.mapAttrsToList (name: value: if lib.elem "out" value.outputs then lib.filter (x: lib.isList x && # If the matched path is in `namedOutputPaths`, # it's a partial match of an output path where # the output name isn't `out` lib.all (o: !lib.hasPrefix (lib.head x) o) namedOutputPaths) (builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name})" string) else [ ]) packages); allPaths = lib.concatStringsSep "\n" (lib.unique (sources ++ namedOutputPaths ++ outputPaths)); allPathsWithContext = builtins.appendContext allPaths context; in if builtins ? getContext then writeText "string-references" allPathsWithContext else writeDirectReferencesToFile (writeText "string-file" string); # Docs in doc/build-helpers/fetchers.chapter.md # See https://nixos.org/manual/nixpkgs/unstable/#requirefile requireFile = { name ? null, sha256 ? null, sha1 ? null, hash ? null , url ? null, message ? null, hashMode ? "flat" }: assert (message != null) || (url != null); assert (sha256 != null) || (sha1 != null) || (hash != null); assert (name != null) || (url != null); let msg = if message != null then message else '' Unfortunately, we cannot download file ${name_} automatically. Please go to ${url} to download it yourself, and add it to the Nix store using either nix-store --add-fixed ${hashAlgo} ${name_} or nix-prefetch-url --type ${hashAlgo} file:///path/to/${name_} ''; hashAlgo = if hash != null then (builtins.head (lib.strings.splitString "-" hash)) else if sha256 != null then "sha256" else "sha1"; hashAlgo_ = if hash != null then "" else hashAlgo; hash_ = if hash != null then hash else if sha256 != null then sha256 else sha1; name_ = if name == null then baseNameOf (toString url) else name; in stdenvNoCC.mkDerivation { name = name_; outputHashMode = hashMode; outputHashAlgo = hashAlgo_; outputHash = hash_; preferLocalBuild = true; allowSubstitutes = false; builder = writeScript "restrict-message" '' source ${stdenvNoCC}/setup cat <<_EOF_ *** ${msg} *** _EOF_ exit 1 ''; }; # TODO: move copyPathToStore docs to the Nixpkgs manual /* Copy a path to the Nix store. Nix automatically copies files to the store before stringifying paths. If you need the store path of a file, ${copyPathToStore } can be shortened to ${}. */ copyPathToStore = builtins.filterSource (p: t: true); # TODO: move copyPathsToStore docs to the Nixpkgs manual # Copy a list of paths to the Nix store. copyPathsToStore = builtins.map copyPathToStore; # TODO: move applyPatches docs to the Nixpkgs manual /* Applies a list of patches to a source directory. Example: # Patching nixpkgs: applyPatches { src = pkgs.path; patches = [ (pkgs.fetchpatch { url = "https://github.com/NixOS/nixpkgs/commit/1f770d20550a413e508e081ddc08464e9d08ba3d.patch"; sha256 = "1nlzx171y3r3jbk0qhvnl711kmdk57jlq4na8f8bs8wz2pbffymr"; }) ]; } */ applyPatches = { src, name ? (if builtins.typeOf src == "path" then builtins.baseNameOf src else if builtins.isAttrs src && builtins.hasAttr "name" src then src.name else throw "applyPatches: please supply a `name` argument because a default name can only be computed when the `src` is a path or is an attribute set with a `name` attribute.") + "-patched", patches ? [ ], prePatch ? "", postPatch ? "", ... }@args: if patches == [ ] && prePatch == "" && postPatch == "" then src # nothing to do, so use original src to avoid additional drv else stdenvNoCC.mkDerivation ({ inherit name src patches prePatch postPatch; preferLocalBuild = true; allowSubstitutes = false; phases = "unpackPhase patchPhase installPhase"; installPhase = "cp -R ./ $out"; } # Carry `meta` information from the underlying `src` if present. // (optionalAttrs (src ? meta) { inherit (src) meta; }) // (removeAttrs args [ "src" "name" "patches" "prePatch" "postPatch" ])); # TODO: move docs to Nixpkgs manual # An immutable file in the store with a length of 0 bytes. emptyFile = runCommand "empty-file" { outputHashAlgo = "sha256"; outputHashMode = "recursive"; outputHash = "0ip26j2h11n1kgkz36rl4akv694yz65hr72q4kv4b3lxcbi65b3p"; preferLocalBuild = true; } "touch $out"; # TODO: move docs to Nixpkgs manual # An immutable empty directory in the store. emptyDirectory = runCommand "empty-directory" { outputHashAlgo = "sha256"; outputHashMode = "recursive"; outputHash = "0sjjj9z1dhilhpc8pq4154czrb79z9cm044jvn75kxcjv6v5l2m5"; preferLocalBuild = true; } "mkdir $out"; }