at 17.09-beta 7.3 kB view raw
1let 2 3 lib = import ./default.nix; 4 inherit (builtins) attrNames isFunction; 5 6in 7 8rec { 9 10 11 /* `overrideDerivation drv f' takes a derivation (i.e., the result 12 of a call to the builtin function `derivation') and returns a new 13 derivation in which the attributes of the original are overridden 14 according to the function `f'. The function `f' is called with 15 the original derivation attributes. 16 17 `overrideDerivation' allows certain "ad-hoc" customisation 18 scenarios (e.g. in ~/.config/nixpkgs/config.nix). For instance, 19 if you want to "patch" the derivation returned by a package 20 function in Nixpkgs to build another version than what the 21 function itself provides, you can do something like this: 22 23 mySed = overrideDerivation pkgs.gnused (oldAttrs: { 24 name = "sed-4.2.2-pre"; 25 src = fetchurl { 26 url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2; 27 sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k"; 28 }; 29 patches = []; 30 }); 31 32 For another application, see build-support/vm, where this 33 function is used to build arbitrary derivations inside a QEMU 34 virtual machine. 35 */ 36 overrideDerivation = drv: f: 37 let 38 newDrv = derivation (drv.drvAttrs // (f drv)); 39 in addPassthru newDrv ( 40 { meta = drv.meta or {}; 41 passthru = if drv ? passthru then drv.passthru else {}; 42 } 43 // 44 (drv.passthru or {}) 45 // 46 (if (drv ? crossDrv && drv ? nativeDrv) 47 then { 48 crossDrv = overrideDerivation drv.crossDrv f; 49 nativeDrv = overrideDerivation drv.nativeDrv f; 50 } 51 else { })); 52 53 54 /* `makeOverridable` takes a function from attribute set to attribute set and 55 injects `override` attibute which can be used to override arguments of 56 the function. 57 58 nix-repl> x = {a, b}: { result = a + b; } 59 60 nix-repl> y = lib.makeOverridable x { a = 1; b = 2; } 61 62 nix-repl> y 63 { override = «lambda»; overrideDerivation = «lambda»; result = 3; } 64 65 nix-repl> y.override { a = 10; } 66 { override = «lambda»; overrideDerivation = «lambda»; result = 12; } 67 68 Please refer to "Nixpkgs Contributors Guide" section 69 "<pkg>.overrideDerivation" to learn about `overrideDerivation` and caveats 70 related to its use. 71 */ 72 makeOverridable = f: origArgs: 73 let 74 ff = f origArgs; 75 overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs); 76 in 77 if builtins.isAttrs ff then (ff // { 78 override = newArgs: makeOverridable f (overrideWith newArgs); 79 overrideDerivation = fdrv: 80 makeOverridable (args: overrideDerivation (f args) fdrv) origArgs; 81 ${if ff ? overrideAttrs then "overrideAttrs" else null} = fdrv: 82 makeOverridable (args: (f args).overrideAttrs fdrv) origArgs; 83 }) 84 else if builtins.isFunction ff then { 85 override = newArgs: makeOverridable f (overrideWith newArgs); 86 __functor = self: ff; 87 overrideDerivation = throw "overrideDerivation not yet supported for functors"; 88 } 89 else ff; 90 91 92 /* Call the package function in the file `fn' with the required 93 arguments automatically. The function is called with the 94 arguments `args', but any missing arguments are obtained from 95 `autoArgs'. This function is intended to be partially 96 parameterised, e.g., 97 98 callPackage = callPackageWith pkgs; 99 pkgs = { 100 libfoo = callPackage ./foo.nix { }; 101 libbar = callPackage ./bar.nix { }; 102 }; 103 104 If the `libbar' function expects an argument named `libfoo', it is 105 automatically passed as an argument. Overrides or missing 106 arguments can be supplied in `args', e.g. 107 108 libbar = callPackage ./bar.nix { 109 libfoo = null; 110 enableX11 = true; 111 }; 112 */ 113 callPackageWith = autoArgs: fn: args: 114 let 115 f = if builtins.isFunction fn then fn else import fn; 116 auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs; 117 in makeOverridable f (auto // args); 118 119 120 /* Like callPackage, but for a function that returns an attribute 121 set of derivations. The override function is added to the 122 individual attributes. */ 123 callPackagesWith = autoArgs: fn: args: 124 let 125 f = if builtins.isFunction fn then fn else import fn; 126 auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs; 127 origArgs = auto // args; 128 pkgs = f origArgs; 129 mkAttrOverridable = name: pkg: makeOverridable (newArgs: (f newArgs).${name}) origArgs; 130 in lib.mapAttrs mkAttrOverridable pkgs; 131 132 133 /* Add attributes to each output of a derivation without changing 134 the derivation itself. */ 135 addPassthru = drv: passthru: 136 let 137 outputs = drv.outputs or [ "out" ]; 138 139 commonAttrs = drv // (builtins.listToAttrs outputsList) // 140 ({ all = map (x: x.value) outputsList; }) // passthru; 141 142 outputToAttrListElement = outputName: 143 { name = outputName; 144 value = commonAttrs // { 145 inherit (drv.${outputName}) outPath drvPath type outputName; 146 }; 147 }; 148 149 outputsList = map outputToAttrListElement outputs; 150 in commonAttrs // { outputUnspecified = true; }; 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 overrideScope = g: 199 makeScope newScope 200 (self_: let super = f self_; in super // g super self_); 201 packages = f; 202 }; 203 in self; 204 205}