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
79 makeOverridable = f: lib.setFunctionArgs
83 # Creates a functor with the same arguments as f
84 copyArgs = g: lib.setFunctionArgs g (lib.functionArgs f);
85 # Changes the original arguments with (potentially a function that returns) a set of new attributes
86 overrideWith = newArgs: origArgs // (if lib.isFunction newArgs then newArgs origArgs else newArgs);
88 # Re-call the function but with different arguments
89 overrideArgs = copyArgs (newArgs: makeOverridable f (overrideWith newArgs));
90 # Change the result of the function call by applying g to it
91 overrideResult = g: makeOverridable (copyArgs (args: g (f args))) origArgs;
93 if builtins.isAttrs result then
95 override = overrideArgs;
96 overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
97 ${if result ? overrideAttrs then "overrideAttrs" else null} = fdrv:
98 overrideResult (x: x.overrideAttrs fdrv);
100 else if lib.isFunction result then
101 # Transform the result into a functor while propagating its arguments
102 lib.setFunctionArgs result (lib.functionArgs result) // {
103 override = overrideArgs;
106 (lib.functionArgs f);
109 /* Call the package function in the file `fn` with the required
110 arguments automatically. The function is called with the
111 arguments `args`, but any missing arguments are obtained from
112 `autoArgs`. This function is intended to be partially
116 callPackage = callPackageWith pkgs;
118 libfoo = callPackage ./foo.nix { };
119 libbar = callPackage ./bar.nix { };
123 If the `libbar` function expects an argument named `libfoo`, it is
124 automatically passed as an argument. Overrides or missing
125 arguments can be supplied in `args`, e.g.
128 libbar = callPackage ./bar.nix {
134 <!-- TODO: Apply "Example:" tag to the examples above -->
137 callPackageWith :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
139 callPackageWith = autoArgs: fn: args:
141 f = if lib.isFunction fn then fn else import fn;
142 fargs = lib.functionArgs f;
144 # All arguments that will be passed to the function
145 # This includes automatic ones and ones passed explicitly
146 allArgs = builtins.intersectAttrs fargs autoArgs // args;
148 # a list of argument names that the function requires, but
149 # wouldn't be passed to it
150 missingArgs = lib.attrNames
151 # Filter out arguments that have a default value
152 (lib.filterAttrs (name: value: ! value)
153 # Filter out arguments that would be passed
154 (removeAttrs fargs (lib.attrNames allArgs)));
156 # Get a list of suggested argument names for a given missing one
157 getSuggestions = arg: lib.pipe (autoArgs // args) [
159 # Only use ones that are at most 2 edits away. While mork would work,
160 # levenshteinAtMost is only fast for 2 or less.
161 (lib.filter (lib.strings.levenshteinAtMost 2 arg))
162 # Put strings with shorter distance first
163 (lib.sort (x: y: lib.strings.levenshtein x arg < lib.strings.levenshtein y arg))
164 # Only take the first couple results
167 (map (x: "\"" + x + "\""))
170 prettySuggestions = suggestions:
171 if suggestions == [] then ""
172 else if lib.length suggestions == 1 then ", did you mean ${lib.elemAt suggestions 0}?"
173 else ", did you mean ${lib.concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
177 loc = builtins.unsafeGetAttrPos arg fargs;
178 # loc' can be removed once lib/minver.nix is >2.3.4, since that includes
179 # https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
180 loc' = if loc != null then loc.file + ":" + toString loc.line
181 else if ! lib.isFunction fn then
182 toString fn + lib.optionalString (lib.sources.pathIsDirectory fn) "/default.nix"
183 else "<unknown location>";
184 in "Function called without required argument \"${arg}\" at "
185 + "${loc'}${prettySuggestions (getSuggestions arg)}";
187 # Only show the error for the first missing argument
188 error = errorForArg (lib.head missingArgs);
190 in if missingArgs == [] then makeOverridable f allArgs else abort error;
193 /* Like callPackage, but for a function that returns an attribute
194 set of derivations. The override function is added to the
195 individual attributes.
198 callPackagesWith :: AttrSet -> ((AttrSet -> AttrSet) | Path) -> AttrSet -> AttrSet
200 callPackagesWith = autoArgs: fn: args:
202 f = if lib.isFunction fn then fn else import fn;
203 auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
204 origArgs = auto // args;
206 mkAttrOverridable = name: _: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
208 if lib.isDerivation pkgs then throw
209 ("function `callPackages` was called on a *single* derivation "
210 + ''"${pkgs.name or "<unknown-name>"}";''
211 + " did you mean to use `callPackage` instead?")
212 else lib.mapAttrs mkAttrOverridable pkgs;
215 /* Add attributes to each output of a derivation without changing
216 the derivation itself and check a given condition when evaluating.
219 extendDerivation :: Bool -> Any -> Derivation -> Derivation
221 extendDerivation = condition: passthru: drv:
223 outputs = drv.outputs or [ "out" ];
225 commonAttrs = drv // (builtins.listToAttrs outputsList) //
226 ({ all = map (x: x.value) outputsList; }) // passthru;
228 outputToAttrListElement = outputName:
230 value = commonAttrs // {
231 inherit (drv.${outputName}) type outputName;
232 outputSpecified = true;
233 drvPath = assert condition; drv.${outputName}.drvPath;
234 outPath = assert condition; drv.${outputName}.outPath;
236 # TODO: give the derivation control over the outputs.
237 # `overrideAttrs` may not be the only attribute that needs
238 # updating when switching outputs.
239 lib.optionalAttrs (passthru?overrideAttrs) {
240 # TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing.
241 overrideAttrs = f: (passthru.overrideAttrs f).${outputName};
245 outputsList = map outputToAttrListElement outputs;
247 drvPath = assert condition; drv.drvPath;
248 outPath = assert condition; drv.outPath;
251 /* Strip a derivation of all non-essential attributes, returning
252 only those needed by hydra-eval-jobs. Also strictly evaluate the
253 result to ensure that there are no thunks kept alive to prevent
257 hydraJob :: (Derivation | Null) -> (Derivation | Null)
261 outputs = drv.outputs or ["out"];
264 { inherit (drv) name system meta; inherit outputs; }
265 // lib.optionalAttrs (drv._hydraAggregate or false) {
266 _hydraAggregate = true;
267 constituents = map hydraJob (lib.flatten drv.constituents);
269 // (lib.listToAttrs outputsList);
271 makeOutput = outputName:
272 let output = drv.${outputName}; in
274 value = commonAttrs // {
275 outPath = output.outPath;
276 drvPath = output.drvPath;
282 outputsList = map makeOutput outputs;
284 drv' = (lib.head outputsList).value;
285 in if drv == null then null else
286 lib.deepSeq drv' drv';
288 /* Make a set of packages with a common scope. All packages called
289 with the provided `callPackage` will be evaluated with the same
290 arguments. Any package in the set may depend on any other. The
291 `overrideScope'` function allows subsequent modification of the package
292 set in a consistent way, i.e. all packages in the set will be
293 called with the overridden packages. The package sets may be
294 hierarchical: the packages in the set are called with the scope
295 provided by `newScope` and the set provides a `newScope` attribute
296 which can form the parent scope for later package sets.
299 makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> AttrSet
301 makeScope = newScope: f:
302 let self = f self // {
303 newScope = scope: newScope (self // scope);
304 callPackage = self.newScope {};
305 overrideScope = g: makeScope newScope (lib.fixedPoints.extends g f);
306 # Remove after 24.11 is released.
307 overrideScope' = g: lib.warnIf (lib.isInOldestRelease 2311)
308 "`overrideScope'` (from `lib.makeScope`) has been renamed to `overrideScope`."
309 (makeScope newScope (lib.fixedPoints.extends g f));
314 /* backward compatibility with old uncurried form; deprecated */
315 makeScopeWithSplicing =
316 splicePackages: newScope: otherSplices: keep: extra: f:
317 makeScopeWithSplicing'
318 { inherit splicePackages newScope; }
319 { inherit otherSplices keep extra f; };
321 /* Like makeScope, but aims to support cross compilation. It's still ugly, but
322 hopefully it helps a little bit.
325 makeScopeWithSplicing' ::
326 { splicePackages :: Splice -> AttrSet
327 , newScope :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
329 -> { otherSplices :: Splice, keep :: AttrSet -> AttrSet, extra :: AttrSet -> AttrSet }
333 { pkgsBuildBuild :: AttrSet
334 , pkgsBuildHost :: AttrSet
335 , pkgsBuildTarget :: AttrSet
336 , pkgsHostHost :: AttrSet
337 , pkgsHostTarget :: AttrSet
338 , pkgsTargetTarget :: AttrSet
341 makeScopeWithSplicing' =
346 # Attrs from `self` which won't be spliced.
347 # Avoid using keep, it's only used for a python hook workaround, added in PR #104201.
348 # ex: `keep = (self: { inherit (self) aAttr; })`
350 # Additional attrs to add to the sets `callPackage`.
351 # When the package is from a subset (but not a subset within a package IS #211340)
352 # within `spliced0` it will be spliced.
353 # When using an package outside the set but it's available from `pkgs`, use the package from `pkgs.__splicedPackages`.
354 # 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
357 # nix-repl> darwin.apple_sdk.frameworks.CoreFoundation
358 # «derivation ...CoreFoundation-11.0.0.drv»
359 # nix-repl> darwin.CoreFoundation
360 # error: attribute 'CoreFoundation' missing
361 # nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { }
362 # «derivation ...CoreFoundation-11.0.0.drv»
364 , extra ? (_spliced0: {})
368 spliced0 = splicePackages {
369 pkgsBuildBuild = otherSplices.selfBuildBuild;
370 pkgsBuildHost = otherSplices.selfBuildHost;
371 pkgsBuildTarget = otherSplices.selfBuildTarget;
372 pkgsHostHost = otherSplices.selfHostHost;
373 pkgsHostTarget = self; # Not `otherSplices.selfHostTarget`;
374 pkgsTargetTarget = otherSplices.selfTargetTarget;
376 spliced = extra spliced0 // spliced0 // keep self;
378 newScope = scope: newScope (spliced // scope);
379 callPackage = newScope spliced; # == self.newScope {};
380 # N.B. the other stages of the package set spliced in are *not*
382 overrideScope = g: (makeScopeWithSplicing'
383 { inherit splicePackages newScope; }
384 { inherit otherSplices keep extra;
385 f = lib.fixedPoints.extends g f;