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 # TODO(@Artturin): remove before release 23.05 and only have __spliced.
42 (lib.optionalAttrs (drv ? crossDrv && drv ? nativeDrv) {
43 crossDrv = overrideDerivation drv.crossDrv f;
44 nativeDrv = overrideDerivation drv.nativeDrv f;
47 lib.optionalAttrs (drv ? __spliced) {
48 __spliced = {} // (lib.mapAttrs (_: sDrv: overrideDerivation sDrv f) drv.__spliced);
52 /* `makeOverridable` takes a function from attribute set to attribute set and
53 injects `override` attribute which can be used to override arguments of
56 nix-repl> x = {a, b}: { result = a + b; }
58 nix-repl> y = lib.makeOverridable x { a = 1; b = 2; }
61 { override = «lambda»; overrideDerivation = «lambda»; result = 3; }
63 nix-repl> y.override { a = 10; }
64 { override = «lambda»; overrideDerivation = «lambda»; result = 12; }
66 Please refer to "Nixpkgs Contributors Guide" section
67 "<pkg>.overrideDerivation" to learn about `overrideDerivation` and caveats
70 makeOverridable = f: origArgs:
74 # Creates a functor with the same arguments as f
75 copyArgs = g: lib.setFunctionArgs g (lib.functionArgs f);
76 # Changes the original arguments with (potentially a function that returns) a set of new attributes
77 overrideWith = newArgs: origArgs // (if lib.isFunction newArgs then newArgs origArgs else newArgs);
79 # Re-call the function but with different arguments
80 overrideArgs = copyArgs (newArgs: makeOverridable f (overrideWith newArgs));
81 # Change the result of the function call by applying g to it
82 overrideResult = g: makeOverridable (copyArgs (args: g (f args))) origArgs;
84 if builtins.isAttrs result then
86 override = overrideArgs;
87 overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
88 ${if result ? overrideAttrs then "overrideAttrs" else null} = fdrv:
89 overrideResult (x: x.overrideAttrs fdrv);
91 else if lib.isFunction result then
92 # Transform the result into a functor while propagating its arguments
93 lib.setFunctionArgs result (lib.functionArgs result) // {
94 override = overrideArgs;
99 /* Call the package function in the file `fn' with the required
100 arguments automatically. The function is called with the
101 arguments `args', but any missing arguments are obtained from
102 `autoArgs'. This function is intended to be partially
105 callPackage = callPackageWith pkgs;
107 libfoo = callPackage ./foo.nix { };
108 libbar = callPackage ./bar.nix { };
111 If the `libbar' function expects an argument named `libfoo', it is
112 automatically passed as an argument. Overrides or missing
113 arguments can be supplied in `args', e.g.
115 libbar = callPackage ./bar.nix {
120 callPackageWith = autoArgs: fn: args:
122 f = if lib.isFunction fn then fn else import fn;
123 fargs = lib.functionArgs f;
125 # All arguments that will be passed to the function
126 # This includes automatic ones and ones passed explicitly
127 allArgs = builtins.intersectAttrs fargs autoArgs // args;
129 # A list of argument names that the function requires, but
130 # wouldn't be passed to it
131 missingArgs = lib.attrNames
132 # Filter out arguments that have a default value
133 (lib.filterAttrs (name: value: ! value)
134 # Filter out arguments that would be passed
135 (removeAttrs fargs (lib.attrNames allArgs)));
137 # Get a list of suggested argument names for a given missing one
138 getSuggestions = arg: lib.pipe (autoArgs // args) [
140 # Only use ones that are at most 2 edits away. While mork would work,
141 # levenshteinAtMost is only fast for 2 or less.
142 (lib.filter (lib.strings.levenshteinAtMost 2 arg))
143 # Put strings with shorter distance first
144 (lib.sort (x: y: lib.strings.levenshtein x arg < lib.strings.levenshtein y arg))
145 # Only take the first couple results
148 (map (x: "\"" + x + "\""))
151 prettySuggestions = suggestions:
152 if suggestions == [] then ""
153 else if lib.length suggestions == 1 then ", did you mean ${lib.elemAt suggestions 0}?"
154 else ", did you mean ${lib.concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
158 loc = builtins.unsafeGetAttrPos arg fargs;
159 # loc' can be removed once lib/minver.nix is >2.3.4, since that includes
160 # https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
161 loc' = if loc != null then loc.file + ":" + toString loc.line
162 else if ! lib.isFunction fn then
163 toString fn + lib.optionalString (lib.sources.pathIsDirectory fn) "/default.nix"
164 else "<unknown location>";
165 in "Function called without required argument \"${arg}\" at "
166 + "${loc'}${prettySuggestions (getSuggestions arg)}";
168 # Only show the error for the first missing argument
169 error = errorForArg (lib.head missingArgs);
171 in if missingArgs == [] then makeOverridable f allArgs else throw error;
174 /* Like callPackage, but for a function that returns an attribute
175 set of derivations. The override function is added to the
176 individual attributes. */
177 callPackagesWith = autoArgs: fn: args:
179 f = if lib.isFunction fn then fn else import fn;
180 auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
181 origArgs = auto // args;
183 mkAttrOverridable = name: _: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
185 if lib.isDerivation pkgs then throw
186 ("function `callPackages` was called on a *single* derivation "
187 + ''"${pkgs.name or "<unknown-name>"}";''
188 + " did you mean to use `callPackage` instead?")
189 else lib.mapAttrs mkAttrOverridable pkgs;
192 /* Add attributes to each output of a derivation without changing
193 the derivation itself and check a given condition when evaluating. */
194 extendDerivation = condition: passthru: drv:
196 outputs = drv.outputs or [ "out" ];
198 commonAttrs = drv // (builtins.listToAttrs outputsList) //
199 ({ all = map (x: x.value) outputsList; }) // passthru;
201 outputToAttrListElement = outputName:
203 value = commonAttrs // {
204 inherit (drv.${outputName}) type outputName;
205 outputSpecified = true;
206 drvPath = assert condition; drv.${outputName}.drvPath;
207 outPath = assert condition; drv.${outputName}.outPath;
211 outputsList = map outputToAttrListElement outputs;
213 drvPath = assert condition; drv.drvPath;
214 outPath = assert condition; drv.outPath;
217 /* Strip a derivation of all non-essential attributes, returning
218 only those needed by hydra-eval-jobs. Also strictly evaluate the
219 result to ensure that there are no thunks kept alive to prevent
220 garbage collection. */
223 outputs = drv.outputs or ["out"];
226 { inherit (drv) name system meta; inherit outputs; }
227 // lib.optionalAttrs (drv._hydraAggregate or false) {
228 _hydraAggregate = true;
229 constituents = map hydraJob (lib.flatten drv.constituents);
231 // (lib.listToAttrs outputsList);
233 makeOutput = outputName:
234 let output = drv.${outputName}; in
236 value = commonAttrs // {
237 outPath = output.outPath;
238 drvPath = output.drvPath;
244 outputsList = map makeOutput outputs;
246 drv' = (lib.head outputsList).value;
247 in lib.deepSeq drv' drv';
249 /* Make a set of packages with a common scope. All packages called
250 with the provided `callPackage' will be evaluated with the same
251 arguments. Any package in the set may depend on any other. The
252 `overrideScope'` function allows subsequent modification of the package
253 set in a consistent way, i.e. all packages in the set will be
254 called with the overridden packages. The package sets may be
255 hierarchical: the packages in the set are called with the scope
256 provided by `newScope' and the set provides a `newScope' attribute
257 which can form the parent scope for later package sets. */
258 makeScope = newScope: f:
259 let self = f self // {
260 newScope = scope: newScope (self // scope);
261 callPackage = self.newScope {};
262 overrideScope = g: lib.warn
263 "`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."
264 (makeScope newScope (lib.fixedPoints.extends (lib.flip g) f));
265 overrideScope' = g: makeScope newScope (lib.fixedPoints.extends g f);
270 /* Like the above, but aims to support cross compilation. It's still ugly, but
271 hopefully it helps a little bit. */
272 makeScopeWithSplicing = splicePackages: newScope: otherSplices: keep: extra: f:
274 spliced0 = splicePackages {
275 pkgsBuildBuild = otherSplices.selfBuildBuild;
276 pkgsBuildHost = otherSplices.selfBuildHost;
277 pkgsBuildTarget = otherSplices.selfBuildTarget;
278 pkgsHostHost = otherSplices.selfHostHost;
279 pkgsHostTarget = self; # Not `otherSplices.selfHostTarget`;
280 pkgsTargetTarget = otherSplices.selfTargetTarget;
282 spliced = extra spliced0 // spliced0 // keep self;
284 newScope = scope: newScope (spliced // scope);
285 callPackage = newScope spliced; # == self.newScope {};
286 # N.B. the other stages of the package set spliced in are *not*
288 overrideScope = g: makeScopeWithSplicing
294 (lib.fixedPoints.extends g f);