aboutsummaryrefslogtreecommitdiff
path: root/infra/libkookie/nixpkgs/pkgs/top-level/splice.nix
diff options
context:
space:
mode:
Diffstat (limited to 'infra/libkookie/nixpkgs/pkgs/top-level/splice.nix')
-rw-r--r--infra/libkookie/nixpkgs/pkgs/top-level/splice.nix137
1 files changed, 137 insertions, 0 deletions
diff --git a/infra/libkookie/nixpkgs/pkgs/top-level/splice.nix b/infra/libkookie/nixpkgs/pkgs/top-level/splice.nix
new file mode 100644
index 000000000000..a093442d3698
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/top-level/splice.nix
@@ -0,0 +1,137 @@
+# 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
+# `nativeDrv` field for the build-time version, and `crossDrv` field for the
+# run-time version.
+#
+# We could have used any names we want for the disambiguated versions, but
+# `crossDrv` and `nativeDrv` were somewhat similarly used for the old
+# cross-compiling infrastructure. The names are mostly invisible as
+# `mkDerivation` knows how to pull out the right ones for `buildDepends` and
+# friends, but a few packages use them directly, so it seemed efficient (to
+# @Ericson2314) to reuse those names, at least initially, to minimize breakage.
+#
+# 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 = throw "`valueHostHost` unimplemented: pass manually rather than relying on splice.";
+ valueHostTarget = pkgsHostTarget.${name} or {};
+ valueTargetTarget = pkgsTargetTarget.${name} or {};
+ augmentedValue = defaultValue
+ # TODO(@Ericson2314): Stop using old names after transition period
+ // (lib.optionalAttrs (pkgsBuildHost ? ${name}) { nativeDrv = valueBuildHost; })
+ // (lib.optionalAttrs (pkgsHostTarget ? ${name}) { crossDrv = valueHostTarget; })
+ // {
+ __spliced =
+ (lib.optionalAttrs (pkgsBuildBuild ? ${name}) { buildBuild = valueBuildBuild; })
+ // (lib.optionalAttrs (pkgsBuildTarget ? ${name}) { buildTarget = valueBuildTarget; })
+ // { hostHost = valueHostHost; }
+ // (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 = {};
+ 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"
+ ];
+
+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 splicedPackagesWithXorg;
+
+ newScope = extra: lib.callPackageWith (splicedPackagesWithXorg // extra);
+
+ # Haskell package sets need this because they reimplement their own
+ # `newScope`.
+ __splicedPackages = splicedPackages // { recurseForDerivations = false; };
+}