at 18.09-beta 7.5 kB view raw
1{ lib }: 2 3rec { 4 5 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. 11 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: 17 18 mySed = overrideDerivation pkgs.gnused (oldAttrs: { 19 name = "sed-4.2.2-pre"; 20 src = fetchurl { 21 url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2; 22 sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k"; 23 }; 24 patches = []; 25 }); 26 27 For another application, see build-support/vm, where this 28 function is used to build arbitrary derivations inside a QEMU 29 virtual machine. 30 */ 31 overrideDerivation = drv: f: 32 let 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 {}; 37 } 38 // 39 (drv.passthru or {}) 40 // 41 (if (drv ? crossDrv && drv ? nativeDrv) 42 then { 43 crossDrv = overrideDerivation drv.crossDrv f; 44 nativeDrv = overrideDerivation drv.nativeDrv f; 45 } 46 else { })); 47 48 49 /* `makeOverridable` takes a function from attribute set to attribute set and 50 injects `override` attibute which can be used to override arguments of 51 the function. 52 53 nix-repl> x = {a, b}: { result = a + b; } 54 55 nix-repl> y = lib.makeOverridable x { a = 1; b = 2; } 56 57 nix-repl> y 58 { override = «lambda»; overrideDerivation = «lambda»; result = 3; } 59 60 nix-repl> y.override { a = 10; } 61 { override = «lambda»; overrideDerivation = «lambda»; result = 12; } 62 63 Please refer to "Nixpkgs Contributors Guide" section 64 "<pkg>.overrideDerivation" to learn about `overrideDerivation` and caveats 65 related to its use. 66 */ 67 makeOverridable = f: origArgs: 68 let 69 ff = f origArgs; 70 overrideWith = newArgs: origArgs // (if lib.isFunction newArgs then newArgs origArgs else newArgs); 71 in 72 if builtins.isAttrs ff then (ff // { 73 override = newArgs: makeOverridable f (overrideWith newArgs); 74 overrideDerivation = fdrv: 75 makeOverridable (args: overrideDerivation (f args) fdrv) origArgs; 76 ${if ff ? overrideAttrs then "overrideAttrs" else null} = fdrv: 77 makeOverridable (args: (f args).overrideAttrs fdrv) origArgs; 78 }) 79 else if lib.isFunction ff then { 80 override = newArgs: makeOverridable f (overrideWith newArgs); 81 __functor = self: ff; 82 overrideDerivation = throw "overrideDerivation not yet supported for functors"; 83 } 84 else ff; 85 86 87 /* Call the package function in the file `fn' with the required 88 arguments automatically. The function is called with the 89 arguments `args', but any missing arguments are obtained from 90 `autoArgs'. This function is intended to be partially 91 parameterised, e.g., 92 93 callPackage = callPackageWith pkgs; 94 pkgs = { 95 libfoo = callPackage ./foo.nix { }; 96 libbar = callPackage ./bar.nix { }; 97 }; 98 99 If the `libbar' function expects an argument named `libfoo', it is 100 automatically passed as an argument. Overrides or missing 101 arguments can be supplied in `args', e.g. 102 103 libbar = callPackage ./bar.nix { 104 libfoo = null; 105 enableX11 = true; 106 }; 107 */ 108 callPackageWith = autoArgs: fn: args: 109 let 110 f = if lib.isFunction fn then fn else import fn; 111 auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs; 112 in makeOverridable f (auto // args); 113 114 115 /* Like callPackage, but for a function that returns an attribute 116 set of derivations. The override function is added to the 117 individual attributes. */ 118 callPackagesWith = autoArgs: fn: args: 119 let 120 f = if lib.isFunction fn then fn else import fn; 121 auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs; 122 origArgs = auto // args; 123 pkgs = f origArgs; 124 mkAttrOverridable = name: pkg: makeOverridable (newArgs: (f newArgs).${name}) origArgs; 125 in lib.mapAttrs mkAttrOverridable pkgs; 126 127 128 /* Add attributes to each output of a derivation without changing 129 the derivation itself and check a given condition when evaluating. */ 130 extendDerivation = condition: passthru: drv: 131 let 132 outputs = drv.outputs or [ "out" ]; 133 134 commonAttrs = drv // (builtins.listToAttrs outputsList) // 135 ({ all = map (x: x.value) outputsList; }) // passthru; 136 137 outputToAttrListElement = outputName: 138 { name = outputName; 139 value = commonAttrs // { 140 inherit (drv.${outputName}) type outputName; 141 drvPath = assert condition; drv.${outputName}.drvPath; 142 outPath = assert condition; drv.${outputName}.outPath; 143 }; 144 }; 145 146 outputsList = map outputToAttrListElement outputs; 147 in commonAttrs // { 148 outputUnspecified = true; 149 drvPath = assert condition; drv.drvPath; 150 outPath = assert condition; drv.outPath; 151 }; 152 153 /* Strip a derivation of all non-essential attributes, returning 154 only those needed by hydra-eval-jobs. Also strictly evaluate the 155 result to ensure that there are no thunks kept alive to prevent 156 garbage collection. */ 157 hydraJob = drv: 158 let 159 outputs = drv.outputs or ["out"]; 160 161 commonAttrs = 162 { inherit (drv) name system meta; inherit outputs; } 163 // lib.optionalAttrs (drv._hydraAggregate or false) { 164 _hydraAggregate = true; 165 constituents = map hydraJob (lib.flatten drv.constituents); 166 } 167 // (lib.listToAttrs outputsList); 168 169 makeOutput = outputName: 170 let output = drv.${outputName}; in 171 { name = outputName; 172 value = commonAttrs // { 173 outPath = output.outPath; 174 drvPath = output.drvPath; 175 type = "derivation"; 176 inherit outputName; 177 }; 178 }; 179 180 outputsList = map makeOutput outputs; 181 182 drv' = (lib.head outputsList).value; 183 in lib.deepSeq drv' drv'; 184 185 /* Make a set of packages with a common scope. All packages called 186 with the provided `callPackage' will be evaluated with the same 187 arguments. Any package in the set may depend on any other. The 188 `overrideScope' function allows subsequent modification of the package 189 set in a consistent way, i.e. all packages in the set will be 190 called with the overridden packages. The package sets may be 191 hierarchical: the packages in the set are called with the scope 192 provided by `newScope' and the set provides a `newScope' attribute 193 which can form the parent scope for later package sets. */ 194 makeScope = newScope: f: 195 let self = f self // { 196 newScope = scope: newScope (self // scope); 197 callPackage = self.newScope {}; 198 # TODO(@Ericson2314): Haromonize argument order of `g` with everything else 199 overrideScope = g: 200 makeScope newScope 201 (lib.fixedPoints.extends (lib.flip g) f); 202 packages = f; 203 }; 204 in self; 205 206}