nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{ lib }:
2
3let
4 inherit (builtins)
5 intersectAttrs
6 unsafeGetAttrPos
7 ;
8 inherit (lib)
9 functionArgs
10 isFunction
11 mirrorFunctionArgs
12 isAttrs
13 setFunctionArgs
14 optionalAttrs
15 attrNames
16 filter
17 elemAt
18 concatStringsSep
19 sortOn
20 take
21 length
22 filterAttrs
23 optionalString
24 flip
25 head
26 pipe
27 isDerivation
28 listToAttrs
29 mapAttrs
30 seq
31 flatten
32 deepSeq
33 extends
34 toFunction
35 id
36 ;
37 inherit (lib.strings) levenshtein levenshteinAtMost;
38
39in
40rec {
41
42 /**
43 `overrideDerivation drv f` takes a derivation (i.e., the result
44 of a call to the builtin function `derivation`) and returns a new
45 derivation in which the attributes of the original are overridden
46 according to the function `f`. The function `f` is called with
47 the original derivation attributes.
48
49 `overrideDerivation` allows certain "ad-hoc" customisation
50 scenarios (e.g. in ~/.config/nixpkgs/config.nix). For instance,
51 if you want to "patch" the derivation returned by a package
52 function in Nixpkgs to build another version than what the
53 function itself provides.
54
55 For another application, see build-support/vm, where this
56 function is used to build arbitrary derivations inside a QEMU
57 virtual machine.
58
59 Note that in order to preserve evaluation errors, the new derivation's
60 outPath depends on the old one's, which means that this function cannot
61 be used in circular situations when the old derivation also depends on the
62 new one.
63
64 You should in general prefer `drv.overrideAttrs` over this function;
65 see the nixpkgs manual for more information on overriding.
66
67 # Inputs
68
69 `drv`
70
71 : 1\. Function argument
72
73 `f`
74
75 : 2\. Function argument
76
77 # Type
78
79 ```
80 overrideDerivation :: Derivation -> ( Derivation -> AttrSet ) -> Derivation
81 ```
82
83 # Examples
84 :::{.example}
85 ## `lib.customisation.overrideDerivation` usage example
86
87 ```nix
88 mySed = overrideDerivation pkgs.gnused (oldAttrs: {
89 name = "sed-4.2.2-pre";
90 src = fetchurl {
91 url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
92 hash = "sha256-MxBJRcM2rYzQYwJ5XKxhXTQByvSg5jZc5cSHEZoB2IY=";
93 };
94 patches = [];
95 });
96 ```
97
98 :::
99 */
100 overrideDerivation =
101 drv: f:
102 let
103 newDrv = derivation (drv.drvAttrs // (f drv));
104 in
105 flip (extendDerivation (seq drv.drvPath true)) newDrv (
106 {
107 meta = drv.meta or { };
108 passthru = if drv ? passthru then drv.passthru else { };
109 }
110 // (drv.passthru or { })
111 // optionalAttrs (drv ? __spliced) {
112 __spliced = { } // (mapAttrs (_: sDrv: overrideDerivation sDrv f) drv.__spliced);
113 }
114 );
115
116 /**
117 `makeOverridable` takes a function from attribute set to attribute set and
118 injects `override` attribute which can be used to override arguments of
119 the function.
120
121 Please refer to documentation on [`<pkg>.overrideDerivation`](#sec-pkg-overrideDerivation) to learn about `overrideDerivation` and caveats
122 related to its use.
123
124 # Inputs
125
126 `f`
127
128 : 1\. Function argument
129
130 # Type
131
132 ```
133 makeOverridable :: (AttrSet -> a) -> AttrSet -> a
134 ```
135
136 # Examples
137 :::{.example}
138 ## `lib.customisation.makeOverridable` usage example
139
140 ```nix
141 nix-repl> x = {a, b}: { result = a + b; }
142
143 nix-repl> y = lib.makeOverridable x { a = 1; b = 2; }
144
145 nix-repl> y
146 { override = «lambda»; overrideDerivation = «lambda»; result = 3; }
147
148 nix-repl> y.override { a = 10; }
149 { override = «lambda»; overrideDerivation = «lambda»; result = 12; }
150 ```
151
152 :::
153 */
154 makeOverridable =
155 f:
156 let
157 # Creates a functor with the same arguments as f
158 mirrorArgs = mirrorFunctionArgs f;
159 # Recover overrider and additional attributes for f
160 # When f is a callable attribute set,
161 # it may contain its own `f.override` and additional attributes.
162 # This helper function recovers those attributes and decorate the overrider.
163 recoverMetadata =
164 if isAttrs f then
165 fDecorated:
166 # Preserve additional attributes for f
167 f
168 // fDecorated
169 # Decorate f.override if presented
170 // lib.optionalAttrs (f ? override) {
171 override = fdrv: makeOverridable (f.override fdrv);
172 }
173 else
174 id;
175 decorate = f': recoverMetadata (mirrorArgs f');
176 in
177 decorate (
178 origArgs:
179 let
180 result = f origArgs;
181
182 # Changes the original arguments with (potentially a function that returns) a set of new attributes
183 overrideWith = newArgs: origArgs // (if isFunction newArgs then newArgs origArgs else newArgs);
184
185 # Re-call the function but with different arguments
186 overrideArgs = mirrorArgs (
187 /**
188 Change the arguments with which a certain function is called.
189
190 In some cases, you may find a list of possible attributes to pass in this function's `__functionArgs` attribute, but it will not be complete for an original function like `args@{foo, ...}: ...`, which accepts arbitrary attributes.
191
192 This function was provided by `lib.makeOverridable`.
193 */
194 newArgs: makeOverridable f (overrideWith newArgs)
195 );
196 # Change the result of the function call by applying g to it
197 overrideResult = g: makeOverridable (mirrorArgs (args: g (f args))) origArgs;
198 in
199 if isAttrs result then
200 result
201 // {
202 override = overrideArgs;
203 overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
204 ${if result ? overrideAttrs then "overrideAttrs" else null} =
205 /**
206 Override the attributes that were passed to `mkDerivation` in order to generate this derivation.
207
208 This function is provided by `lib.makeOverridable`, and indirectly by `callPackage` among others, in order to make the combination of `override` and `overrideAttrs` work.
209 Specifically, it re-adds the `override` attribute to the result of `overrideAttrs`.
210
211 The real implementation of `overrideAttrs` is provided by `stdenv.mkDerivation`.
212 */
213 # NOTE: part of the above documentation had to be duplicated in `mkDerivation`'s `overrideAttrs`.
214 # design/tech debt issue: https://github.com/NixOS/nixpkgs/issues/273815
215 fdrv: overrideResult (x: x.overrideAttrs fdrv);
216 }
217 else if isFunction result then
218 # Transform the result into a functor while propagating its arguments
219 setFunctionArgs result (functionArgs result)
220 // {
221 override = overrideArgs;
222 }
223 else
224 result
225 );
226
227 /**
228 Call the package function in the file `fn` with the required
229 arguments automatically. The function is called with the
230 arguments `args`, but any missing arguments are obtained from
231 `autoArgs`. This function is intended to be partially
232 parameterised, e.g.,
233
234 ```nix
235 callPackage = callPackageWith pkgs;
236 pkgs = {
237 libfoo = callPackage ./foo.nix { };
238 libbar = callPackage ./bar.nix { };
239 };
240 ```
241
242 If the `libbar` function expects an argument named `libfoo`, it is
243 automatically passed as an argument. Overrides or missing
244 arguments can be supplied in `args`, e.g.
245
246 ```nix
247 libbar = callPackage ./bar.nix {
248 libfoo = null;
249 enableX11 = true;
250 };
251 ```
252
253 <!-- TODO: Apply "Example:" tag to the examples above -->
254
255 # Inputs
256
257 `autoArgs`
258
259 : 1\. Function argument
260
261 `fn`
262
263 : 2\. Function argument
264
265 `args`
266
267 : 3\. Function argument
268
269 # Type
270
271 ```
272 callPackageWith :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
273 ```
274 */
275 callPackageWith =
276 autoArgs: fn: args:
277 let
278 f = if isFunction fn then fn else import fn;
279 fargs = functionArgs f;
280
281 # All arguments that will be passed to the function
282 # This includes automatic ones and ones passed explicitly
283 allArgs = intersectAttrs fargs autoArgs // args;
284
285 # a list of argument names that the function requires, but
286 # wouldn't be passed to it
287 missingArgs =
288 # Filter out arguments that have a default value
289 (
290 filterAttrs (name: value: !value)
291 # Filter out arguments that would be passed
292 (removeAttrs fargs (attrNames allArgs))
293 );
294
295 # Get a list of suggested argument names for a given missing one
296 getSuggestions =
297 arg:
298 pipe (autoArgs // args) [
299 attrNames
300 # Only use ones that are at most 2 edits away. While mork would work,
301 # levenshteinAtMost is only fast for 2 or less.
302 (filter (levenshteinAtMost 2 arg))
303 # Put strings with shorter distance first
304 (sortOn (levenshtein arg))
305 # Only take the first couple results
306 (take 3)
307 # Quote all entries
308 (map (x: "\"" + x + "\""))
309 ];
310
311 prettySuggestions =
312 suggestions:
313 if suggestions == [ ] then
314 ""
315 else if length suggestions == 1 then
316 ", did you mean ${elemAt suggestions 0}?"
317 else
318 ", did you mean ${concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
319
320 errorForArg =
321 arg:
322 let
323 loc = unsafeGetAttrPos arg fargs;
324 loc' = if loc != null then loc.file + ":" + toString loc.line else "<unknown location>";
325 in
326 "Function called without required argument \"${arg}\" at "
327 + "${loc'}${prettySuggestions (getSuggestions arg)}";
328
329 # Only show the error for the first missing argument
330 error = errorForArg (head (attrNames missingArgs));
331
332 in
333 if missingArgs == { } then
334 makeOverridable f allArgs
335 # This needs to be an abort so it can't be caught with `builtins.tryEval`,
336 # which is used by nix-env and ofborg to filter out packages that don't evaluate.
337 # This way we're forced to fix such errors in Nixpkgs,
338 # which is especially relevant with allowAliases = false
339 else
340 abort "lib.customisation.callPackageWith: ${error}";
341
342 /**
343 Like `callPackage`, but for a function that returns an attribute
344 set of derivations. The override function is added to the
345 individual attributes.
346
347 # Inputs
348
349 `autoArgs`
350
351 : 1\. Function argument
352
353 `fn`
354
355 : 2\. Function argument
356
357 `args`
358
359 : 3\. Function argument
360
361 # Type
362
363 ```
364 callPackagesWith :: AttrSet -> ((AttrSet -> AttrSet) | Path) -> AttrSet -> AttrSet
365 ```
366 */
367 callPackagesWith =
368 autoArgs: fn: args:
369 let
370 f = if isFunction fn then fn else import fn;
371 auto = intersectAttrs (functionArgs f) autoArgs;
372 mirrorArgs = mirrorFunctionArgs f;
373 origArgs = auto // args;
374 pkgs = f origArgs;
375 mkAttrOverridable = name: _: makeOverridable (mirrorArgs (newArgs: (f newArgs).${name})) origArgs;
376 in
377 if isDerivation pkgs then
378 throw (
379 "function `callPackages` was called on a *single* derivation "
380 + ''"${pkgs.name or "<unknown-name>"}";''
381 + " did you mean to use `callPackage` instead?"
382 )
383 else
384 mapAttrs mkAttrOverridable pkgs;
385
386 /**
387 Add attributes to each output of a derivation without changing
388 the derivation itself and check a given condition when evaluating.
389
390 # Inputs
391
392 `condition`
393
394 : 1\. Function argument
395
396 `passthru`
397
398 : 2\. Function argument
399
400 `drv`
401
402 : 3\. Function argument
403
404 # Type
405
406 ```
407 extendDerivation :: Bool -> Any -> Derivation -> Derivation
408 ```
409 */
410 extendDerivation =
411 condition: passthru: drv:
412 let
413 outputs = drv.outputs or [ "out" ];
414
415 commonAttrs =
416 drv // (listToAttrs outputsList) // { all = map (x: x.value) outputsList; } // passthru;
417
418 outputToAttrListElement = outputName: {
419 name = outputName;
420 value =
421 commonAttrs
422 // {
423 inherit (drv.${outputName}) type outputName;
424 outputSpecified = true;
425 drvPath =
426 assert condition;
427 drv.${outputName}.drvPath;
428 outPath =
429 assert condition;
430 drv.${outputName}.outPath;
431 }
432 //
433 # TODO: give the derivation control over the outputs.
434 # `overrideAttrs` may not be the only attribute that needs
435 # updating when switching outputs.
436 optionalAttrs (passthru ? overrideAttrs) {
437 # TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing.
438 overrideAttrs = f: (passthru.overrideAttrs f).${outputName};
439 };
440 };
441
442 outputsList = map outputToAttrListElement outputs;
443 in
444 commonAttrs
445 // {
446 drvPath =
447 assert condition;
448 drv.drvPath;
449 outPath =
450 assert condition;
451 drv.outPath;
452 };
453
454 /**
455 Strip a derivation of all non-essential attributes, returning
456 only those needed by hydra-eval-jobs. Also strictly evaluate the
457 result to ensure that there are no thunks kept alive to prevent
458 garbage collection.
459
460 # Inputs
461
462 `drv`
463
464 : 1\. Function argument
465
466 # Type
467
468 ```
469 hydraJob :: (Derivation | Null) -> (Derivation | Null)
470 ```
471 */
472 hydraJob =
473 drv:
474 let
475 outputs = drv.outputs or [ "out" ];
476
477 commonAttrs = {
478 inherit (drv) name system meta;
479 inherit outputs;
480 }
481 // optionalAttrs (drv._hydraAggregate or false) {
482 _hydraAggregate = true;
483 constituents = map hydraJob (flatten drv.constituents);
484 }
485 // (listToAttrs outputsList);
486
487 makeOutput =
488 outputName:
489 let
490 output = drv.${outputName};
491 in
492 {
493 name = outputName;
494 value = commonAttrs // {
495 outPath = output.outPath;
496 drvPath = output.drvPath;
497 type = "derivation";
498 inherit outputName;
499 };
500 };
501
502 outputsList = map makeOutput outputs;
503
504 drv' = (head outputsList).value;
505 in
506 if drv == null then null else deepSeq drv' drv';
507
508 /**
509 Make an attribute set (a "scope") from functions that take arguments from that same attribute set.
510 See [](#ex-makeScope) for how to use it.
511
512 # Inputs
513
514 1. `newScope` (`AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a`)
515
516 A function that takes an attribute set `attrs` and returns what ends up as `callPackage` in the output.
517
518 Typical values are `callPackageWith` or the output attribute `newScope`.
519
520 2. `f` (`AttrSet -> AttrSet`)
521
522 A function that takes an attribute set as returned by `makeScope newScope f` (a "scope") and returns any attribute set.
523
524 This function is used to compute the fixpoint of the resulting scope using `callPackage`.
525 Its argument is the lazily evaluated reference to the value of that fixpoint, and is typically called `self` or `final`.
526
527 See [](#ex-makeScope) for how to use it.
528 See [](#sec-functions-library-fixedPoints) for details on fixpoint computation.
529
530 # Output
531
532 `makeScope` returns an attribute set of a form called `scope`, which also contains the final attributes produced by `f`:
533
534 ```
535 scope :: {
536 callPackage :: ((AttrSet -> a) | Path) -> AttrSet -> a
537 newScope = AttrSet -> scope
538 overrideScope = (scope -> scope -> AttrSet) -> scope
539 packages :: AttrSet -> AttrSet
540 }
541 ```
542
543 - `callPackage` (`((AttrSet -> a) | Path) -> AttrSet -> a`)
544
545 A function that
546
547 1. Takes a function `p`, or a path to a Nix file that contains a function `p`, which takes an attribute set and returns value of arbitrary type `a`,
548 2. Takes an attribute set `args` with explicit attributes to pass to `p`,
549 3. Calls `f` with attributes from the original attribute set `attrs` passed to `newScope` updated with `args`, i.e. `attrs // args`, if they match the attributes in the argument of `p`.
550
551 All such functions `p` will be called with the same value for `attrs`.
552
553 See [](#ex-makeScope-callPackage) for how to use it.
554
555 - `newScope` (`AttrSet -> scope`)
556
557 Takes an attribute set `attrs` and returns a scope that extends the original scope.
558
559 - `overrideScope` (`(scope -> scope -> AttrSet) -> scope`)
560
561 Takes a function `g` of the form `final: prev: { # attributes }` to act as an overlay on `f`, and returns a new scope with values determined by `extends g f`.
562 See [](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.fixedPoints.extends) for details.
563
564 This allows subsequent modification of the final attribute set in a consistent way, i.e. all functions `p` invoked with `callPackage` will be called with the modified values.
565
566 - `packages` (`AttrSet -> AttrSet`)
567
568 The value of the argument `f` to `makeScope`.
569
570 - final attributes
571
572 The final values returned by `f`.
573
574 # Examples
575
576 :::{#ex-makeScope .example}
577 # Create an interdependent package set on top of `pkgs`
578
579 The functions in `foo.nix` and `bar.nix` can depend on each other, in the sense that `foo.nix` can contain a function that expects `bar` as an attribute in its argument.
580
581 ```nix
582 let
583 pkgs = import <nixpkgs> { };
584 in
585 pkgs.lib.makeScope pkgs.newScope (self: {
586 foo = self.callPackage ./foo.nix { };
587 bar = self.callPackage ./bar.nix { };
588 })
589 ```
590
591 evaluates to
592
593 ```nix
594 {
595 callPackage = «lambda»;
596 newScope = «lambda»;
597 overrideScope = «lambda»;
598 packages = «lambda»;
599 foo = «derivation»;
600 bar = «derivation»;
601 }
602 ```
603 :::
604
605 :::{#ex-makeScope-callPackage .example}
606 # Using `callPackage` from a scope
607
608 ```nix
609 let
610 pkgs = import <nixpkgs> { };
611 inherit (pkgs) lib;
612 scope = lib.makeScope lib.callPackageWith (self: { a = 1; b = 2; });
613 three = scope.callPackage ({ a, b }: a + b) { };
614 four = scope.callPackage ({ a, b }: a + b) { a = 2; };
615 in
616 [ three four ]
617 ```
618
619 evaluates to
620
621 ```nix
622 [ 3 4 ]
623 ```
624 :::
625
626 # Type
627
628 ```
629 makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> scope
630 ```
631 */
632 makeScope =
633 newScope: f:
634 let
635 self = f self // {
636 newScope = scope: newScope (self // scope);
637 callPackage = self.newScope { };
638 overrideScope = g: makeScope newScope (extends g f);
639 packages = f;
640 };
641 in
642 self;
643
644 /**
645 backward compatibility with old uncurried form; deprecated
646
647 # Inputs
648
649 `splicePackages`
650
651 : 1\. Function argument
652
653 `newScope`
654
655 : 2\. Function argument
656
657 `otherSplices`
658
659 : 3\. Function argument
660
661 `keep`
662
663 : 4\. Function argument
664
665 `extra`
666
667 : 5\. Function argument
668
669 `f`
670
671 : 6\. Function argument
672 */
673 makeScopeWithSplicing =
674 splicePackages: newScope: otherSplices: keep: extra: f:
675 makeScopeWithSplicing' { inherit splicePackages newScope; } {
676 inherit
677 otherSplices
678 keep
679 extra
680 f
681 ;
682 };
683
684 /**
685 Like `makeScope`, but aims to support cross compilation. It's still ugly, but
686 hopefully it helps a little bit.
687
688 # Type
689
690 ```
691 makeScopeWithSplicing' ::
692 { splicePackages :: Splice -> AttrSet
693 , newScope :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
694 }
695 -> { otherSplices :: Splice, keep :: AttrSet -> AttrSet, extra :: AttrSet -> AttrSet }
696 -> AttrSet
697
698 Splice ::
699 { pkgsBuildBuild :: AttrSet
700 , pkgsBuildHost :: AttrSet
701 , pkgsBuildTarget :: AttrSet
702 , pkgsHostHost :: AttrSet
703 , pkgsHostTarget :: AttrSet
704 , pkgsTargetTarget :: AttrSet
705 }
706 ```
707 */
708 makeScopeWithSplicing' =
709 {
710 splicePackages,
711 newScope,
712 }:
713 {
714 otherSplices,
715 # Attrs from `self` which won't be spliced.
716 # Avoid using keep, it's only used for a python hook workaround, added in PR #104201.
717 # ex: `keep = (self: { inherit (self) aAttr; })`
718 keep ? (_self: { }),
719 # Additional attrs to add to the sets `callPackage`.
720 # When the package is from a subset (but not a subset within a package IS #211340)
721 # within `spliced0` it will be spliced.
722 # When using an package outside the set but it's available from `pkgs`, use the package from `pkgs.__splicedPackages`.
723 # If the package is not available within the set or in `pkgs`, such as a package in a let binding, it will not be spliced
724 # ex:
725 # ```
726 # nix-repl> darwin.apple_sdk.frameworks.CoreFoundation
727 # «derivation ...CoreFoundation-11.0.0.drv»
728 # nix-repl> darwin.CoreFoundation
729 # error: attribute 'CoreFoundation' missing
730 # nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { }
731 # «derivation ...CoreFoundation-11.0.0.drv»
732 # ```
733 extra ? (_spliced0: { }),
734 f,
735 }:
736 let
737 spliced0 = splicePackages {
738 pkgsBuildBuild = otherSplices.selfBuildBuild;
739 pkgsBuildHost = otherSplices.selfBuildHost;
740 pkgsBuildTarget = otherSplices.selfBuildTarget;
741 pkgsHostHost = otherSplices.selfHostHost;
742 pkgsHostTarget = self; # Not `otherSplices.selfHostTarget`;
743 pkgsTargetTarget = otherSplices.selfTargetTarget;
744 };
745 spliced = extra spliced0 // spliced0 // keep self;
746 self = f self // {
747 newScope = scope: newScope (spliced // scope);
748 callPackage = newScope spliced; # == self.newScope {};
749 # N.B. the other stages of the package set spliced in are *not*
750 # overridden.
751 overrideScope =
752 g:
753 (makeScopeWithSplicing' { inherit splicePackages newScope; } {
754 inherit otherSplices keep extra;
755 f = extends g f;
756 });
757 packages = f;
758 };
759 in
760 self;
761
762 /**
763 Define a `mkDerivation`-like function based on another `mkDerivation`-like function.
764
765 [`stdenv.mkDerivation`](#part-stdenv) gives access to
766 its final set of derivation attributes when it is passed a function,
767 or when it is passed an overlay-style function in `overrideAttrs`.
768
769 Instead of composing new `stdenv.mkDerivation`-like build helpers
770 using normal function composition,
771 `extendMkDerivation` makes sure that the returned build helper
772 supports such first class recursion like `mkDerivation` does.
773
774 `extendMkDerivation` takes an extra attribute set to configure its behaviour.
775 One can optionally specify
776 `transformDrv` to specify a function to apply to the result derivation,
777 or `inheritFunctionArgs` to decide whether to inherit the `__functionArgs`
778 from the base build helper.
779
780 # Inputs
781
782 `extendMkDerivation`-specific configurations
783 : `constructDrv` (required)
784 : Base build helper, the `mkDerivation`-like build helper to extend.
785
786 `excludeDrvArgNames` (default to `[ ]`)
787 : Argument names not to pass from the input fixed-point arguments to `constructDrv`.
788 It doesn't apply to the updating arguments returned by `extendDrvArgs`.
789
790 `excludeFunctionArgNames` (default to `[ ]`)
791 : `__functionArgs` attribute names to remove from the result build helper.
792 `excludeFunctionArgNames` is useful for argument deprecation while avoiding ellipses.
793
794 `extendDrvArgs` (required)
795 : An extension (overlay) of the argument set, like the one taken by [`overrideAttrs`](#sec-pkg-overrideAttrs) but applied before passing to `constructDrv`.
796
797 `inheritFunctionArgs` (default to `true`)
798 : Whether to inherit `__functionArgs` from the base build helper.
799 Set `inheritFunctionArgs` to `false` when `extendDrvArgs`'s `args` set pattern does not contain an ellipsis.
800
801 `transformDrv` (default to `lib.id`)
802 : Function to apply to the result derivation.
803
804 # Type
805
806 ```
807 extendMkDerivation ::
808 {
809 constructDrv :: ((FixedPointArgs | AttrSet) -> a)
810 excludeDrvArgNames :: [ String ],
811 excludeFunctionArgNames :: [ String ]
812 extendDrvArgs :: (AttrSet -> AttrSet -> AttrSet)
813 inheritFunctionArgs :: Bool,
814 transformDrv :: a -> a,
815 }
816 -> (FixedPointArgs | AttrSet) -> a
817
818 FixedPointArgs = AttrSet -> AttrSet
819 a = Derivation when defining a build helper
820 ```
821
822 # Examples
823
824 :::{.example}
825 ## `lib.customisation.extendMkDerivation` usage example
826 ```nix-repl
827 mkLocalDerivation = lib.extendMkDerivation {
828 constructDrv = pkgs.stdenv.mkDerivation;
829 excludeDrvArgNames = [ "specialArg" ];
830 extendDrvArgs =
831 finalAttrs: args@{ preferLocalBuild ? true, allowSubstitute ? false, specialArg ? (_: false), ... }:
832 { inherit preferLocalBuild allowSubstitute; passthru = { inherit specialArg; } // args.passthru or { }; };
833 }
834
835 mkLocalDerivation.__functionArgs
836 => { allowSubstitute = true; preferLocalBuild = true; specialArg = true; }
837
838 mkLocalDerivation { inherit (pkgs.hello) pname version src; specialArg = _: false; }
839 => «derivation /nix/store/xirl67m60ahg6jmzicx43a81g635g8z8-hello-2.12.1.drv»
840
841 mkLocalDerivation (finalAttrs: { inherit (pkgs.hello) pname version src; specialArg = _: false; })
842 => «derivation /nix/store/xirl67m60ahg6jmzicx43a81g635g8z8-hello-2.12.1.drv»
843
844 (mkLocalDerivation (finalAttrs: { inherit (pkgs.hello) pname version src; passthru = { foo = "a"; bar = "${finalAttrs.passthru.foo}b"; }; })).bar
845 => "ab"
846 ```
847 :::
848
849 :::{.note}
850 If `transformDrv` is specified,
851 it should take care of existing attributes that perform overriding
852 (e.g., [`overrideAttrs`](#sec-pkg-overrideAttrs))
853 to ensure that the overriding functionality of the result derivation
854 work as expected.
855 Modifications that breaks the overriding include
856 direct [attribute set update](https://nixos.org/manual/nix/stable/language/operators#update)
857 and [`lib.extendDerivation`](#function-library-lib.customisation.extendDerivation).
858 :::
859 */
860 extendMkDerivation =
861 let
862 extendsWithExclusion =
863 excludedNames: g: f: final:
864 let
865 previous = f final;
866 in
867 removeAttrs previous excludedNames // g final previous;
868 in
869 {
870 constructDrv,
871 excludeDrvArgNames ? [ ],
872 excludeFunctionArgNames ? [ ],
873 extendDrvArgs,
874 inheritFunctionArgs ? true,
875 transformDrv ? id,
876 }:
877 setFunctionArgs
878 # Adds the fixed-point style support
879 (
880 fpargs:
881 transformDrv (
882 constructDrv (extendsWithExclusion excludeDrvArgNames extendDrvArgs (toFunction fpargs))
883 )
884 )
885 # Add __functionArgs
886 (
887 removeAttrs (
888 # Inherit the __functionArgs from the base build helper
889 optionalAttrs inheritFunctionArgs (removeAttrs (functionArgs constructDrv) excludeDrvArgNames)
890 # Recover the __functionArgs from the derived build helper
891 // functionArgs (extendDrvArgs { })
892 ) excludeFunctionArgNames
893 )
894 // {
895 inherit
896 # Expose to the result build helper.
897 constructDrv
898 excludeDrvArgNames
899 extendDrvArgs
900 transformDrv
901 ;
902 };
903
904 /**
905 Removes a prefix from the attribute names of a cross index.
906
907 A cross index (short for "Cross Platform Pair Index") is a 6-field structure
908 organizing values by cross-compilation platform relationships.
909
910 # Inputs
911
912 `prefix`
913 : The prefix to remove from cross index attribute names
914
915 `crossIndex`
916 : A cross index with prefixed names
917
918 # Type
919
920 ```
921 renameCrossIndexFrom :: String -> AttrSet -> AttrSet
922 ```
923
924 # Examples
925
926 :::{.example}
927 ## `lib.customisation.renameCrossIndexFrom` usage example
928
929 ```nix
930 renameCrossIndexFrom "pkgs" { pkgsBuildBuild = ...; pkgsBuildHost = ...; ... }
931 => { buildBuild = ...; buildHost = ...; ... }
932 ```
933 :::
934 */
935 renameCrossIndexFrom = prefix: x: {
936 buildBuild = x."${prefix}BuildBuild";
937 buildHost = x."${prefix}BuildHost";
938 buildTarget = x."${prefix}BuildTarget";
939 hostHost = x."${prefix}HostHost";
940 hostTarget = x."${prefix}HostTarget";
941 targetTarget = x."${prefix}TargetTarget";
942 };
943
944 /**
945 Adds a prefix to the attribute names of a cross index.
946
947 A cross index (short for "Cross Platform Pair Index") is a 6-field structure
948 organizing values by cross-compilation platform relationships.
949
950 # Inputs
951
952 `prefix`
953 : The prefix to add to cross index attribute names
954
955 `crossIndex`
956 : A cross index to be prefixed
957
958 # Type
959
960 ```
961 renameCrossIndexTo :: String -> AttrSet -> AttrSet
962 ```
963
964 # Examples
965
966 :::{.example}
967 ## `lib.customisation.renameCrossIndexTo` usage example
968
969 ```nix
970 renameCrossIndexTo "self" { buildBuild = ...; buildHost = ...; ... }
971 => { selfBuildBuild = ...; selfBuildHost = ...; ... }
972 ```
973 :::
974 */
975 renameCrossIndexTo = prefix: x: {
976 "${prefix}BuildBuild" = x.buildBuild;
977 "${prefix}BuildHost" = x.buildHost;
978 "${prefix}BuildTarget" = x.buildTarget;
979 "${prefix}HostHost" = x.hostHost;
980 "${prefix}HostTarget" = x.hostTarget;
981 "${prefix}TargetTarget" = x.targetTarget;
982 };
983
984 /**
985 Takes a function and applies it pointwise to each field of a cross index.
986
987 A cross index (short for "Cross Platform Pair Index") is a 6-field structure
988 organizing values by cross-compilation platform relationships.
989
990 # Inputs
991
992 `f`
993 : Function to apply to each cross index value
994
995 `crossIndex`
996 : A cross index to transform
997
998 # Type
999
1000 ```
1001 mapCrossIndex :: (a -> b) -> AttrSet -> AttrSet
1002 ```
1003
1004 # Examples
1005
1006 :::{.example}
1007 ## `lib.customisation.mapCrossIndex` usage example
1008
1009 ```nix
1010 mapCrossIndex (x: x * 10) { buildBuild = 1; buildHost = 2; ... }
1011 => { buildBuild = 10; buildHost = 20; ... }
1012 ```
1013
1014 ```nix
1015 # Extract a package from package sets
1016 mapCrossIndex (pkgs: pkgs.hello) crossIndexedPackageSets
1017 ```
1018 :::
1019 */
1020 mapCrossIndex =
1021 f:
1022 {
1023 buildBuild,
1024 buildHost,
1025 buildTarget,
1026 hostHost,
1027 hostTarget,
1028 targetTarget,
1029 }:
1030 {
1031 buildBuild = f buildBuild;
1032 buildHost = f buildHost;
1033 buildTarget = f buildTarget;
1034 hostHost = f hostHost;
1035 hostTarget = f hostTarget;
1036 targetTarget = f targetTarget;
1037 };
1038}