create-amis.sh: fix typo
[NixPkgs.git] / lib / customisation.nix
bloba794b673d70c28ea9e09d7020c30487394b810d6
1 { lib }:
3 rec {
6   /* `overrideDerivation drv f' takes a derivation (i.e., the result
7      of a call to the builtin function `derivation') and returns a new
8      derivation in which the attributes of the original are overridden
9      according to the function `f'.  The function `f' is called with
10      the original derivation attributes.
12      `overrideDerivation' allows certain "ad-hoc" customisation
13      scenarios (e.g. in ~/.config/nixpkgs/config.nix).  For instance,
14      if you want to "patch" the derivation returned by a package
15      function in Nixpkgs to build another version than what the
16      function itself provides, you can do something like this:
18        mySed = overrideDerivation pkgs.gnused (oldAttrs: {
19          name = "sed-4.2.2-pre";
20          src = fetchurl {
21            url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
22            sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k";
23          };
24          patches = [];
25        });
27      For another application, see build-support/vm, where this
28      function is used to build arbitrary derivations inside a QEMU
29      virtual machine.
30   */
31   overrideDerivation = drv: f:
32     let
33       newDrv = derivation (drv.drvAttrs // (f drv));
34     in lib.flip (extendDerivation true) newDrv (
35       { meta = drv.meta or {};
36         passthru = if drv ? passthru then drv.passthru else {};
37       }
38       //
39       (drv.passthru or {})
40       //
41       (if (drv ? crossDrv && drv ? nativeDrv)
42        then {
43          crossDrv = overrideDerivation drv.crossDrv f;
44          nativeDrv = overrideDerivation drv.nativeDrv f;
45        }
46        else { }));
49   /* `makeOverridable` takes a function from attribute set to attribute set and
50      injects `override` attribute which can be used to override arguments of
51      the function.
53        nix-repl> x = {a, b}: { result = a + b; }
55        nix-repl> y = lib.makeOverridable x { a = 1; b = 2; }
57        nix-repl> y
58        { override = «lambda»; overrideDerivation = «lambda»; result = 3; }
60        nix-repl> y.override { a = 10; }
61        { override = «lambda»; overrideDerivation = «lambda»; result = 12; }
63      Please refer to "Nixpkgs Contributors Guide" section
64      "<pkg>.overrideDerivation" to learn about `overrideDerivation` and caveats
65      related to its use.
66   */
67   makeOverridable = f: origArgs:
68     let
69       result = f origArgs;
71       # Creates a functor with the same arguments as f
72       copyArgs = g: lib.setFunctionArgs g (lib.functionArgs f);
73       # Changes the original arguments with (potentially a function that returns) a set of new attributes
74       overrideWith = newArgs: origArgs // (if lib.isFunction newArgs then newArgs origArgs else newArgs);
76       # Re-call the function but with different arguments
77       overrideArgs = copyArgs (newArgs: makeOverridable f (overrideWith newArgs));
78       # Change the result of the function call by applying g to it
79       overrideResult = g: makeOverridable (copyArgs (args: g (f args))) origArgs;
80     in
81       if builtins.isAttrs result then
82         result // {
83           override = overrideArgs;
84           overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
85           ${if result ? overrideAttrs then "overrideAttrs" else null} = fdrv:
86             overrideResult (x: x.overrideAttrs fdrv);
87         }
88       else if lib.isFunction result then
89         # Transform the result into a functor while propagating its arguments
90         lib.setFunctionArgs result (lib.functionArgs result) // {
91           override = overrideArgs;
92         }
93       else result;
96   /* Call the package function in the file `fn' with the required
97     arguments automatically.  The function is called with the
98     arguments `args', but any missing arguments are obtained from
99     `autoArgs'.  This function is intended to be partially
100     parameterised, e.g.,
102       callPackage = callPackageWith pkgs;
103       pkgs = {
104         libfoo = callPackage ./foo.nix { };
105         libbar = callPackage ./bar.nix { };
106       };
108     If the `libbar' function expects an argument named `libfoo', it is
109     automatically passed as an argument.  Overrides or missing
110     arguments can be supplied in `args', e.g.
112       libbar = callPackage ./bar.nix {
113         libfoo = null;
114         enableX11 = true;
115       };
116   */
117   callPackageWith = autoArgs: fn: args:
118     let
119       f = if lib.isFunction fn then fn else import fn;
120       auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
121     in makeOverridable f (auto // args);
124   /* Like callPackage, but for a function that returns an attribute
125      set of derivations. The override function is added to the
126      individual attributes. */
127   callPackagesWith = autoArgs: fn: args:
128     let
129       f = if lib.isFunction fn then fn else import fn;
130       auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
131       origArgs = auto // args;
132       pkgs = f origArgs;
133       mkAttrOverridable = name: _: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
134     in
135       if lib.isDerivation pkgs then throw
136         ("function `callPackages` was called on a *single* derivation "
137           + ''"${pkgs.name or "<unknown-name>"}";''
138           + " did you mean to use `callPackage` instead?")
139       else lib.mapAttrs mkAttrOverridable pkgs;
142   /* Add attributes to each output of a derivation without changing
143      the derivation itself and check a given condition when evaluating. */
144   extendDerivation = condition: passthru: drv:
145     let
146       outputs = drv.outputs or [ "out" ];
148       commonAttrs = (removeAttrs drv [ "outputUnspecified" ]) //
149         (builtins.listToAttrs outputsList) //
150         ({ all = map (x: x.value) outputsList; }) // passthru;
152       outputToAttrListElement = outputName:
153         { name = outputName;
154           value = commonAttrs // {
155             inherit (drv.${outputName}) type outputName;
156             drvPath = assert condition; drv.${outputName}.drvPath;
157             outPath = assert condition; drv.${outputName}.outPath;
158           };
159         };
161       outputsList = map outputToAttrListElement outputs;
162     in commonAttrs // {
163       outputUnspecified = true;
164       drvPath = assert condition; drv.drvPath;
165       outPath = assert condition; drv.outPath;
166     };
168   /* Strip a derivation of all non-essential attributes, returning
169      only those needed by hydra-eval-jobs. Also strictly evaluate the
170      result to ensure that there are no thunks kept alive to prevent
171      garbage collection. */
172   hydraJob = drv:
173     let
174       outputs = drv.outputs or ["out"];
176       commonAttrs =
177         { inherit (drv) name system meta; inherit outputs; }
178         // lib.optionalAttrs (drv._hydraAggregate or false) {
179           _hydraAggregate = true;
180           constituents = map hydraJob (lib.flatten drv.constituents);
181         }
182         // (lib.listToAttrs outputsList);
184       makeOutput = outputName:
185         let output = drv.${outputName}; in
186         { name = outputName;
187           value = commonAttrs // {
188             outPath = output.outPath;
189             drvPath = output.drvPath;
190             type = "derivation";
191             inherit outputName;
192           };
193         };
195       outputsList = map makeOutput outputs;
197       drv' = (lib.head outputsList).value;
198     in lib.deepSeq drv' drv';
200   /* Make a set of packages with a common scope. All packages called
201      with the provided `callPackage' will be evaluated with the same
202      arguments. Any package in the set may depend on any other. The
203      `overrideScope'` function allows subsequent modification of the package
204      set in a consistent way, i.e. all packages in the set will be
205      called with the overridden packages. The package sets may be
206      hierarchical: the packages in the set are called with the scope
207      provided by `newScope' and the set provides a `newScope' attribute
208      which can form the parent scope for later package sets. */
209   makeScope = newScope: f:
210     let self = f self // {
211           newScope = scope: newScope (self // scope);
212           callPackage = self.newScope {};
213           overrideScope = g: lib.warn
214             "`overrideScope` (from `lib.makeScope`) is deprecated. Do `overrideScope' (self: super: { … })` instead of `overrideScope (super: self: { … })`. All other overrides have the parameters in that order, including other definitions of `overrideScope`. This was the only definition violating the pattern."
215             (makeScope newScope (lib.fixedPoints.extends (lib.flip g) f));
216           overrideScope' = g: makeScope newScope (lib.fixedPoints.extends g f);
217           packages = f;
218         };
219     in self;
221   /* Like the above, but aims to support cross compilation. It's still ugly, but
222      hopefully it helps a little bit. */
223   makeScopeWithSplicing = splicePackages: newScope: otherSplices: keep: extra: f:
224     let
225       spliced0 = splicePackages {
226         pkgsBuildBuild = otherSplices.selfBuildBuild;
227         pkgsBuildHost = otherSplices.selfBuildHost;
228         pkgsBuildTarget = otherSplices.selfBuildTarget;
229         pkgsHostHost = otherSplices.selfHostHost;
230         pkgsHostTarget = self; # Not `otherSplices.selfHostTarget`;
231         pkgsTargetTarget = otherSplices.selfTargetTarget;
232       };
233       spliced = extra spliced0 // spliced0 // keep self;
234       self = f self // {
235         newScope = scope: newScope (spliced // scope);
236         callPackage = newScope spliced; # == self.newScope {};
237         # N.B. the other stages of the package set spliced in are *not*
238         # overridden.
239         overrideScope = g: makeScopeWithSplicing
240           splicePackages
241           newScope
242           otherSplices
243           keep
244           extra
245           (lib.fixedPoints.extends g f);
246         packages = f;
247       };
248     in self;