at 23.11-beta 3.9 kB view raw
1{ lib }: 2 3let 4 inherit (lib) throwIfNot; 5in 6{ 7 /* 8 Restrict a derivation to a predictable set of attribute names, so 9 that the returned attrset is not strict in the actual derivation, 10 saving a lot of computation when the derivation is non-trivial. 11 12 This is useful in situations where a derivation might only be used for its 13 passthru attributes, improving evaluation performance. 14 15 The returned attribute set is lazy in `derivation`. Specifically, this 16 means that the derivation will not be evaluated in at least the 17 situations below. 18 19 For illustration and/or testing, we define derivation such that its 20 evaluation is very noticeable. 21 22 let derivation = throw "This won't be evaluated."; 23 24 In the following expressions, `derivation` will _not_ be evaluated: 25 26 (lazyDerivation { inherit derivation; }).type 27 28 attrNames (lazyDerivation { inherit derivation; }) 29 30 (lazyDerivation { inherit derivation; } // { foo = true; }).foo 31 32 (lazyDerivation { inherit derivation; meta.foo = true; }).meta 33 34 In these expressions, `derivation` _will_ be evaluated: 35 36 "${lazyDerivation { inherit derivation }}" 37 38 (lazyDerivation { inherit derivation }).outPath 39 40 (lazyDerivation { inherit derivation }).meta 41 42 And the following expressions are not valid, because the refer to 43 implementation details and/or attributes that may not be present on 44 some derivations: 45 46 (lazyDerivation { inherit derivation }).buildInputs 47 48 (lazyDerivation { inherit derivation }).passthru 49 50 (lazyDerivation { inherit derivation }).pythonPath 51 52 */ 53 lazyDerivation = 54 args@{ 55 # The derivation to be wrapped. 56 derivation 57 , # Optional meta attribute. 58 # 59 # While this function is primarily about derivations, it can improve 60 # the `meta` package attribute, which is usually specified through 61 # `mkDerivation`. 62 meta ? null 63 , # Optional extra values to add to the returned attrset. 64 # 65 # This can be used for adding package attributes, such as `tests`. 66 passthru ? { } 67 }: 68 let 69 # These checks are strict in `drv` and some `drv` attributes, but the 70 # attrset spine returned by lazyDerivation does not depend on it. 71 # Instead, the individual derivation attributes do depend on it. 72 checked = 73 throwIfNot (derivation.type or null == "derivation") 74 "lazySimpleDerivation: input must be a derivation." 75 throwIfNot 76 (derivation.outputs == [ "out" ]) 77 # Supporting multiple outputs should be a matter of inheriting more attrs. 78 "The derivation ${derivation.name or "<unknown>"} has multiple outputs. This is not supported by lazySimpleDerivation yet. Support could be added, and be useful as long as the set of outputs is known in advance, without evaluating the actual derivation." 79 derivation; 80 in 81 { 82 # Hardcoded `type` 83 # 84 # `lazyDerivation` requires its `derivation` argument to be a derivation, 85 # so if it is not, that is a programming error by the caller and not 86 # something that `lazyDerivation` consumers should be able to correct 87 # for after the fact. 88 # So, to improve laziness, we assume correctness here and check it only 89 # when actual derivation values are accessed later. 90 type = "derivation"; 91 92 # A fixed set of derivation values, so that `lazyDerivation` can return 93 # its attrset before evaluating `derivation`. 94 # This must only list attributes that are available on _all_ derivations. 95 inherit (checked) outputs out outPath outputName drvPath name system; 96 97 # The meta attribute can either be taken from the derivation, or if the 98 # `lazyDerivation` caller knew a shortcut, be taken from there. 99 meta = args.meta or checked.meta; 100 } // passthru; 101}