mastodon: 4.3.1 -> 4.3.2 (#361487)
[NixPkgs.git] / pkgs / build-support / trivial-builders / default.nix
blob12a40a2d9602363e7f9ce08cfc4b3ba97a70e016
1 { lib, config, stdenv, stdenvNoCC, jq, lndir, runtimeShell, shellcheck-minimal }:
3 let
4   inherit (lib)
5     optionalAttrs
6     warn
7     ;
8 in
10 rec {
12   # Docs in doc/build-helpers/trivial-build-helpers.chapter.md
13   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommand
14   runCommand = name: env: runCommandWith {
15     stdenv = stdenvNoCC;
16     runLocal = false;
17     inherit name;
18     derivationArgs = env;
19   };
20   # Docs in doc/build-helpers/trivial-build-helpers.chapter.md
21   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommandLocal
22   runCommandLocal = name: env: runCommandWith {
23     stdenv = stdenvNoCC;
24     runLocal = true;
25     inherit name;
26     derivationArgs = env;
27   };
28   # Docs in doc/build-helpers/trivial-build-helpers.chapter.md
29   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommandCC
30   runCommandCC = name: env: runCommandWith {
31     stdenv = stdenv;
32     runLocal = false;
33     inherit name;
34     derivationArgs = env;
35   };
36   # `runCommandCCLocal` left out on purpose.
37   # We shouldn’t force the user to have a cc in scope.
39   # Docs in doc/build-helpers/trivial-build-helpers.chapter.md
40   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommandWith
41   runCommandWith =
42     let
43       # prevent infinite recursion for the default stdenv value
44       defaultStdenv = stdenv;
45     in
46     {
47       # which stdenv to use, defaults to a stdenv with a C compiler, pkgs.stdenv
48       stdenv ? defaultStdenv
49       # whether to build this derivation locally instead of substituting
50     , runLocal ? false
51       # extra arguments to pass to stdenv.mkDerivation
52     , derivationArgs ? { }
53       # name of the resulting derivation
54     , name
55       # TODO(@Artturin): enable strictDeps always
56     }: buildCommand:
57       stdenv.mkDerivation ({
58         enableParallelBuilding = true;
59         inherit buildCommand name;
60         passAsFile = [ "buildCommand" ]
61           ++ (derivationArgs.passAsFile or [ ]);
62       }
63       // lib.optionalAttrs (! derivationArgs?meta) {
64         pos = let args = builtins.attrNames derivationArgs; in
65           if builtins.length args > 0
66           then builtins.unsafeGetAttrPos (builtins.head args) derivationArgs
67           else null;
68       }
69       // (lib.optionalAttrs runLocal {
70         preferLocalBuild = true;
71         allowSubstitutes = false;
72       })
73       // builtins.removeAttrs derivationArgs [ "passAsFile" ]);
76   # Docs in doc/build-helpers/trivial-build-helpers.chapter.md
77   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeTextFile
78   writeTextFile =
79     { name
80     , text
81     , executable ? false
82     , destination ? ""
83     , checkPhase ? ""
84     , meta ? { }
85     , passthru ? { }
86     , allowSubstitutes ? false
87     , preferLocalBuild ? true
88     , derivationArgs ? { }
89     }:
90     assert lib.assertMsg (destination != "" -> (lib.hasPrefix "/" destination && destination != "/")) ''
91       destination must be an absolute path, relative to the derivation's out path,
92       got '${destination}' instead.
94       Ensure that the path starts with a / and specifies at least the filename.
95     '';
97     let
98       matches = builtins.match "/bin/([^/]+)" destination;
99     in
100     runCommand name
101       ({
102         inherit text executable checkPhase allowSubstitutes preferLocalBuild;
103         passAsFile = [ "text" ]
104           ++ derivationArgs.passAsFile or [ ];
105         meta = lib.optionalAttrs (executable && matches != null)
106           {
107             mainProgram = lib.head matches;
108           } // meta // derivationArgs.meta or {};
109         passthru = passthru // derivationArgs.passthru or {};
110       } // removeAttrs derivationArgs [ "passAsFile" "meta" "passthru" ])
111       ''
112         target=$out${lib.escapeShellArg destination}
113         mkdir -p "$(dirname "$target")"
115         if [ -e "$textPath" ]; then
116           mv "$textPath" "$target"
117         else
118           echo -n "$text" > "$target"
119         fi
121         if [ -n "$executable" ]; then
122           chmod +x "$target"
123         fi
125         eval "$checkPhase"
126       '';
128   # See doc/build-helpers/trivial-build-helpers.chapter.md
129   # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing
130   writeText = name: text:
131     # TODO: To fully deprecate, replace the assertion with `lib.isString` and remove the warning
132     assert lib.assertMsg (lib.strings.isConvertibleWithToString text) ''
133       pkgs.writeText ${lib.strings.escapeNixString name}: The second argument should be a string, but it's a ${builtins.typeOf text} instead.'';
134     lib.warnIf (! lib.isString text) ''
135       pkgs.writeText ${lib.strings.escapeNixString name}: The second argument should be a string, but it's a ${builtins.typeOf text} instead, which is deprecated. Use `toString` to convert the value to a string first.''
136     writeTextFile { inherit name text; };
138   # See doc/build-helpers/trivial-build-helpers.chapter.md
139   # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing
140   writeTextDir = path: text: writeTextFile {
141     inherit text;
142     name = builtins.baseNameOf path;
143     destination = "/${path}";
144   };
146   # See doc/build-helpers/trivial-build-helpers.chapter.md
147   # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing
148   writeScript = name: text: writeTextFile { inherit name text; executable = true; };
150   # See doc/build-helpers/trivial-build-helpers.chapter.md
151   # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing
152   writeScriptBin = name: text: writeTextFile {
153     inherit name text;
154     executable = true;
155     destination = "/bin/${name}";
156   };
158   # See doc/build-helpers/trivial-build-helpers.chapter.md
159   # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing
160   writeShellScript = name: text:
161     writeTextFile {
162       inherit name;
163       executable = true;
164       text = ''
165         #!${runtimeShell}
166         ${text}
167       '';
168       checkPhase = ''
169         ${stdenv.shellDryRun} "$target"
170       '';
171     };
173   # See doc/build-helpers/trivial-build-helpers.chapter.md
174   # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing
175   writeShellScriptBin = name: text:
176     writeTextFile {
177       inherit name;
178       executable = true;
179       destination = "/bin/${name}";
180       text = ''
181         #!${runtimeShell}
182         ${text}
183       '';
184       checkPhase = ''
185         ${stdenv.shellDryRun} "$target"
186       '';
187       meta.mainProgram = name;
188     };
190   # TODO: move parameter documentation to the Nixpkgs manual
191   # See doc/build-helpers/trivial-build-helpers.chapter.md
192   # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeShellApplication
193   writeShellApplication =
194     {
195       /*
196          The name of the script to write.
198          Type: String
199        */
200       name,
201       /*
202          The shell script's text, not including a shebang.
204          Type: String
205        */
206       text,
207       /*
208          Inputs to add to the shell script's `$PATH` at runtime.
210          Type: [String|Derivation]
211        */
212       runtimeInputs ? [ ],
213       /*
214          Extra environment variables to set at runtime.
216          Type: AttrSet
217        */
218       runtimeEnv ? null,
219       /*
220          `stdenv.mkDerivation`'s `meta` argument.
222          Type: AttrSet
223        */
224       meta ? { },
225       /*
226          `stdenv.mkDerivation`'s `passthru` argument.
228          Type: AttrSet
229        */
230       passthru ? { },
231       /*
232          The `checkPhase` to run. Defaults to `shellcheck` on supported
233          platforms and `bash -n`.
235          The script path will be given as `$target` in the `checkPhase`.
237          Type: String
238        */
239       checkPhase ? null,
240       /*
241          Checks to exclude when running `shellcheck`, e.g. `[ "SC2016" ]`.
243          See <https://www.shellcheck.net/wiki/> for a list of checks.
245          Type: [String]
246        */
247       excludeShellChecks ? [ ],
248       /*
249          Extra command-line flags to pass to ShellCheck.
251          Type: [String]
252        */
253       extraShellCheckFlags ? [ ],
254       /*
255          Bash options to activate with `set -o` at the start of the script.
257          Defaults to `[ "errexit" "nounset" "pipefail" ]`.
259          Type: [String]
260        */
261       bashOptions ? [ "errexit" "nounset" "pipefail" ],
262       /* Extra arguments to pass to `stdenv.mkDerivation`.
264          :::{.caution}
265          Certain derivation attributes are used internally,
266          overriding those could cause problems.
267          :::
269          Type: AttrSet
270        */
271       derivationArgs ? { },
272     }:
273     writeTextFile {
274       inherit name meta passthru derivationArgs;
275       executable = true;
276       destination = "/bin/${name}";
277       allowSubstitutes = true;
278       preferLocalBuild = false;
279       text = ''
280         #!${runtimeShell}
281         ${lib.concatMapStringsSep "\n" (option: "set -o ${option}") bashOptions}
282       '' + lib.optionalString (runtimeEnv != null)
283         (lib.concatStrings
284           (lib.mapAttrsToList
285             (name: value: ''
286               ${lib.toShellVar name value}
287               export ${name}
288             '')
289             runtimeEnv))
290       + lib.optionalString (runtimeInputs != [ ]) ''
292         export PATH="${lib.makeBinPath runtimeInputs}:$PATH"
293       '' + ''
295         ${text}
296       '';
298       checkPhase =
299         # GHC (=> shellcheck) isn't supported on some platforms (such as risc-v)
300         # but we still want to use writeShellApplication on those platforms
301         let
302           shellcheckSupported = lib.meta.availableOn stdenv.buildPlatform shellcheck-minimal.compiler;
303           excludeFlags = lib.optionals (excludeShellChecks != [ ]) [ "--exclude" (lib.concatStringsSep "," excludeShellChecks) ];
304           shellcheckCommand = lib.optionalString shellcheckSupported ''
305             # use shellcheck which does not include docs
306             # pandoc takes long to build and documentation isn't needed for just running the cli
307             ${lib.getExe shellcheck-minimal} ${lib.escapeShellArgs (excludeFlags ++ extraShellCheckFlags)} "$target"
308           '';
309         in
310         if checkPhase == null then ''
311           runHook preCheck
312           ${stdenv.shellDryRun} "$target"
313           ${shellcheckCommand}
314           runHook postCheck
315         ''
316         else checkPhase;
317     };
319   # Create a C binary
320   # TODO: add to writers? pkgs/build-support/writers
321   writeCBin = pname: code:
322     runCommandCC pname
323       {
324         inherit pname code;
325         executable = true;
326         passAsFile = [ "code" ];
327         # Pointless to do this on a remote machine.
328         preferLocalBuild = true;
329         allowSubstitutes = false;
330         meta = {
331           mainProgram = pname;
332         };
333       }
334       ''
335         n=$out/bin/${pname}
336         mkdir -p "$(dirname "$n")"
337         mv "$codePath" code.c
338         $CC -x c code.c -o "$n"
339       '';
341   # TODO: deduplicate with documentation in doc/build-helpers/trivial-build-helpers.chapter.md
342   #       see also https://github.com/NixOS/nixpkgs/pull/249721
343   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-concatText
344   /* concat a list of files to the nix store.
345     The contents of files are added to the file in the store.
347     Example:
350     # Writes my-file to /nix/store/<store path>
351     concatTextFile {
352       name = "my-file";
353       files = [ drv1 "${drv2}/path/to/file" ];
354     }
357     See also the `concatText` helper function below.
360     # Writes executable my-file to /nix/store/<store path>/bin/my-file
361     concatTextFile {
362       name = "my-file";
363       files = [ drv1 "${drv2}/path/to/file" ];
364       executable = true;
365       destination = "/bin/my-file";
366     }
369    */
370   concatTextFile =
371     { name # the name of the derivation
372     , files
373     , executable ? false # run chmod +x ?
374     , destination ? ""   # relative path appended to $out eg "/bin/foo"
375     , checkPhase ? ""    # syntax checks, e.g. for scripts
376     , meta ? { }
377     , passthru ? { }
378     }:
379     runCommandLocal name
380       { inherit files executable checkPhase meta passthru destination; }
381       ''
382         file=$out$destination
383         mkdir -p "$(dirname "$file")"
384         cat $files > "$file"
386         if [ -n "$executable" ]; then
387           chmod +x "$file"
388         fi
390         eval "$checkPhase"
391       '';
393   # TODO: deduplicate with documentation in doc/build-helpers/trivial-build-helpers.chapter.md
394   #       see also https://github.com/NixOS/nixpkgs/pull/249721
395   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-concatText
396   /*
397     Writes a text file to nix store with no optional parameters available.
399     Example:
402     # Writes contents of files to /nix/store/<store path>
403     concatText "my-file" [ file1 file2 ]
406   */
407   concatText = name: files: concatTextFile { inherit name files; };
409   # TODO: deduplicate with documentation in doc/build-helpers/trivial-build-helpers.chapter.md
410   #       see also https://github.com/NixOS/nixpkgs/pull/249721
411   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-concatText
412   /*
413     Writes a text file to nix store with and mark it as executable.
415     Example:
416     # Writes contents of files to /nix/store/<store path>
417     concatScript "my-file" [ file1 file2 ]
419   */
420   concatScript = name: files: concatTextFile { inherit name files; executable = true; };
423   /*
424     TODO: Deduplicate this documentation.
425     More docs in doc/build-helpers/trivial-build-helpers.chapter.md
426     See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-symlinkJoin
428     Create a forest of symlinks to the files in `paths`.
430     This creates a single derivation that replicates the directory structure
431     of all the input paths.
433     BEWARE: it may not "work right" when the passed paths contain symlinks to directories.
435     Example:
438     # adds symlinks of hello to current build.
439     symlinkJoin { name = "myhello"; paths = [ pkgs.hello ]; }
444     # adds symlinks of hello and stack to current build and prints "links added"
445     symlinkJoin { name = "myexample"; paths = [ pkgs.hello pkgs.stack ]; postBuild = "echo links added"; }
448     This creates a derivation with a directory structure like the following:
451     /nix/store/sglsr5g079a5235hy29da3mq3hv8sjmm-myexample
452     |-- bin
453     |   |-- hello -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10/bin/hello
454     |   `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/bin/stack
455     `-- share
456         |-- bash-completion
457         |   `-- completions
458         |       `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/bash-completion/completions/stack
459         |-- fish
460         |   `-- vendor_completions.d
461         |       `-- stack.fish -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/fish/vendor_completions.d/stack.fish
462     ...
465     symlinkJoin and linkFarm are similar functions, but they output
466     derivations with different structure.
468     symlinkJoin is used to create a derivation with a familiar directory
469     structure (top-level bin/, share/, etc), but with all actual files being symlinks to
470     the files in the input derivations.
472     symlinkJoin is used many places in nixpkgs to create a single derivation
473     that appears to contain binaries, libraries, documentation, etc from
474     multiple input derivations.
476     linkFarm is instead used to create a simple derivation with symlinks to
477     other derivations.  A derivation created with linkFarm is often used in CI
478     as a easy way to build multiple derivations at once.
479    */
480   symlinkJoin =
481     args_@{
482       name ?
483         assert lib.assertMsg (args_ ? pname && args_ ? version)
484           "symlinkJoin requires either a `name` OR `pname` and `version`";
485         "${args_.pname}-${args_.version}"
486     , paths
487     , preferLocalBuild ? true
488     , allowSubstitutes ? false
489     , postBuild ? ""
490     , ...
491     }:
492     let
493       args = removeAttrs args_ [ "name" "postBuild" ]
494         // {
495         inherit preferLocalBuild allowSubstitutes;
496         passAsFile = [ "paths" ];
497       }; # pass the defaults
498     in
499     runCommand name args
500       ''
501         mkdir -p $out
502         for i in $(cat $pathsPath); do
503           ${lndir}/bin/lndir -silent $i $out
504         done
505         ${postBuild}
506       '';
508   # TODO: move linkFarm docs to the Nixpkgs manual
509   /*
510     Quickly create a set of symlinks to derivations.
512     This creates a simple derivation with symlinks to all inputs.
514     entries can be a list of attribute sets like
516     [ { name = "name" ; path = "/nix/store/..."; } ]
519     or an attribute set name -> path like:
521     { name = "/nix/store/..."; other = "/nix/store/..."; }
524     Example:
526     # Symlinks hello and stack paths in store to current $out/hello-test and
527     # $out/foobar.
528     linkFarm "myexample" [ { name = "hello-test"; path = pkgs.hello; } { name = "foobar"; path = pkgs.stack; } ]
530     This creates a derivation with a directory structure like the following:
532     /nix/store/qc5728m4sa344mbks99r3q05mymwm4rw-myexample
533     |-- foobar -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1
534     `-- hello-test -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10
537     See the note on symlinkJoin for the difference between linkFarm and symlinkJoin.
538    */
539   linkFarm = name: entries:
540     let
541       entries' =
542         if (lib.isAttrs entries) then entries
543         # We do this foldl to have last-wins semantics in case of repeated entries
544         else if (lib.isList entries) then lib.foldl (a: b: a // { "${b.name}" = b.path; }) { } entries
545         else throw "linkFarm entries must be either attrs or a list!";
547       linkCommands = lib.mapAttrsToList
548         (name: path: ''
549           mkdir -p "$(dirname ${lib.escapeShellArg "${name}"})"
550           ln -s ${lib.escapeShellArg "${path}"} ${lib.escapeShellArg "${name}"}
551         '')
552         entries';
553     in
554     runCommand name
555       {
556         preferLocalBuild = true;
557         allowSubstitutes = false;
558         passthru.entries = entries';
559       } ''
560       mkdir -p $out
561       cd $out
562       ${lib.concatStrings linkCommands}
563     '';
565   # TODO: move linkFarmFromDrvs docs to the Nixpkgs manual
566   /*
567     Easily create a linkFarm from a set of derivations.
569     This calls linkFarm with a list of entries created from the list of input
570     derivations.  It turns each input derivation into an attribute set
571     like { name = drv.name ; path = drv }, and passes this to linkFarm.
573     Example:
575     # Symlinks the hello, gcc, and ghc derivations in $out
576     linkFarmFromDrvs "myexample" [ pkgs.hello pkgs.gcc pkgs.ghc ]
578     This creates a derivation with a directory structure like the following:
581     /nix/store/m3s6wkjy9c3wy830201bqsb91nk2yj8c-myexample
582     |-- gcc-wrapper-9.2.0 -> /nix/store/fqhjxf9ii4w4gqcsx59fyw2vvj91486a-gcc-wrapper-9.2.0
583     |-- ghc-8.6.5 -> /nix/store/gnf3s07bglhbbk4y6m76sbh42siym0s6-ghc-8.6.5
584     `-- hello-2.10 -> /nix/store/k0ll91c4npk4lg8lqhx00glg2m735g74-hello-2.10
586   */
587   linkFarmFromDrvs = name: drvs:
588     let mkEntryFromDrv = drv: { name = drv.name; path = drv; };
589     in linkFarm name (map mkEntryFromDrv drvs);
591   # TODO: move onlyBin docs to the Nixpkgs manual
592   /*
593     Produce a derivation that links to the target derivation's `/bin`,
594     and *only* `/bin`.
596     This is useful when your favourite package doesn't have a separate
597     bin output and other contents of the package's output (e.g. setup
598     hooks) cause trouble when used in your environment.
599   */
600   onlyBin = drv: runCommand "${drv.name}-only-bin" { } ''
601     mkdir -p $out
602     ln -s ${lib.getBin drv}/bin $out/bin
603   '';
606   # Docs in doc/build-helpers/special/makesetuphook.section.md
607   # See https://nixos.org/manual/nixpkgs/unstable/#sec-pkgs.makeSetupHook
608   makeSetupHook =
609     { name ? lib.warn "calling makeSetupHook without passing a name is deprecated." "hook"
610       # hooks go in nativeBuildInputs so these will be nativeBuildInputs
611     , propagatedBuildInputs ? [ ]
612       # these will be buildInputs
613     , depsTargetTargetPropagated ? [ ]
614     , meta ? { }
615     , passthru ? { }
616     , substitutions ? { }
617     }:
618     script:
619     runCommand name
620       (substitutions // {
621         # TODO(@Artturin:) substitutions should be inside the env attrset
622         # but users are likely passing non-substitution arguments through substitutions
623         # turn off __structuredAttrs to unbreak substituteAll
624         __structuredAttrs = false;
625         inherit meta;
626         inherit depsTargetTargetPropagated;
627         inherit propagatedBuildInputs;
628         strictDeps = true;
629         # TODO 2023-01, no backport: simplify to inherit passthru;
630         passthru = passthru
631           // optionalAttrs (substitutions?passthru)
632           (warn "makeSetupHook (name = ${lib.strings.escapeNixString name}): `substitutions.passthru` is deprecated. Please set `passthru` directly."
633             substitutions.passthru);
634       })
635       (''
636         mkdir -p $out/nix-support
637         cp ${script} $out/nix-support/setup-hook
638         recordPropagatedDependencies
639       '' + lib.optionalString (substitutions != { }) ''
640         substituteAll ${script} $out/nix-support/setup-hook
641       '');
643   # Remove after 25.05 branch-off
644   writeReferencesToFile = throw "writeReferencesToFile has been removed. Use writeClosure instead.";
646   # Docs in doc/build-helpers/trivial-build-helpers.chapter.md
647   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeClosure
648   writeClosure = paths: runCommand "runtime-deps"
649     {
650       # Get the cleaner exportReferencesGraph interface
651       __structuredAttrs = true;
652       exportReferencesGraph.graph = paths;
653       nativeBuildInputs = [ jq ];
654     }
655     ''
656       jq -r ".graph | map(.path) | sort | .[]" "$NIX_ATTRS_JSON_FILE" > "$out"
657     '';
659   # Docs in doc/build-helpers/trivial-build-helpers.chapter.md
660   # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeDirectReferencesToFile
661   writeDirectReferencesToFile = path: runCommand "runtime-references"
662     {
663       exportReferencesGraph = [ "graph" path ];
664       inherit path;
665     }
666     ''
667       touch ./references
668       while read p; do
669         read dummy
670         read nrRefs
671         if [[ $p == $path ]]; then
672           for ((i = 0; i < nrRefs; i++)); do
673             read ref;
674             echo $ref >>./references
675           done
676         else
677           for ((i = 0; i < nrRefs; i++)); do
678             read ref;
679           done
680         fi
681       done < graph
682       sort ./references >$out
683     '';
685   # TODO: move writeStringReferencesToFile docs to the Nixpkgs manual
686   /*
687     Extract a string's references to derivations and paths (its
688     context) and write them to a text file, removing the input string
689     itself from the dependency graph. This is useful when you want to
690     make a derivation depend on the string's references, but not its
691     contents (to avoid unnecessary rebuilds, for example).
693     Note that this only works as intended on Nix >= 2.3.
694    */
695   writeStringReferencesToFile = string:
696     /*
697        The basic operation this performs is to copy the string context
698        from `string` to a second string and wrap that string in a
699        derivation. However, that alone is not enough, since nothing in the
700        string refers to the output paths of the derivations/paths in its
701        context, meaning they'll be considered build-time dependencies and
702        removed from the wrapper derivation's closure. Putting the
703        necessary output paths in the new string is however not very
704        straightforward - the attrset returned by `getContext` contains
705        only references to derivations' .drv-paths, not their output
706        paths. In order to "convert" them, we try to extract the
707        corresponding paths from the original string using regex.
708     */
709     let
710       # Taken from https://github.com/NixOS/nix/blob/130284b8508dad3c70e8160b15f3d62042fc730a/src/libutil/hash.cc#L84
711       nixHashChars = "0123456789abcdfghijklmnpqrsvwxyz";
712       context = builtins.getContext string;
713       derivations = lib.filterAttrs (n: v: v ? outputs) context;
714       # Objects copied from outside of the store, such as paths and
715       # `builtins.fetch*`ed ones
716       sources = lib.attrNames (lib.filterAttrs (n: v: v ? path) context);
717       packages =
718         lib.mapAttrs'
719           (name: value:
720             {
721               inherit value;
722               name = lib.head (builtins.match "${builtins.storeDir}/[${nixHashChars}]+-(.*)\.drv" name);
723             })
724           derivations;
725       # The syntax of output paths differs between outputs named `out`
726       # and other, explicitly named ones. For explicitly named ones,
727       # the output name is suffixed as `-name`, but `out` outputs
728       # aren't suffixed at all, and thus aren't easily distinguished
729       # from named output paths. Therefore, we find all the named ones
730       # first so we can use them to remove false matches when looking
731       # for `out` outputs (see the definition of `outputPaths`).
732       namedOutputPaths =
733         lib.flatten
734           (lib.mapAttrsToList
735             (name: value:
736               (map
737                 (output:
738                   lib.filter
739                     lib.isList
740                     (builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name}-${output})" string))
741                 (lib.remove "out" value.outputs)))
742             packages);
743       # Only `out` outputs
744       outputPaths =
745         lib.flatten
746           (lib.mapAttrsToList
747             (name: value:
748               if lib.elem "out" value.outputs then
749                 lib.filter
750                   (x: lib.isList x &&
751                     # If the matched path is in `namedOutputPaths`,
752                     # it's a partial match of an output path where
753                     # the output name isn't `out`
754                     lib.all (o: !lib.hasPrefix (lib.head x) o) namedOutputPaths)
755                   (builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name})" string)
756               else
757                 [ ])
758             packages);
759       allPaths = lib.concatStringsSep "\n" (lib.unique (sources ++ namedOutputPaths ++ outputPaths));
760       allPathsWithContext = builtins.appendContext allPaths context;
761     in
762     if builtins ? getContext then
763       writeText "string-references" allPathsWithContext
764     else
765       writeDirectReferencesToFile (writeText "string-file" string);
768   # Docs in doc/build-helpers/fetchers.chapter.md
769   # See https://nixos.org/manual/nixpkgs/unstable/#requirefile
770   requireFile =
771     { name ? null
772     , sha256 ? null
773     , sha1 ? null
774     , hash ? null
775     , url ? null
776     , message ? null
777     , hashMode ? "flat"
778     }:
779       assert (message != null) || (url != null);
780       assert (sha256 != null) || (sha1 != null) || (hash != null);
781       assert (name != null) || (url != null);
782       let
783         msg =
784           if message != null then message
785           else ''
786             Unfortunately, we cannot download file ${name_} automatically.
787             Please go to ${url} to download it yourself, and add it to the Nix store
788             using either
789               nix-store --add-fixed ${hashAlgo} ${name_}
790             or
791               nix-prefetch-url --type ${hashAlgo} file:///path/to/${name_}
792           '';
793         hashAlgo =
794           if hash != null then (builtins.head (lib.strings.splitString "-" hash))
795           else if sha256 != null then "sha256"
796           else "sha1";
797         hashAlgo_ = if hash != null then "" else hashAlgo;
798         hash_ =
799           if hash != null then hash
800           else if sha256 != null then sha256
801           else sha1;
802         name_ = if name == null then baseNameOf (toString url) else name;
803       in
804       stdenvNoCC.mkDerivation {
805         name = name_;
806         outputHashMode = hashMode;
807         outputHashAlgo = hashAlgo_;
808         outputHash = hash_;
809         preferLocalBuild = true;
810         allowSubstitutes = false;
811         builder = writeScript "restrict-message" ''
812           source ${stdenvNoCC}/setup
813           cat <<_EOF_
815           ***
816           ${msg}
817           ***
819           _EOF_
820           exit 1
821         '';
822       };
825   # TODO: move copyPathToStore docs to the Nixpkgs manual
826   /*
827     Copy a path to the Nix store.
828     Nix automatically copies files to the store before stringifying paths.
829     If you need the store path of a file, ${copyPathToStore <path>} can be
830     shortened to ${<path>}.
831   */
832   copyPathToStore = builtins.filterSource (p: t: true);
835   # TODO: move copyPathsToStore docs to the Nixpkgs manual
836   /*
837     Copy a list of paths to the Nix store.
838   */
839   copyPathsToStore = builtins.map copyPathToStore;
841   # TODO: move applyPatches docs to the Nixpkgs manual
842   /* Applies a list of patches to a source directory.
844     Example:
846     # Patching nixpkgs:
848     applyPatches {
849       src = pkgs.path;
850       patches = [
851         (pkgs.fetchpatch {
852           url = "https://github.com/NixOS/nixpkgs/commit/1f770d20550a413e508e081ddc08464e9d08ba3d.patch";
853           sha256 = "1nlzx171y3r3jbk0qhvnl711kmdk57jlq4na8f8bs8wz2pbffymr";
854         })
855       ];
856     }
858    */
859   applyPatches =
860     { src
861     , name ? (if builtins.typeOf src == "path"
862       then builtins.baseNameOf src
863       else
864         if builtins.isAttrs src && builtins.hasAttr "name" src
865         then src.name
866         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."
867       ) + "-patched"
868     , patches ? [ ]
869     , prePatch ? ""
870     , postPatch ? ""
871     , ...
872     }@args:
873     if patches == [ ] && prePatch == "" && postPatch == ""
874     then src # nothing to do, so use original src to avoid additional drv
875     else stdenvNoCC.mkDerivation
876       ({
877         inherit name src patches prePatch postPatch;
878         preferLocalBuild = true;
879         allowSubstitutes = false;
880         phases = "unpackPhase patchPhase installPhase";
881         installPhase = "cp -R ./ $out";
882       }
883       # Carry `meta` information from the underlying `src` if present.
884       // (optionalAttrs (src?meta) { inherit (src) meta; })
885       // (removeAttrs args [ "src" "name" "patches" "prePatch" "postPatch" ]));
887   # TODO: move docs to Nixpkgs manual
888   /* An immutable file in the store with a length of 0 bytes. */
889   emptyFile = runCommand "empty-file"
890     {
891       outputHash = "sha256-d6xi4mKdjkX2JFicDIv5niSzpyI0m/Hnm8GGAIU04kY=";
892       outputHashMode = "recursive";
893       preferLocalBuild = true;
894     } "touch $out";
896   # TODO: move docs to Nixpkgs manual
897   /* An immutable empty directory in the store. */
898   emptyDirectory = runCommand "empty-directory"
899     {
900       outputHashAlgo = "sha256";
901       outputHashMode = "recursive";
902       outputHash = "0sjjj9z1dhilhpc8pq4154czrb79z9cm044jvn75kxcjv6v5l2m5";
903       preferLocalBuild = true;
904     } "mkdir $out";