1let
2
3 lib = import ./default.nix;
4 inherit (builtins) attrNames isFunction;
5
6in
7
8rec {
9
10
11 /* `overrideDerivation drv f' takes a derivation (i.e., the result
12 of a call to the builtin function `derivation') and returns a new
13 derivation in which the attributes of the original are overriden
14 according to the function `f'. The function `f' is called with
15 the original derivation attributes.
16
17 `overrideDerivation' allows certain "ad-hoc" customisation
18 scenarios (e.g. in ~/.nixpkgs/config.nix). For instance, if you
19 want to "patch" the derivation returned by a package function in
20 Nixpkgs to build another version than what the function itself
21 provides, you can do something like this:
22
23 mySed = overrideDerivation pkgs.gnused (oldAttrs: {
24 name = "sed-4.2.2-pre";
25 src = fetchurl {
26 url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
27 sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k";
28 };
29 patches = [];
30 });
31
32 For another application, see build-support/vm, where this
33 function is used to build arbitrary derivations inside a QEMU
34 virtual machine.
35 */
36 overrideDerivation = drv: f:
37 let
38 newDrv = derivation (drv.drvAttrs // (f drv));
39 in addPassthru newDrv (
40 { meta = drv.meta or {};
41 passthru = if drv ? passthru then drv.passthru else {};
42 }
43 //
44 (drv.passthru or {})
45 //
46 (if (drv ? crossDrv && drv ? nativeDrv)
47 then {
48 crossDrv = overrideDerivation drv.crossDrv f;
49 nativeDrv = overrideDerivation drv.nativeDrv f;
50 }
51 else { }));
52
53
54 makeOverridable = f: origArgs:
55 let
56 ff = f origArgs;
57 overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs);
58 in
59 if builtins.isAttrs ff then (ff //
60 { override = newArgs: makeOverridable f (overrideWith newArgs);
61 overrideDerivation = fdrv:
62 makeOverridable (args: overrideDerivation (f args) fdrv) origArgs;
63 })
64 else if builtins.isFunction ff then
65 { override = newArgs: makeOverridable f (overrideWith newArgs);
66 __functor = self: ff;
67 overrideDerivation = throw "overrideDerivation not yet supported for functors";
68 }
69 else ff;
70
71
72 /* Call the package function in the file `fn' with the required
73 arguments automatically. The function is called with the
74 arguments `args', but any missing arguments are obtained from
75 `autoArgs'. This function is intended to be partially
76 parameterised, e.g.,
77
78 callPackage = callPackageWith pkgs;
79 pkgs = {
80 libfoo = callPackage ./foo.nix { };
81 libbar = callPackage ./bar.nix { };
82 };
83
84 If the `libbar' function expects an argument named `libfoo', it is
85 automatically passed as an argument. Overrides or missing
86 arguments can be supplied in `args', e.g.
87
88 libbar = callPackage ./bar.nix {
89 libfoo = null;
90 enableX11 = true;
91 };
92 */
93 callPackageWith = autoArgs: fn: args:
94 let
95 f = if builtins.isFunction fn then fn else import fn;
96 auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
97 in makeOverridable f (auto // args);
98
99
100 /* Like callPackage, but for a function that returns an attribute
101 set of derivations. The override function is added to the
102 individual attributes. */
103 callPackagesWith = autoArgs: fn: args:
104 let
105 f = if builtins.isFunction fn then fn else import fn;
106 auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
107 finalArgs = auto // args;
108 pkgs = f finalArgs;
109 mkAttrOverridable = name: pkg: pkg // {
110 override = newArgs: mkAttrOverridable name (f (finalArgs // newArgs)).${name};
111 };
112 in lib.mapAttrs mkAttrOverridable pkgs;
113
114
115 /* Add attributes to each output of a derivation without changing
116 the derivation itself. */
117 addPassthru = drv: passthru:
118 let
119 outputs = drv.outputs or [ "out" ];
120
121 commonAttrs = drv // (builtins.listToAttrs outputsList) //
122 ({ all = map (x: x.value) outputsList; }) // passthru;
123
124 outputToAttrListElement = outputName:
125 { name = outputName;
126 value = commonAttrs // {
127 inherit (drv.${outputName}) outPath drvPath type outputName;
128 };
129 };
130
131 outputsList = map outputToAttrListElement outputs;
132 in commonAttrs.${drv.outputName};
133
134
135 /* Strip a derivation of all non-essential attributes, returning
136 only those needed by hydra-eval-jobs. Also strictly evaluate the
137 result to ensure that there are no thunks kept alive to prevent
138 garbage collection. */
139 hydraJob = drv:
140 let
141 outputs = drv.outputs or ["out"];
142
143 commonAttrs =
144 { inherit (drv) name system meta; inherit outputs; }
145 // lib.optionalAttrs (drv._hydraAggregate or false) {
146 _hydraAggregate = true;
147 constituents = map hydraJob (lib.flatten drv.constituents);
148 }
149 // (lib.listToAttrs outputsList);
150
151 makeOutput = outputName:
152 let output = drv.${outputName}; in
153 { name = outputName;
154 value = commonAttrs // {
155 outPath = output.outPath;
156 drvPath = output.drvPath;
157 type = "derivation";
158 inherit outputName;
159 };
160 };
161
162 outputsList = map makeOutput outputs;
163
164 drv' = (lib.head outputsList).value;
165 in lib.deepSeq drv' drv';
166
167}