lol
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 24.11-pre 174 lines 7.1 kB view raw
1# The `splicedPackages' package set, and its use by `callPackage` 2# 3# The `buildPackages` pkg set is a new concept, and the vast majority package 4# expression (the other *.nix files) are not designed with it in mind. This 5# presents us with a problem with how to get the right version (build-time vs 6# run-time) of a package to a consumer that isn't used to thinking so cleverly. 7# 8# The solution is to splice the package sets together as we do below, so every 9# `callPackage`d expression in fact gets both versions. Each derivation (and 10# each derivation's outputs) consists of the run-time version, augmented with 11# a `__spliced.buildHost` field for the build-time version, and 12# `__spliced.hostTarget` field for the run-time version. 13# 14# For performance reasons, rather than uniformally splice in all cases, we only 15# do so when `pkgs` and `buildPackages` are distinct. The `actuallySplice` 16# parameter there the boolean value of that equality check. 17lib: pkgs: actuallySplice: 18 19let 20 21 spliceReal = 22 { pkgsBuildBuild 23 , pkgsBuildHost 24 , pkgsBuildTarget 25 , pkgsHostHost 26 , pkgsHostTarget 27 , pkgsTargetTarget 28 }: 29 let 30 mash = 31 # Other pkgs sets 32 pkgsBuildBuild // pkgsBuildTarget // pkgsHostHost // pkgsTargetTarget 33 # The same pkgs sets one probably intends 34 // pkgsBuildHost // pkgsHostTarget; 35 merge = name: { 36 inherit name; 37 value = 38 let 39 defaultValue = mash.${name}; 40 # `or {}` is for the non-derivation attsert splicing case, where `{}` is the identity. 41 valueBuildBuild = pkgsBuildBuild.${name} or { }; 42 valueBuildHost = pkgsBuildHost.${name} or { }; 43 valueBuildTarget = pkgsBuildTarget.${name} or { }; 44 valueHostHost = pkgsHostHost.${name} or { }; 45 valueHostTarget = pkgsHostTarget.${name} or { }; 46 valueTargetTarget = pkgsTargetTarget.${name} or { }; 47 augmentedValue = defaultValue 48 // { 49 __spliced = 50 (lib.optionalAttrs (pkgsBuildBuild ? ${name}) { buildBuild = valueBuildBuild; }) 51 // (lib.optionalAttrs (pkgsBuildHost ? ${name}) { buildHost = valueBuildHost; }) 52 // (lib.optionalAttrs (pkgsBuildTarget ? ${name}) { buildTarget = valueBuildTarget; }) 53 // (lib.optionalAttrs (pkgsHostHost ? ${name}) { hostHost = valueHostHost; }) 54 // (lib.optionalAttrs (pkgsHostTarget ? ${name}) { hostTarget = valueHostTarget; }) 55 // (lib.optionalAttrs (pkgsTargetTarget ? ${name}) { 56 targetTarget = valueTargetTarget; 57 }); 58 }; 59 # Get the set of outputs of a derivation. If one derivation fails to 60 # evaluate we don't want to diverge the entire splice, so we fall back 61 # on {} 62 tryGetOutputs = value0: 63 let 64 inherit (builtins.tryEval value0) success value; 65 in 66 getOutputs (lib.optionalAttrs success value); 67 getOutputs = value: lib.genAttrs 68 (value.outputs or (lib.optional (value ? out) "out")) 69 (output: value.${output}); 70 in 71 # The derivation along with its outputs, which we recur 72 # on to splice them together. 73 if lib.isDerivation defaultValue then augmentedValue // spliceReal { 74 pkgsBuildBuild = tryGetOutputs valueBuildBuild; 75 pkgsBuildHost = tryGetOutputs valueBuildHost; 76 pkgsBuildTarget = tryGetOutputs valueBuildTarget; 77 pkgsHostHost = tryGetOutputs valueHostHost; 78 pkgsHostTarget = getOutputs valueHostTarget; 79 pkgsTargetTarget = tryGetOutputs valueTargetTarget; 80 # Just recur on plain attrsets 81 } else if lib.isAttrs defaultValue then 82 spliceReal 83 { 84 pkgsBuildBuild = valueBuildBuild; 85 pkgsBuildHost = valueBuildHost; 86 pkgsBuildTarget = valueBuildTarget; 87 pkgsHostHost = valueHostHost; 88 pkgsHostTarget = valueHostTarget; 89 pkgsTargetTarget = valueTargetTarget; 90 # Don't be fancy about non-derivations. But we could have used used 91 # `__functor__` for functions instead. 92 } else defaultValue; 93 }; 94 in 95 lib.listToAttrs (map merge (lib.attrNames mash)); 96 97 splicePackages = 98 { pkgsBuildBuild 99 , pkgsBuildHost 100 , pkgsBuildTarget 101 , pkgsHostHost 102 , pkgsHostTarget 103 , pkgsTargetTarget 104 } @ args: 105 if actuallySplice then spliceReal args else pkgsHostTarget; 106 107 splicedPackages = splicePackages 108 { 109 inherit (pkgs) 110 pkgsBuildBuild pkgsBuildHost pkgsBuildTarget 111 pkgsHostHost pkgsHostTarget 112 pkgsTargetTarget 113 ; 114 } // { 115 # These should never be spliced under any circumstances 116 inherit (pkgs) 117 pkgsBuildBuild pkgsBuildHost pkgsBuildTarget 118 pkgsHostHost pkgsHostTarget 119 pkgsTargetTarget 120 buildPackages pkgs targetPackages 121 ; 122 inherit (pkgs.stdenv) buildPlatform targetPlatform hostPlatform; 123 }; 124 125 splicedPackagesWithXorg = splicedPackages // builtins.removeAttrs splicedPackages.xorg [ 126 "callPackage" 127 "newScope" 128 "overrideScope" 129 "packages" 130 ]; 131 132in 133 134{ 135 inherit splicePackages; 136 137 # We use `callPackage' to be able to omit function arguments that can be 138 # obtained `pkgs` or `buildPackages` and their `xorg` package sets. Use 139 # `newScope' for sets of packages in `pkgs' (see e.g. `gnome' below). 140 callPackage = pkgs.newScope { }; 141 142 callPackages = lib.callPackagesWith splicedPackagesWithXorg; 143 144 newScope = extra: lib.callPackageWith (splicedPackagesWithXorg // extra); 145 146 # prefill 2 fields of the function for convenience 147 makeScopeWithSplicing = lib.makeScopeWithSplicing splicePackages pkgs.newScope; 148 makeScopeWithSplicing' = lib.makeScopeWithSplicing' { inherit splicePackages; inherit (pkgs) newScope; }; 149 150 # generate 'otherSplices' for 'makeScopeWithSplicing' 151 generateSplicesForMkScope = attrs: 152 let 153 split = X: [ X ] ++ ( 154 if builtins.isList attrs 155 then attrs 156 else if builtins.isString attrs 157 then lib.splitString "." attrs 158 else throw "generateSplicesForMkScope must be passed a list of string or string" 159 ); 160 bad = throw "attribute should be found"; 161 in 162 { 163 selfBuildBuild = lib.attrByPath (split "pkgsBuildBuild") bad pkgs; 164 selfBuildHost = lib.attrByPath (split "pkgsBuildHost") bad pkgs; 165 selfBuildTarget = lib.attrByPath (split "pkgsBuildTarget") bad pkgs; 166 selfHostHost = lib.attrByPath (split "pkgsHostHost") bad pkgs; 167 selfHostTarget = lib.attrByPath (split "pkgsHostTarget") bad pkgs; 168 selfTargetTarget = lib.attrByPath (split "pkgsTargetTarget") { } pkgs; 169 }; 170 171 # Haskell package sets need this because they reimplement their own 172 # `newScope`. 173 __splicedPackages = splicedPackages // { recurseForDerivations = false; }; 174}