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.
18 For another application, see build-support/vm, where this
19 function is used to build arbitrary derivations inside a QEMU
22 Note that in order to preserve evaluation errors, the new derivation's
23 outPath depends on the old one's, which means that this function cannot
24 be used in circular situations when the old derivation also depends on the
27 You should in general prefer `drv.overrideAttrs` over this function;
28 see the nixpkgs manual for more information on overriding.
31 mySed = overrideDerivation pkgs.gnused (oldAttrs: {
32 name = "sed-4.2.2-pre";
34 url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
35 hash = "sha256-MxBJRcM2rYzQYwJ5XKxhXTQByvSg5jZc5cSHEZoB2IY=";
41 overrideDerivation :: Derivation -> ( Derivation -> AttrSet ) -> Derivation
43 overrideDerivation = drv: f:
45 newDrv = derivation (drv.drvAttrs // (f drv));
46 in lib.flip (extendDerivation (builtins.seq drv.drvPath true)) newDrv (
47 { meta = drv.meta or {};
48 passthru = if drv ? passthru then drv.passthru else {};
53 lib.optionalAttrs (drv ? __spliced) {
54 __spliced = {} // (lib.mapAttrs (_: sDrv: overrideDerivation sDrv f) drv.__spliced);
58 /* `makeOverridable` takes a function from attribute set to attribute set and
59 injects `override` attribute which can be used to override arguments of
62 Please refer to documentation on [`<pkg>.overrideDerivation`](#sec-pkg-overrideDerivation) to learn about `overrideDerivation` and caveats
66 nix-repl> x = {a, b}: { result = a + b; }
68 nix-repl> y = lib.makeOverridable x { a = 1; b = 2; }
71 { override = «lambda»; overrideDerivation = «lambda»; result = 3; }
73 nix-repl> y.override { a = 10; }
74 { override = «lambda»; overrideDerivation = «lambda»; result = 12; }
77 makeOverridable :: (AttrSet -> a) -> AttrSet -> a
81 # Creates a functor with the same arguments as f
82 mirrorArgs = lib.mirrorFunctionArgs f;
88 # Changes the original arguments with (potentially a function that returns) a set of new attributes
89 overrideWith = newArgs: origArgs // (if lib.isFunction newArgs then newArgs origArgs else newArgs);
91 # Re-call the function but with different arguments
92 overrideArgs = mirrorArgs (newArgs: makeOverridable f (overrideWith newArgs));
93 # Change the result of the function call by applying g to it
94 overrideResult = g: makeOverridable (mirrorArgs (args: g (f args))) origArgs;
96 if builtins.isAttrs result then
98 override = overrideArgs;
99 overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
100 ${if result ? overrideAttrs then "overrideAttrs" else null} = fdrv:
101 overrideResult (x: x.overrideAttrs fdrv);
103 else if lib.isFunction result then
104 # Transform the result into a functor while propagating its arguments
105 lib.setFunctionArgs result (lib.functionArgs result) // {
106 override = overrideArgs;
111 /* Call the package function in the file `fn` with the required
112 arguments automatically. The function is called with the
113 arguments `args`, but any missing arguments are obtained from
114 `autoArgs`. This function is intended to be partially
118 callPackage = callPackageWith pkgs;
120 libfoo = callPackage ./foo.nix { };
121 libbar = callPackage ./bar.nix { };
125 If the `libbar` function expects an argument named `libfoo`, it is
126 automatically passed as an argument. Overrides or missing
127 arguments can be supplied in `args`, e.g.
130 libbar = callPackage ./bar.nix {
136 <!-- TODO: Apply "Example:" tag to the examples above -->
139 callPackageWith :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
141 callPackageWith = autoArgs: fn: args:
143 f = if lib.isFunction fn then fn else import fn;
144 fargs = lib.functionArgs f;
146 # All arguments that will be passed to the function
147 # This includes automatic ones and ones passed explicitly
148 allArgs = builtins.intersectAttrs fargs autoArgs // args;
150 # a list of argument names that the function requires, but
151 # wouldn't be passed to it
152 missingArgs = lib.attrNames
153 # Filter out arguments that have a default value
154 (lib.filterAttrs (name: value: ! value)
155 # Filter out arguments that would be passed
156 (removeAttrs fargs (lib.attrNames allArgs)));
158 # Get a list of suggested argument names for a given missing one
159 getSuggestions = arg: lib.pipe (autoArgs // args) [
161 # Only use ones that are at most 2 edits away. While mork would work,
162 # levenshteinAtMost is only fast for 2 or less.
163 (lib.filter (lib.strings.levenshteinAtMost 2 arg))
164 # Put strings with shorter distance first
165 (lib.sort (x: y: lib.strings.levenshtein x arg < lib.strings.levenshtein y arg))
166 # Only take the first couple results
169 (map (x: "\"" + x + "\""))
172 prettySuggestions = suggestions:
173 if suggestions == [] then ""
174 else if lib.length suggestions == 1 then ", did you mean ${lib.elemAt suggestions 0}?"
175 else ", did you mean ${lib.concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
179 loc = builtins.unsafeGetAttrPos arg fargs;
180 # loc' can be removed once lib/minver.nix is >2.3.4, since that includes
181 # https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
182 loc' = if loc != null then loc.file + ":" + toString loc.line
183 else if ! lib.isFunction fn then
184 toString fn + lib.optionalString (lib.sources.pathIsDirectory fn) "/default.nix"
185 else "<unknown location>";
186 in "Function called without required argument \"${arg}\" at "
187 + "${loc'}${prettySuggestions (getSuggestions arg)}";
189 # Only show the error for the first missing argument
190 error = errorForArg (lib.head missingArgs);
192 in if missingArgs == [] then makeOverridable f allArgs else abort error;
195 /* Like callPackage, but for a function that returns an attribute
196 set of derivations. The override function is added to the
197 individual attributes.
200 callPackagesWith :: AttrSet -> ((AttrSet -> AttrSet) | Path) -> AttrSet -> AttrSet
202 callPackagesWith = autoArgs: fn: args:
204 f = if lib.isFunction fn then fn else import fn;
205 auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
206 origArgs = auto // args;
208 mkAttrOverridable = name: _: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
210 if lib.isDerivation pkgs then throw
211 ("function `callPackages` was called on a *single* derivation "
212 + ''"${pkgs.name or "<unknown-name>"}";''
213 + " did you mean to use `callPackage` instead?")
214 else lib.mapAttrs mkAttrOverridable pkgs;
217 /* Add attributes to each output of a derivation without changing
218 the derivation itself and check a given condition when evaluating.
221 extendDerivation :: Bool -> Any -> Derivation -> Derivation
223 extendDerivation = condition: passthru: drv:
225 outputs = drv.outputs or [ "out" ];
227 commonAttrs = drv // (builtins.listToAttrs outputsList) //
228 ({ all = map (x: x.value) outputsList; }) // passthru;
230 outputToAttrListElement = outputName:
232 value = commonAttrs // {
233 inherit (drv.${outputName}) type outputName;
234 outputSpecified = true;
235 drvPath = assert condition; drv.${outputName}.drvPath;
236 outPath = assert condition; drv.${outputName}.outPath;
238 # TODO: give the derivation control over the outputs.
239 # `overrideAttrs` may not be the only attribute that needs
240 # updating when switching outputs.
241 lib.optionalAttrs (passthru?overrideAttrs) {
242 # TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing.
243 overrideAttrs = f: (passthru.overrideAttrs f).${outputName};
247 outputsList = map outputToAttrListElement outputs;
249 drvPath = assert condition; drv.drvPath;
250 outPath = assert condition; drv.outPath;
253 /* Strip a derivation of all non-essential attributes, returning
254 only those needed by hydra-eval-jobs. Also strictly evaluate the
255 result to ensure that there are no thunks kept alive to prevent
259 hydraJob :: (Derivation | Null) -> (Derivation | Null)
263 outputs = drv.outputs or ["out"];
266 { inherit (drv) name system meta; inherit outputs; }
267 // lib.optionalAttrs (drv._hydraAggregate or false) {
268 _hydraAggregate = true;
269 constituents = map hydraJob (lib.flatten drv.constituents);
271 // (lib.listToAttrs outputsList);
273 makeOutput = outputName:
274 let output = drv.${outputName}; in
276 value = commonAttrs // {
277 outPath = output.outPath;
278 drvPath = output.drvPath;
284 outputsList = map makeOutput outputs;
286 drv' = (lib.head outputsList).value;
287 in if drv == null then null else
288 lib.deepSeq drv' drv';
290 /* Make a set of packages with a common scope. All packages called
291 with the provided `callPackage` will be evaluated with the same
292 arguments. Any package in the set may depend on any other. The
293 `overrideScope'` function allows subsequent modification of the package
294 set in a consistent way, i.e. all packages in the set will be
295 called with the overridden packages. The package sets may be
296 hierarchical: the packages in the set are called with the scope
297 provided by `newScope` and the set provides a `newScope` attribute
298 which can form the parent scope for later package sets.
301 makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> AttrSet
303 makeScope = newScope: f:
304 let self = f self // {
305 newScope = scope: newScope (self // scope);
306 callPackage = self.newScope {};
307 overrideScope = g: makeScope newScope (lib.fixedPoints.extends g f);
308 # Remove after 24.11 is released.
309 overrideScope' = g: lib.warnIf (lib.isInOldestRelease 2311)
310 "`overrideScope'` (from `lib.makeScope`) has been renamed to `overrideScope`."
311 (makeScope newScope (lib.fixedPoints.extends g f));
316 /* backward compatibility with old uncurried form; deprecated */
317 makeScopeWithSplicing =
318 splicePackages: newScope: otherSplices: keep: extra: f:
319 makeScopeWithSplicing'
320 { inherit splicePackages newScope; }
321 { inherit otherSplices keep extra f; };
323 /* Like makeScope, but aims to support cross compilation. It's still ugly, but
324 hopefully it helps a little bit.
327 makeScopeWithSplicing' ::
328 { splicePackages :: Splice -> AttrSet
329 , newScope :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
331 -> { otherSplices :: Splice, keep :: AttrSet -> AttrSet, extra :: AttrSet -> AttrSet }
335 { pkgsBuildBuild :: AttrSet
336 , pkgsBuildHost :: AttrSet
337 , pkgsBuildTarget :: AttrSet
338 , pkgsHostHost :: AttrSet
339 , pkgsHostTarget :: AttrSet
340 , pkgsTargetTarget :: AttrSet
343 makeScopeWithSplicing' =
348 # Attrs from `self` which won't be spliced.
349 # Avoid using keep, it's only used for a python hook workaround, added in PR #104201.
350 # ex: `keep = (self: { inherit (self) aAttr; })`
352 # Additional attrs to add to the sets `callPackage`.
353 # When the package is from a subset (but not a subset within a package IS #211340)
354 # within `spliced0` it will be spliced.
355 # When using an package outside the set but it's available from `pkgs`, use the package from `pkgs.__splicedPackages`.
356 # 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
359 # nix-repl> darwin.apple_sdk.frameworks.CoreFoundation
360 # «derivation ...CoreFoundation-11.0.0.drv»
361 # nix-repl> darwin.CoreFoundation
362 # error: attribute 'CoreFoundation' missing
363 # nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { }
364 # «derivation ...CoreFoundation-11.0.0.drv»
366 , extra ? (_spliced0: {})
370 spliced0 = splicePackages {
371 pkgsBuildBuild = otherSplices.selfBuildBuild;
372 pkgsBuildHost = otherSplices.selfBuildHost;
373 pkgsBuildTarget = otherSplices.selfBuildTarget;
374 pkgsHostHost = otherSplices.selfHostHost;
375 pkgsHostTarget = self; # Not `otherSplices.selfHostTarget`;
376 pkgsTargetTarget = otherSplices.selfTargetTarget;
378 spliced = extra spliced0 // spliced0 // keep self;
380 newScope = scope: newScope (spliced // scope);
381 callPackage = newScope spliced; # == self.newScope {};
382 # N.B. the other stages of the package set spliced in are *not*
384 overrideScope = g: (makeScopeWithSplicing'
385 { inherit splicePackages newScope; }
386 { inherit otherSplices keep extra;
387 f = lib.fixedPoints.extends g f;