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";
21 url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
22 sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k";
27 For another application, see build-support/vm, where this
28 function is used to build arbitrary derivations inside a QEMU
31 overrideDerivation = drv: f:
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 {};
41 (if (drv ? crossDrv && drv ? nativeDrv)
43 crossDrv = overrideDerivation drv.crossDrv f;
44 nativeDrv = overrideDerivation drv.nativeDrv f;
49 /* `makeOverridable` takes a function from attribute set to attribute set and
50 injects `override` attribute which can be used to override arguments of
53 nix-repl> x = {a, b}: { result = a + b; }
55 nix-repl> y = lib.makeOverridable x { a = 1; b = 2; }
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
67 makeOverridable = 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;
81 if builtins.isAttrs result then
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);
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;
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
102 callPackage = callPackageWith pkgs;
104 libfoo = callPackage ./foo.nix { };
105 libbar = callPackage ./bar.nix { };
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 {
117 callPackageWith = autoArgs: fn: args:
119 f = if lib.isFunction fn then fn else import fn;
120 fargs = lib.functionArgs f;
122 # All arguments that will be passed to the function
123 # This includes automatic ones and ones passed explicitly
124 allArgs = builtins.intersectAttrs fargs autoArgs // args;
126 # A list of argument names that the function requires, but
127 # wouldn't be passed to it
128 missingArgs = lib.attrNames
129 # Filter out arguments that have a default value
130 (lib.filterAttrs (name: value: ! value)
131 # Filter out arguments that would be passed
132 (removeAttrs fargs (lib.attrNames allArgs)));
134 # Get a list of suggested argument names for a given missing one
135 getSuggestions = arg: lib.pipe (autoArgs // args) [
137 # Only use ones that are at most 2 edits away. While mork would work,
138 # levenshteinAtMost is only fast for 2 or less.
139 (lib.filter (lib.strings.levenshteinAtMost 2 arg))
140 # Put strings with shorter distance first
141 (lib.sort (x: y: lib.strings.levenshtein x arg < lib.strings.levenshtein y arg))
142 # Only take the first couple results
145 (map (x: "\"" + x + "\""))
148 prettySuggestions = suggestions:
149 if suggestions == [] then ""
150 else if lib.length suggestions == 1 then ", did you mean ${lib.elemAt suggestions 0}?"
151 else ", did you mean ${lib.concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
155 loc = builtins.unsafeGetAttrPos arg fargs;
156 # loc' can be removed once lib/minver.nix is >2.3.4, since that includes
157 # https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
158 loc' = if loc != null then loc.file + ":" + toString loc.line
159 else if ! lib.isFunction fn then
160 toString fn + lib.optionalString (lib.sources.pathIsDirectory fn) "/default.nix"
161 else "<unknown location>";
162 in "Function called without required argument \"${arg}\" at "
163 + "${loc'}${prettySuggestions (getSuggestions arg)}";
165 # Only show the error for the first missing argument
166 error = errorForArg (lib.head missingArgs);
168 in if missingArgs == [] then makeOverridable f allArgs else throw error;
171 /* Like callPackage, but for a function that returns an attribute
172 set of derivations. The override function is added to the
173 individual attributes. */
174 callPackagesWith = autoArgs: fn: args:
176 f = if lib.isFunction fn then fn else import fn;
177 auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
178 origArgs = auto // args;
180 mkAttrOverridable = name: _: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
182 if lib.isDerivation pkgs then throw
183 ("function `callPackages` was called on a *single* derivation "
184 + ''"${pkgs.name or "<unknown-name>"}";''
185 + " did you mean to use `callPackage` instead?")
186 else lib.mapAttrs mkAttrOverridable pkgs;
189 /* Add attributes to each output of a derivation without changing
190 the derivation itself and check a given condition when evaluating. */
191 extendDerivation = condition: passthru: drv:
193 outputs = drv.outputs or [ "out" ];
195 commonAttrs = drv // (builtins.listToAttrs outputsList) //
196 ({ all = map (x: x.value) outputsList; }) // passthru;
198 outputToAttrListElement = outputName:
200 value = commonAttrs // {
201 inherit (drv.${outputName}) type outputName;
202 outputSpecified = true;
203 drvPath = assert condition; drv.${outputName}.drvPath;
204 outPath = assert condition; drv.${outputName}.outPath;
208 outputsList = map outputToAttrListElement outputs;
210 drvPath = assert condition; drv.drvPath;
211 outPath = assert condition; drv.outPath;
214 /* Strip a derivation of all non-essential attributes, returning
215 only those needed by hydra-eval-jobs. Also strictly evaluate the
216 result to ensure that there are no thunks kept alive to prevent
217 garbage collection. */
220 outputs = drv.outputs or ["out"];
223 { inherit (drv) name system meta; inherit outputs; }
224 // lib.optionalAttrs (drv._hydraAggregate or false) {
225 _hydraAggregate = true;
226 constituents = map hydraJob (lib.flatten drv.constituents);
228 // (lib.listToAttrs outputsList);
230 makeOutput = outputName:
231 let output = drv.${outputName}; in
233 value = commonAttrs // {
234 outPath = output.outPath;
235 drvPath = output.drvPath;
241 outputsList = map makeOutput outputs;
243 drv' = (lib.head outputsList).value;
244 in lib.deepSeq drv' drv';
246 /* Make a set of packages with a common scope. All packages called
247 with the provided `callPackage' will be evaluated with the same
248 arguments. Any package in the set may depend on any other. The
249 `overrideScope'` function allows subsequent modification of the package
250 set in a consistent way, i.e. all packages in the set will be
251 called with the overridden packages. The package sets may be
252 hierarchical: the packages in the set are called with the scope
253 provided by `newScope' and the set provides a `newScope' attribute
254 which can form the parent scope for later package sets. */
255 makeScope = newScope: f:
256 let self = f self // {
257 newScope = scope: newScope (self // scope);
258 callPackage = self.newScope {};
259 overrideScope = g: lib.warn
260 "`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."
261 (makeScope newScope (lib.fixedPoints.extends (lib.flip g) f));
262 overrideScope' = g: makeScope newScope (lib.fixedPoints.extends g f);
267 /* Like the above, but aims to support cross compilation. It's still ugly, but
268 hopefully it helps a little bit. */
269 makeScopeWithSplicing = splicePackages: newScope: otherSplices: keep: extra: f:
271 spliced0 = splicePackages {
272 pkgsBuildBuild = otherSplices.selfBuildBuild;
273 pkgsBuildHost = otherSplices.selfBuildHost;
274 pkgsBuildTarget = otherSplices.selfBuildTarget;
275 pkgsHostHost = otherSplices.selfHostHost;
276 pkgsHostTarget = self; # Not `otherSplices.selfHostTarget`;
277 pkgsTargetTarget = otherSplices.selfTargetTarget;
279 spliced = extra spliced0 // spliced0 // keep self;
281 newScope = scope: newScope (spliced // scope);
282 callPackage = newScope spliced; # == self.newScope {};
283 # N.B. the other stages of the package set spliced in are *not*
285 overrideScope = g: makeScopeWithSplicing
291 (lib.fixedPoints.extends g f);