7 functionArgs isFunction mirrorFunctionArgs isAttrs setFunctionArgs
8 optionalAttrs attrNames filter elemAt concatStringsSep sort take length
9 filterAttrs optionalString flip pathIsDirectory head pipe isDerivation listToAttrs
10 mapAttrs seq flatten deepSeq warnIf isInOldestRelease extends
12 inherit (lib.strings) levenshtein levenshteinAtMost;
18 /* `overrideDerivation drv f` takes a derivation (i.e., the result
19 of a call to the builtin function `derivation`) and returns a new
20 derivation in which the attributes of the original are overridden
21 according to the function `f`. The function `f` is called with
22 the original derivation attributes.
24 `overrideDerivation` allows certain "ad-hoc" customisation
25 scenarios (e.g. in ~/.config/nixpkgs/config.nix). For instance,
26 if you want to "patch" the derivation returned by a package
27 function in Nixpkgs to build another version than what the
28 function itself provides.
30 For another application, see build-support/vm, where this
31 function is used to build arbitrary derivations inside a QEMU
34 Note that in order to preserve evaluation errors, the new derivation's
35 outPath depends on the old one's, which means that this function cannot
36 be used in circular situations when the old derivation also depends on the
39 You should in general prefer `drv.overrideAttrs` over this function;
40 see the nixpkgs manual for more information on overriding.
43 mySed = overrideDerivation pkgs.gnused (oldAttrs: {
44 name = "sed-4.2.2-pre";
46 url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
47 hash = "sha256-MxBJRcM2rYzQYwJ5XKxhXTQByvSg5jZc5cSHEZoB2IY=";
53 overrideDerivation :: Derivation -> ( Derivation -> AttrSet ) -> Derivation
55 overrideDerivation = drv: f:
57 newDrv = derivation (drv.drvAttrs // (f drv));
58 in flip (extendDerivation (seq drv.drvPath true)) newDrv (
59 { meta = drv.meta or {};
60 passthru = if drv ? passthru then drv.passthru else {};
65 optionalAttrs (drv ? __spliced) {
66 __spliced = {} // (mapAttrs (_: sDrv: overrideDerivation sDrv f) drv.__spliced);
70 /* `makeOverridable` takes a function from attribute set to attribute set and
71 injects `override` attribute which can be used to override arguments of
74 Please refer to documentation on [`<pkg>.overrideDerivation`](#sec-pkg-overrideDerivation) to learn about `overrideDerivation` and caveats
78 nix-repl> x = {a, b}: { result = a + b; }
80 nix-repl> y = lib.makeOverridable x { a = 1; b = 2; }
83 { override = «lambda»; overrideDerivation = «lambda»; result = 3; }
85 nix-repl> y.override { a = 10; }
86 { override = «lambda»; overrideDerivation = «lambda»; result = 12; }
89 makeOverridable :: (AttrSet -> a) -> AttrSet -> a
93 # Creates a functor with the same arguments as f
94 mirrorArgs = mirrorFunctionArgs f;
100 # Changes the original arguments with (potentially a function that returns) a set of new attributes
101 overrideWith = newArgs: origArgs // (if isFunction newArgs then newArgs origArgs else newArgs);
103 # Re-call the function but with different arguments
104 overrideArgs = mirrorArgs (newArgs: makeOverridable f (overrideWith newArgs));
105 # Change the result of the function call by applying g to it
106 overrideResult = g: makeOverridable (mirrorArgs (args: g (f args))) origArgs;
108 if isAttrs result then
110 override = overrideArgs;
111 overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
112 ${if result ? overrideAttrs then "overrideAttrs" else null} = fdrv:
113 overrideResult (x: x.overrideAttrs fdrv);
115 else if isFunction result then
116 # Transform the result into a functor while propagating its arguments
117 setFunctionArgs result (functionArgs result) // {
118 override = overrideArgs;
123 /* Call the package function in the file `fn` with the required
124 arguments automatically. The function is called with the
125 arguments `args`, but any missing arguments are obtained from
126 `autoArgs`. This function is intended to be partially
130 callPackage = callPackageWith pkgs;
132 libfoo = callPackage ./foo.nix { };
133 libbar = callPackage ./bar.nix { };
137 If the `libbar` function expects an argument named `libfoo`, it is
138 automatically passed as an argument. Overrides or missing
139 arguments can be supplied in `args`, e.g.
142 libbar = callPackage ./bar.nix {
148 <!-- TODO: Apply "Example:" tag to the examples above -->
151 callPackageWith :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
153 callPackageWith = autoArgs: fn: args:
155 f = if isFunction fn then fn else import fn;
156 fargs = functionArgs f;
158 # All arguments that will be passed to the function
159 # This includes automatic ones and ones passed explicitly
160 allArgs = intersectAttrs fargs autoArgs // args;
162 # a list of argument names that the function requires, but
163 # wouldn't be passed to it
165 # Filter out arguments that have a default value
166 (filterAttrs (name: value: ! value)
167 # Filter out arguments that would be passed
168 (removeAttrs fargs (attrNames allArgs)));
170 # Get a list of suggested argument names for a given missing one
171 getSuggestions = arg: pipe (autoArgs // args) [
173 # Only use ones that are at most 2 edits away. While mork would work,
174 # levenshteinAtMost is only fast for 2 or less.
175 (filter (levenshteinAtMost 2 arg))
176 # Put strings with shorter distance first
177 (sort (x: y: levenshtein x arg < levenshtein y arg))
178 # Only take the first couple results
181 (map (x: "\"" + x + "\""))
184 prettySuggestions = suggestions:
185 if suggestions == [] then ""
186 else if length suggestions == 1 then ", did you mean ${elemAt suggestions 0}?"
187 else ", did you mean ${concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
191 loc = builtins.unsafeGetAttrPos arg fargs;
192 # loc' can be removed once lib/minver.nix is >2.3.4, since that includes
193 # https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
194 loc' = if loc != null then loc.file + ":" + toString loc.line
195 else if ! isFunction fn then
196 toString fn + optionalString (pathIsDirectory fn) "/default.nix"
197 else "<unknown location>";
198 in "Function called without required argument \"${arg}\" at "
199 + "${loc'}${prettySuggestions (getSuggestions arg)}";
201 # Only show the error for the first missing argument
202 error = errorForArg (head (attrNames missingArgs));
204 in if missingArgs == {}
205 then makeOverridable f allArgs
206 else throw "lib.customisation.callPackageWith: ${error}";
209 /* Like callPackage, but for a function that returns an attribute
210 set of derivations. The override function is added to the
211 individual attributes.
214 callPackagesWith :: AttrSet -> ((AttrSet -> AttrSet) | Path) -> AttrSet -> AttrSet
216 callPackagesWith = autoArgs: fn: args:
218 f = if isFunction fn then fn else import fn;
219 auto = intersectAttrs (functionArgs f) autoArgs;
220 origArgs = auto // args;
222 mkAttrOverridable = name: _: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
224 if isDerivation pkgs then throw
225 ("function `callPackages` was called on a *single* derivation "
226 + ''"${pkgs.name or "<unknown-name>"}";''
227 + " did you mean to use `callPackage` instead?")
228 else mapAttrs mkAttrOverridable pkgs;
231 /* Add attributes to each output of a derivation without changing
232 the derivation itself and check a given condition when evaluating.
235 extendDerivation :: Bool -> Any -> Derivation -> Derivation
237 extendDerivation = condition: passthru: drv:
239 outputs = drv.outputs or [ "out" ];
241 commonAttrs = drv // (listToAttrs outputsList) //
242 ({ all = map (x: x.value) outputsList; }) // passthru;
244 outputToAttrListElement = outputName:
246 value = commonAttrs // {
247 inherit (drv.${outputName}) type outputName;
248 outputSpecified = true;
249 drvPath = assert condition; drv.${outputName}.drvPath;
250 outPath = assert condition; drv.${outputName}.outPath;
252 # TODO: give the derivation control over the outputs.
253 # `overrideAttrs` may not be the only attribute that needs
254 # updating when switching outputs.
255 optionalAttrs (passthru?overrideAttrs) {
256 # TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing.
257 overrideAttrs = f: (passthru.overrideAttrs f).${outputName};
261 outputsList = map outputToAttrListElement outputs;
263 drvPath = assert condition; drv.drvPath;
264 outPath = assert condition; drv.outPath;
267 /* Strip a derivation of all non-essential attributes, returning
268 only those needed by hydra-eval-jobs. Also strictly evaluate the
269 result to ensure that there are no thunks kept alive to prevent
273 hydraJob :: (Derivation | Null) -> (Derivation | Null)
277 outputs = drv.outputs or ["out"];
280 { inherit (drv) name system meta; inherit outputs; }
281 // optionalAttrs (drv._hydraAggregate or false) {
282 _hydraAggregate = true;
283 constituents = map hydraJob (flatten drv.constituents);
285 // (listToAttrs outputsList);
287 makeOutput = outputName:
288 let output = drv.${outputName}; in
290 value = commonAttrs // {
291 outPath = output.outPath;
292 drvPath = output.drvPath;
298 outputsList = map makeOutput outputs;
300 drv' = (head outputsList).value;
301 in if drv == null then null else
304 /* Make a set of packages with a common scope. All packages called
305 with the provided `callPackage` will be evaluated with the same
306 arguments. Any package in the set may depend on any other. The
307 `overrideScope'` function allows subsequent modification of the package
308 set in a consistent way, i.e. all packages in the set will be
309 called with the overridden packages. The package sets may be
310 hierarchical: the packages in the set are called with the scope
311 provided by `newScope` and the set provides a `newScope` attribute
312 which can form the parent scope for later package sets.
315 makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> AttrSet
317 makeScope = newScope: f:
318 let self = f self // {
319 newScope = scope: newScope (self // scope);
320 callPackage = self.newScope {};
321 overrideScope = g: makeScope newScope (extends g f);
322 # Remove after 24.11 is released.
323 overrideScope' = g: warnIf (isInOldestRelease 2311)
324 "`overrideScope'` (from `lib.makeScope`) has been renamed to `overrideScope`."
325 (makeScope newScope (extends g f));
330 /* backward compatibility with old uncurried form; deprecated */
331 makeScopeWithSplicing =
332 splicePackages: newScope: otherSplices: keep: extra: f:
333 makeScopeWithSplicing'
334 { inherit splicePackages newScope; }
335 { inherit otherSplices keep extra f; };
337 /* Like makeScope, but aims to support cross compilation. It's still ugly, but
338 hopefully it helps a little bit.
341 makeScopeWithSplicing' ::
342 { splicePackages :: Splice -> AttrSet
343 , newScope :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
345 -> { otherSplices :: Splice, keep :: AttrSet -> AttrSet, extra :: AttrSet -> AttrSet }
349 { pkgsBuildBuild :: AttrSet
350 , pkgsBuildHost :: AttrSet
351 , pkgsBuildTarget :: AttrSet
352 , pkgsHostHost :: AttrSet
353 , pkgsHostTarget :: AttrSet
354 , pkgsTargetTarget :: AttrSet
357 makeScopeWithSplicing' =
362 # Attrs from `self` which won't be spliced.
363 # Avoid using keep, it's only used for a python hook workaround, added in PR #104201.
364 # ex: `keep = (self: { inherit (self) aAttr; })`
366 # Additional attrs to add to the sets `callPackage`.
367 # When the package is from a subset (but not a subset within a package IS #211340)
368 # within `spliced0` it will be spliced.
369 # When using an package outside the set but it's available from `pkgs`, use the package from `pkgs.__splicedPackages`.
370 # 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
373 # nix-repl> darwin.apple_sdk.frameworks.CoreFoundation
374 # «derivation ...CoreFoundation-11.0.0.drv»
375 # nix-repl> darwin.CoreFoundation
376 # error: attribute 'CoreFoundation' missing
377 # nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { }
378 # «derivation ...CoreFoundation-11.0.0.drv»
380 , extra ? (_spliced0: {})
384 spliced0 = splicePackages {
385 pkgsBuildBuild = otherSplices.selfBuildBuild;
386 pkgsBuildHost = otherSplices.selfBuildHost;
387 pkgsBuildTarget = otherSplices.selfBuildTarget;
388 pkgsHostHost = otherSplices.selfHostHost;
389 pkgsHostTarget = self; # Not `otherSplices.selfHostTarget`;
390 pkgsTargetTarget = otherSplices.selfTargetTarget;
392 spliced = extra spliced0 // spliced0 // keep self;
394 newScope = scope: newScope (spliced // scope);
395 callPackage = newScope spliced; # == self.newScope {};
396 # N.B. the other stages of the package set spliced in are *not*
398 overrideScope = g: (makeScopeWithSplicing'
399 { inherit splicePackages newScope; }
400 { inherit otherSplices keep extra;