ea7c2e29be
All these 062c4f5974/pkgs/top-level/splice.nix (L116-L121)
are already in pkgs, so they don't have to be added on top again when there's no splicing
|stat | before | after | Δ | Δ% |
|----------------------|----------------|----------------|----------------|-------|
|cpuTime | 767.33 | 757.25 | ↘ 10.08 | -1.31%|
|envs-bytes | 23,767,294,088 | 23,767,243,520 | ↘ 50,568 | -0.00%|
|envs-elements | 1,260,156,605 | 1,260,151,924 | ↘ 4,681 | -0.00%|
|envs-number | 855,377,578 | 855,376,758 | ↘ 820 | -0.00%|
|gc-heapSize | 66,525,835,264 | 64,428,679,168 | ↘ 2,097,156,096| -3.15%|
|gc-totalBytes | 146,231,201,712| 145,437,495,488| ↘ 793,706,224 | -0.54%|
|list-bytes | 3,319,349,160 | 3,319,349,160 | 0 | |
|list-concats | 88,567,304 | 88,567,304 | 0 | |
|list-elements | 414,918,645 | 414,918,645 | 0 | |
|nrAvoided | 989,429,178 | 989,427,108 | ↘ 2,070 | -0.00%|
|nrFunctionCalls | 784,049,358 | 784,048,538 | ↘ 820 | -0.00%|
|nrLookups | 412,401,378 | 412,399,016 | ↘ 2,362 | -0.00%|
|nrOpUpdateValuesCopied| 2,132,453,124 | 2,082,900,933 | ↘ 49,552,191 | -2.32%|
|nrOpUpdates | 99,050,775 | 99,048,489 | ↘ 2,286 | -0.00%|
|nrPrimOpCalls | 411,581,753 | 411,581,753 | 0 | |
|nrThunks | 1,248,612,305 | 1,248,600,848 | ↘ 11,457 | -0.00%|
|sets-bytes | 48,379,815,792 | 47,586,523,600 | ↘ 793,292,192 | -1.64%|
|sets-elements | 2,840,072,218 | 2,790,496,848 | ↘ 49,575,370 | -1.75%|
|sets-number | 183,666,269 | 183,660,877 | ↘ 5,392 | -0.00%|
|sizes-Attr | 16 | 16 | 0 | |
|sizes-Bindings | 16 | 16 | 0 | |
|sizes-Env | 16 | 16 | 0 | |
|sizes-Value | 24 | 24 | 0 | |
|symbols-bytes | 3,454,822 | 3,454,838 | ↗ 16 | 0.00% |
|symbols-number | 188,756 | 188,757 | ↗ 1 | 0.00% |
|values-bytes | 38,132,032,032 | 38,131,756,776 | ↘ 275,256 | -0.00%|
|values-number | 1,588,834,668 | 1,588,823,199 | ↘ 11,469 | -0.00%|
The table was formatted manually from stats copied from ofborg(I forgot how to do it properly), so it may
look a bit wonky
184 lines
7.1 KiB
Nix
184 lines
7.1 KiB
Nix
# The `splicedPackages' package set, and its use by `callPackage`
|
|
#
|
|
# The `buildPackages` pkg set is a new concept, and the vast majority package
|
|
# expression (the other *.nix files) are not designed with it in mind. This
|
|
# presents us with a problem with how to get the right version (build-time vs
|
|
# run-time) of a package to a consumer that isn't used to thinking so cleverly.
|
|
#
|
|
# The solution is to splice the package sets together as we do below, so every
|
|
# `callPackage`d expression in fact gets both versions. Each derivation (and
|
|
# each derivation's outputs) consists of the run-time version, augmented with
|
|
# a `__spliced.buildHost` field for the build-time version, and
|
|
# `__spliced.hostTarget` field for the run-time version.
|
|
#
|
|
# For performance reasons, rather than uniformally splice in all cases, we only
|
|
# do so when `pkgs` and `buildPackages` are distinct. The `actuallySplice`
|
|
# parameter there the boolean value of that equality check.
|
|
lib: pkgs: actuallySplice:
|
|
|
|
let
|
|
|
|
spliceReal =
|
|
{ pkgsBuildBuild
|
|
, pkgsBuildHost
|
|
, pkgsBuildTarget
|
|
, pkgsHostHost
|
|
, pkgsHostTarget
|
|
, pkgsTargetTarget
|
|
}:
|
|
let
|
|
mash =
|
|
# Other pkgs sets
|
|
pkgsBuildBuild // pkgsBuildTarget // pkgsHostHost // pkgsTargetTarget
|
|
# The same pkgs sets one probably intends
|
|
// pkgsBuildHost // pkgsHostTarget;
|
|
merge = name: {
|
|
inherit name;
|
|
value =
|
|
let
|
|
defaultValue = mash.${name};
|
|
# `or {}` is for the non-derivation attsert splicing case, where `{}` is the identity.
|
|
valueBuildBuild = pkgsBuildBuild.${name} or { };
|
|
valueBuildHost = pkgsBuildHost.${name} or { };
|
|
valueBuildTarget = pkgsBuildTarget.${name} or { };
|
|
valueHostHost = pkgsHostHost.${name} or { };
|
|
valueHostTarget = pkgsHostTarget.${name} or { };
|
|
valueTargetTarget = pkgsTargetTarget.${name} or { };
|
|
augmentedValue = defaultValue
|
|
// {
|
|
__spliced =
|
|
(lib.optionalAttrs (pkgsBuildBuild ? ${name}) { buildBuild = valueBuildBuild; })
|
|
// (lib.optionalAttrs (pkgsBuildHost ? ${name}) { buildHost = valueBuildHost; })
|
|
// (lib.optionalAttrs (pkgsBuildTarget ? ${name}) { buildTarget = valueBuildTarget; })
|
|
// (lib.optionalAttrs (pkgsHostHost ? ${name}) { hostHost = valueHostHost; })
|
|
// (lib.optionalAttrs (pkgsHostTarget ? ${name}) { hostTarget = valueHostTarget; })
|
|
// (lib.optionalAttrs (pkgsTargetTarget ? ${name}) {
|
|
targetTarget = valueTargetTarget;
|
|
});
|
|
};
|
|
# Get the set of outputs of a derivation. If one derivation fails to
|
|
# evaluate we don't want to diverge the entire splice, so we fall back
|
|
# on {}
|
|
tryGetOutputs = value0:
|
|
let
|
|
inherit (builtins.tryEval value0) success value;
|
|
in
|
|
getOutputs (lib.optionalAttrs success value);
|
|
getOutputs = value: lib.genAttrs
|
|
(value.outputs or (lib.optional (value ? out) "out"))
|
|
(output: value.${output});
|
|
in
|
|
# The derivation along with its outputs, which we recur
|
|
# on to splice them together.
|
|
if lib.isDerivation defaultValue then augmentedValue // spliceReal {
|
|
pkgsBuildBuild = tryGetOutputs valueBuildBuild;
|
|
pkgsBuildHost = tryGetOutputs valueBuildHost;
|
|
pkgsBuildTarget = tryGetOutputs valueBuildTarget;
|
|
pkgsHostHost = tryGetOutputs valueHostHost;
|
|
pkgsHostTarget = getOutputs valueHostTarget;
|
|
pkgsTargetTarget = tryGetOutputs valueTargetTarget;
|
|
# Just recur on plain attrsets
|
|
} else if lib.isAttrs defaultValue then
|
|
spliceReal
|
|
{
|
|
pkgsBuildBuild = valueBuildBuild;
|
|
pkgsBuildHost = valueBuildHost;
|
|
pkgsBuildTarget = valueBuildTarget;
|
|
pkgsHostHost = valueHostHost;
|
|
pkgsHostTarget = valueHostTarget;
|
|
pkgsTargetTarget = valueTargetTarget;
|
|
# Don't be fancy about non-derivations. But we could have used used
|
|
# `__functor__` for functions instead.
|
|
} else defaultValue;
|
|
};
|
|
in
|
|
lib.listToAttrs (map merge (lib.attrNames mash));
|
|
|
|
splicePackages =
|
|
{ pkgsBuildBuild
|
|
, pkgsBuildHost
|
|
, pkgsBuildTarget
|
|
, pkgsHostHost
|
|
, pkgsHostTarget
|
|
, pkgsTargetTarget
|
|
} @ args:
|
|
if actuallySplice then spliceReal args else pkgsHostTarget;
|
|
|
|
splicedPackages = splicePackages
|
|
{
|
|
inherit (pkgs)
|
|
pkgsBuildBuild pkgsBuildHost pkgsBuildTarget
|
|
pkgsHostHost pkgsHostTarget
|
|
pkgsTargetTarget
|
|
;
|
|
} // {
|
|
# These should never be spliced under any circumstances
|
|
inherit (pkgs)
|
|
pkgsBuildBuild pkgsBuildHost pkgsBuildTarget
|
|
pkgsHostHost pkgsHostTarget
|
|
pkgsTargetTarget
|
|
buildPackages pkgs targetPackages
|
|
;
|
|
inherit (pkgs.stdenv) buildPlatform targetPlatform hostPlatform;
|
|
};
|
|
|
|
splicedPackagesWithXorg = splicedPackages // builtins.removeAttrs splicedPackages.xorg [
|
|
"callPackage"
|
|
"newScope"
|
|
"overrideScope"
|
|
"packages"
|
|
];
|
|
|
|
packagesWithXorg = pkgs // builtins.removeAttrs pkgs.xorg [
|
|
"callPackage"
|
|
"newScope"
|
|
"overrideScope"
|
|
"packages"
|
|
];
|
|
|
|
pkgsForCall = if actuallySplice then splicedPackagesWithXorg else packagesWithXorg;
|
|
|
|
in
|
|
|
|
{
|
|
inherit splicePackages;
|
|
|
|
# We use `callPackage' to be able to omit function arguments that can be
|
|
# obtained `pkgs` or `buildPackages` and their `xorg` package sets. Use
|
|
# `newScope' for sets of packages in `pkgs' (see e.g. `gnome' below).
|
|
callPackage = pkgs.newScope { };
|
|
|
|
callPackages = lib.callPackagesWith pkgsForCall;
|
|
|
|
newScope = extra: lib.callPackageWith (pkgsForCall // extra);
|
|
|
|
# prefill 2 fields of the function for convenience
|
|
makeScopeWithSplicing = lib.makeScopeWithSplicing splicePackages pkgs.newScope;
|
|
makeScopeWithSplicing' = lib.makeScopeWithSplicing' { inherit splicePackages; inherit (pkgs) newScope; };
|
|
|
|
# generate 'otherSplices' for 'makeScopeWithSplicing'
|
|
generateSplicesForMkScope = attrs:
|
|
let
|
|
split = X: [ X ] ++ (
|
|
if builtins.isList attrs
|
|
then attrs
|
|
else if builtins.isString attrs
|
|
then lib.splitString "." attrs
|
|
else throw "generateSplicesForMkScope must be passed a list of string or string"
|
|
);
|
|
bad = throw "attribute should be found";
|
|
in
|
|
{
|
|
selfBuildBuild = lib.attrByPath (split "pkgsBuildBuild") bad pkgs;
|
|
selfBuildHost = lib.attrByPath (split "pkgsBuildHost") bad pkgs;
|
|
selfBuildTarget = lib.attrByPath (split "pkgsBuildTarget") bad pkgs;
|
|
selfHostHost = lib.attrByPath (split "pkgsHostHost") bad pkgs;
|
|
selfHostTarget = lib.attrByPath (split "pkgsHostTarget") bad pkgs;
|
|
selfTargetTarget = lib.attrByPath (split "pkgsTargetTarget") { } pkgs;
|
|
};
|
|
|
|
# Haskell package sets need this because they reimplement their own
|
|
# `newScope`.
|
|
__splicedPackages = if actuallySplice then splicedPackages // { recurseForDerivations = false; } else pkgs;
|
|
}
|