at 15.09-beta 5.5 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 overriden 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 ~/.nixpkgs/config.nix). For instance, if you 19 want to "patch" the derivation returned by a package function in 20 Nixpkgs to build another version than what the function itself 21 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 = f: origArgs: 55 let 56 ff = f origArgs; 57 overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs); 58 in 59 if builtins.isAttrs ff then (ff // 60 { override = newArgs: makeOverridable f (overrideWith newArgs); 61 overrideDerivation = fdrv: 62 makeOverridable (args: overrideDerivation (f args) fdrv) origArgs; 63 }) 64 else if builtins.isFunction ff then 65 { override = newArgs: makeOverridable f (overrideWith newArgs); 66 __functor = self: ff; 67 overrideDerivation = throw "overrideDerivation not yet supported for functors"; 68 } 69 else ff; 70 71 72 /* Call the package function in the file `fn' with the required 73 arguments automatically. The function is called with the 74 arguments `args', but any missing arguments are obtained from 75 `autoArgs'. This function is intended to be partially 76 parameterised, e.g., 77 78 callPackage = callPackageWith pkgs; 79 pkgs = { 80 libfoo = callPackage ./foo.nix { }; 81 libbar = callPackage ./bar.nix { }; 82 }; 83 84 If the `libbar' function expects an argument named `libfoo', it is 85 automatically passed as an argument. Overrides or missing 86 arguments can be supplied in `args', e.g. 87 88 libbar = callPackage ./bar.nix { 89 libfoo = null; 90 enableX11 = true; 91 }; 92 */ 93 callPackageWith = autoArgs: fn: args: 94 let 95 f = if builtins.isFunction fn then fn else import fn; 96 auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs; 97 in makeOverridable f (auto // args); 98 99 100 /* Like callPackage, but for a function that returns an attribute 101 set of derivations. The override function is added to the 102 individual attributes. */ 103 callPackagesWith = autoArgs: fn: args: 104 let 105 f = if builtins.isFunction fn then fn else import fn; 106 auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs; 107 finalArgs = auto // args; 108 pkgs = f finalArgs; 109 mkAttrOverridable = name: pkg: pkg // { 110 override = newArgs: mkAttrOverridable name (f (finalArgs // newArgs)).${name}; 111 }; 112 in lib.mapAttrs mkAttrOverridable pkgs; 113 114 115 /* Add attributes to each output of a derivation without changing 116 the derivation itself. */ 117 addPassthru = drv: passthru: 118 let 119 outputs = drv.outputs or [ "out" ]; 120 121 commonAttrs = drv // (builtins.listToAttrs outputsList) // 122 ({ all = map (x: x.value) outputsList; }) // passthru; 123 124 outputToAttrListElement = outputName: 125 { name = outputName; 126 value = commonAttrs // { 127 inherit (drv.${outputName}) outPath drvPath type outputName; 128 }; 129 }; 130 131 outputsList = map outputToAttrListElement outputs; 132 in commonAttrs.${drv.outputName}; 133 134 135 /* Strip a derivation of all non-essential attributes, returning 136 only those needed by hydra-eval-jobs. Also strictly evaluate the 137 result to ensure that there are no thunks kept alive to prevent 138 garbage collection. */ 139 hydraJob = drv: 140 let 141 outputs = drv.outputs or ["out"]; 142 143 commonAttrs = 144 { inherit (drv) name system meta; inherit outputs; } 145 // lib.optionalAttrs (drv._hydraAggregate or false) { 146 _hydraAggregate = true; 147 constituents = map hydraJob (lib.flatten drv.constituents); 148 } 149 // (lib.listToAttrs outputsList); 150 151 makeOutput = outputName: 152 let output = drv.${outputName}; in 153 { name = outputName; 154 value = commonAttrs // { 155 outPath = output.outPath; 156 drvPath = output.drvPath; 157 type = "derivation"; 158 inherit outputName; 159 }; 160 }; 161 162 outputsList = map makeOutput outputs; 163 164 drv' = (lib.head outputsList).value; 165 in lib.deepSeq drv' drv'; 166 167}