Loading lib/customisation.nix +135 −0 Original line number Diff line number Diff line Loading @@ -864,4 +864,139 @@ rec { transformDrv ; }; /** Removes a prefix from the attribute names of a cross index. A cross index (short for "Cross Platform Pair Index") is a 6-field structure organizing values by cross-compilation platform relationships. # Inputs `prefix` : The prefix to remove from cross index attribute names `crossIndex` : A cross index with prefixed names # Type ``` renameCrossIndexFrom :: String -> AttrSet -> AttrSet ``` # Examples :::{.example} ## `lib.customisation.renameCrossIndexFrom` usage example ```nix renameCrossIndexFrom "pkgs" { pkgsBuildBuild = ...; pkgsBuildHost = ...; ... } => { buildBuild = ...; buildHost = ...; ... } ``` ::: */ renameCrossIndexFrom = prefix: x: { buildBuild = x."${prefix}BuildBuild"; buildHost = x."${prefix}BuildHost"; buildTarget = x."${prefix}BuildTarget"; hostHost = x."${prefix}HostHost"; hostTarget = x."${prefix}HostTarget"; targetTarget = x."${prefix}TargetTarget"; }; /** Adds a prefix to the attribute names of a cross index. A cross index (short for "Cross Platform Pair Index") is a 6-field structure organizing values by cross-compilation platform relationships. # Inputs `prefix` : The prefix to add to cross index attribute names `crossIndex` : A cross index to be prefixed # Type ``` renameCrossIndexTo :: String -> AttrSet -> AttrSet ``` # Examples :::{.example} ## `lib.customisation.renameCrossIndexTo` usage example ```nix renameCrossIndexTo "self" { buildBuild = ...; buildHost = ...; ... } => { selfBuildBuild = ...; selfBuildHost = ...; ... } ``` ::: */ renameCrossIndexTo = prefix: x: { "${prefix}BuildBuild" = x.buildBuild; "${prefix}BuildHost" = x.buildHost; "${prefix}BuildTarget" = x.buildTarget; "${prefix}HostHost" = x.hostHost; "${prefix}HostTarget" = x.hostTarget; "${prefix}TargetTarget" = x.targetTarget; }; /** Takes a function and applies it pointwise to each field of a cross index. A cross index (short for "Cross Platform Pair Index") is a 6-field structure organizing values by cross-compilation platform relationships. # Inputs `f` : Function to apply to each cross index value `crossIndex` : A cross index to transform # Type ``` mapCrossIndex :: (a -> b) -> AttrSet -> AttrSet ``` # Examples :::{.example} ## `lib.customisation.mapCrossIndex` usage example ```nix mapCrossIndex (x: x * 10) { buildBuild = 1; buildHost = 2; ... } => { buildBuild = 10; buildHost = 20; ... } ``` ```nix # Extract a package from package sets mapCrossIndex (pkgs: pkgs.hello) crossIndexedPackageSets ``` ::: */ mapCrossIndex = f: { buildBuild, buildHost, buildTarget, hostHost, hostTarget, targetTarget, }: { buildBuild = f buildBuild; buildHost = f buildHost; buildTarget = f buildTarget; hostHost = f hostHost; hostTarget = f hostTarget; targetTarget = f targetTarget; }; } lib/default.nix +3 −0 Original line number Diff line number Diff line Loading @@ -397,6 +397,9 @@ let makeScopeWithSplicing makeScopeWithSplicing' extendMkDerivation renameCrossIndexFrom renameCrossIndexTo mapCrossIndex ; inherit (self.derivations) lazyDerivation optionalDrvAttr warnOnInstantiate; inherit (self.generators) mkLuaInline; Loading lib/tests/misc.nix +78 −0 Original line number Diff line number Diff line Loading @@ -4741,4 +4741,82 @@ runTests { expected = "/non-existent/this/does/not/exist/for/real/please-dont-mess-with-your-local-fs/default.nix"; }; # Tests for cross index utilities testRenameCrossIndexFrom = { expr = lib.renameCrossIndexFrom "pkgs" { pkgsBuildBuild = "dummy-build-build"; pkgsBuildHost = "dummy-build-host"; pkgsBuildTarget = "dummy-build-target"; pkgsHostHost = "dummy-host-host"; pkgsHostTarget = "dummy-host-target"; pkgsTargetTarget = "dummy-target-target"; }; expected = { buildBuild = "dummy-build-build"; buildHost = "dummy-build-host"; buildTarget = "dummy-build-target"; hostHost = "dummy-host-host"; hostTarget = "dummy-host-target"; targetTarget = "dummy-target-target"; }; }; testRenameCrossIndexTo = { expr = lib.renameCrossIndexTo "self" { buildBuild = "dummy-build-build"; buildHost = "dummy-build-host"; buildTarget = "dummy-build-target"; hostHost = "dummy-host-host"; hostTarget = "dummy-host-target"; targetTarget = "dummy-target-target"; }; expected = { selfBuildBuild = "dummy-build-build"; selfBuildHost = "dummy-build-host"; selfBuildTarget = "dummy-build-target"; selfHostHost = "dummy-host-host"; selfHostTarget = "dummy-host-target"; selfTargetTarget = "dummy-target-target"; }; }; testMapCrossIndex = { expr = lib.mapCrossIndex (x: x * 10) { buildBuild = 1; buildHost = 2; buildTarget = 3; hostHost = 4; hostTarget = 5; targetTarget = 6; }; expected = { buildBuild = 10; buildHost = 20; buildTarget = 30; hostHost = 40; hostTarget = 50; targetTarget = 60; }; }; testMapCrossIndexString = { expr = lib.mapCrossIndex (x: "prefix-${x}") { buildBuild = "bb"; buildHost = "bh"; buildTarget = "bt"; hostHost = "hh"; hostTarget = "ht"; targetTarget = "tt"; }; expected = { buildBuild = "prefix-bb"; buildHost = "prefix-bh"; buildTarget = "prefix-bt"; hostHost = "prefix-hh"; hostTarget = "prefix-ht"; targetTarget = "prefix-tt"; }; }; } pkgs/top-level/splice.nix +16 −49 Original line number Diff line number Diff line Loading @@ -17,48 +17,30 @@ lib: pkgs: actuallySplice: let inherit (lib.customisation) mapCrossIndex renameCrossIndexFrom; spliceReal = { pkgsBuildBuild, pkgsBuildHost, pkgsBuildTarget, pkgsHostHost, pkgsHostTarget, pkgsTargetTarget, }: inputs: let mash = # Other pkgs sets pkgsBuildBuild // pkgsBuildTarget // pkgsHostHost // pkgsTargetTarget inputs.buildBuild // inputs.buildTarget // inputs.hostHost // inputs.targetTarget # The same pkgs sets one probably intends // pkgsBuildHost // pkgsHostTarget; // inputs.buildHost // inputs.hostTarget; 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 { }; value' = mapCrossIndex (x: x.${name} or { }) inputs; 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; }); __spliced = lib.filterAttrs (k: v: inputs.${k} ? ${name}) value'; }; # 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 Loading @@ -76,27 +58,12 @@ let # 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 } // spliceReal (mapCrossIndex tryGetOutputs value' // { hostTarget = getOutputs value'.hostTarget; }) else if lib.isAttrs defaultValue then spliceReal { pkgsBuildBuild = valueBuildBuild; pkgsBuildHost = valueBuildHost; pkgsBuildTarget = valueBuildTarget; pkgsHostHost = valueHostHost; pkgsHostTarget = valueHostTarget; pkgsTargetTarget = valueTargetTarget; spliceReal value' else # Don't be fancy about non-derivations. But we could have used used # `__functor__` for functions instead. } else defaultValue; }; in Loading @@ -111,7 +78,7 @@ let pkgsHostTarget, pkgsTargetTarget, }@args: if actuallySplice then spliceReal args else pkgsHostTarget; if actuallySplice then spliceReal (renameCrossIndexFrom "pkgs" args) else pkgsHostTarget; splicedPackages = splicePackages { Loading Loading
lib/customisation.nix +135 −0 Original line number Diff line number Diff line Loading @@ -864,4 +864,139 @@ rec { transformDrv ; }; /** Removes a prefix from the attribute names of a cross index. A cross index (short for "Cross Platform Pair Index") is a 6-field structure organizing values by cross-compilation platform relationships. # Inputs `prefix` : The prefix to remove from cross index attribute names `crossIndex` : A cross index with prefixed names # Type ``` renameCrossIndexFrom :: String -> AttrSet -> AttrSet ``` # Examples :::{.example} ## `lib.customisation.renameCrossIndexFrom` usage example ```nix renameCrossIndexFrom "pkgs" { pkgsBuildBuild = ...; pkgsBuildHost = ...; ... } => { buildBuild = ...; buildHost = ...; ... } ``` ::: */ renameCrossIndexFrom = prefix: x: { buildBuild = x."${prefix}BuildBuild"; buildHost = x."${prefix}BuildHost"; buildTarget = x."${prefix}BuildTarget"; hostHost = x."${prefix}HostHost"; hostTarget = x."${prefix}HostTarget"; targetTarget = x."${prefix}TargetTarget"; }; /** Adds a prefix to the attribute names of a cross index. A cross index (short for "Cross Platform Pair Index") is a 6-field structure organizing values by cross-compilation platform relationships. # Inputs `prefix` : The prefix to add to cross index attribute names `crossIndex` : A cross index to be prefixed # Type ``` renameCrossIndexTo :: String -> AttrSet -> AttrSet ``` # Examples :::{.example} ## `lib.customisation.renameCrossIndexTo` usage example ```nix renameCrossIndexTo "self" { buildBuild = ...; buildHost = ...; ... } => { selfBuildBuild = ...; selfBuildHost = ...; ... } ``` ::: */ renameCrossIndexTo = prefix: x: { "${prefix}BuildBuild" = x.buildBuild; "${prefix}BuildHost" = x.buildHost; "${prefix}BuildTarget" = x.buildTarget; "${prefix}HostHost" = x.hostHost; "${prefix}HostTarget" = x.hostTarget; "${prefix}TargetTarget" = x.targetTarget; }; /** Takes a function and applies it pointwise to each field of a cross index. A cross index (short for "Cross Platform Pair Index") is a 6-field structure organizing values by cross-compilation platform relationships. # Inputs `f` : Function to apply to each cross index value `crossIndex` : A cross index to transform # Type ``` mapCrossIndex :: (a -> b) -> AttrSet -> AttrSet ``` # Examples :::{.example} ## `lib.customisation.mapCrossIndex` usage example ```nix mapCrossIndex (x: x * 10) { buildBuild = 1; buildHost = 2; ... } => { buildBuild = 10; buildHost = 20; ... } ``` ```nix # Extract a package from package sets mapCrossIndex (pkgs: pkgs.hello) crossIndexedPackageSets ``` ::: */ mapCrossIndex = f: { buildBuild, buildHost, buildTarget, hostHost, hostTarget, targetTarget, }: { buildBuild = f buildBuild; buildHost = f buildHost; buildTarget = f buildTarget; hostHost = f hostHost; hostTarget = f hostTarget; targetTarget = f targetTarget; }; }
lib/default.nix +3 −0 Original line number Diff line number Diff line Loading @@ -397,6 +397,9 @@ let makeScopeWithSplicing makeScopeWithSplicing' extendMkDerivation renameCrossIndexFrom renameCrossIndexTo mapCrossIndex ; inherit (self.derivations) lazyDerivation optionalDrvAttr warnOnInstantiate; inherit (self.generators) mkLuaInline; Loading
lib/tests/misc.nix +78 −0 Original line number Diff line number Diff line Loading @@ -4741,4 +4741,82 @@ runTests { expected = "/non-existent/this/does/not/exist/for/real/please-dont-mess-with-your-local-fs/default.nix"; }; # Tests for cross index utilities testRenameCrossIndexFrom = { expr = lib.renameCrossIndexFrom "pkgs" { pkgsBuildBuild = "dummy-build-build"; pkgsBuildHost = "dummy-build-host"; pkgsBuildTarget = "dummy-build-target"; pkgsHostHost = "dummy-host-host"; pkgsHostTarget = "dummy-host-target"; pkgsTargetTarget = "dummy-target-target"; }; expected = { buildBuild = "dummy-build-build"; buildHost = "dummy-build-host"; buildTarget = "dummy-build-target"; hostHost = "dummy-host-host"; hostTarget = "dummy-host-target"; targetTarget = "dummy-target-target"; }; }; testRenameCrossIndexTo = { expr = lib.renameCrossIndexTo "self" { buildBuild = "dummy-build-build"; buildHost = "dummy-build-host"; buildTarget = "dummy-build-target"; hostHost = "dummy-host-host"; hostTarget = "dummy-host-target"; targetTarget = "dummy-target-target"; }; expected = { selfBuildBuild = "dummy-build-build"; selfBuildHost = "dummy-build-host"; selfBuildTarget = "dummy-build-target"; selfHostHost = "dummy-host-host"; selfHostTarget = "dummy-host-target"; selfTargetTarget = "dummy-target-target"; }; }; testMapCrossIndex = { expr = lib.mapCrossIndex (x: x * 10) { buildBuild = 1; buildHost = 2; buildTarget = 3; hostHost = 4; hostTarget = 5; targetTarget = 6; }; expected = { buildBuild = 10; buildHost = 20; buildTarget = 30; hostHost = 40; hostTarget = 50; targetTarget = 60; }; }; testMapCrossIndexString = { expr = lib.mapCrossIndex (x: "prefix-${x}") { buildBuild = "bb"; buildHost = "bh"; buildTarget = "bt"; hostHost = "hh"; hostTarget = "ht"; targetTarget = "tt"; }; expected = { buildBuild = "prefix-bb"; buildHost = "prefix-bh"; buildTarget = "prefix-bt"; hostHost = "prefix-hh"; hostTarget = "prefix-ht"; targetTarget = "prefix-tt"; }; }; }
pkgs/top-level/splice.nix +16 −49 Original line number Diff line number Diff line Loading @@ -17,48 +17,30 @@ lib: pkgs: actuallySplice: let inherit (lib.customisation) mapCrossIndex renameCrossIndexFrom; spliceReal = { pkgsBuildBuild, pkgsBuildHost, pkgsBuildTarget, pkgsHostHost, pkgsHostTarget, pkgsTargetTarget, }: inputs: let mash = # Other pkgs sets pkgsBuildBuild // pkgsBuildTarget // pkgsHostHost // pkgsTargetTarget inputs.buildBuild // inputs.buildTarget // inputs.hostHost // inputs.targetTarget # The same pkgs sets one probably intends // pkgsBuildHost // pkgsHostTarget; // inputs.buildHost // inputs.hostTarget; 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 { }; value' = mapCrossIndex (x: x.${name} or { }) inputs; 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; }); __spliced = lib.filterAttrs (k: v: inputs.${k} ? ${name}) value'; }; # 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 Loading @@ -76,27 +58,12 @@ let # 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 } // spliceReal (mapCrossIndex tryGetOutputs value' // { hostTarget = getOutputs value'.hostTarget; }) else if lib.isAttrs defaultValue then spliceReal { pkgsBuildBuild = valueBuildBuild; pkgsBuildHost = valueBuildHost; pkgsBuildTarget = valueBuildTarget; pkgsHostHost = valueHostHost; pkgsHostTarget = valueHostTarget; pkgsTargetTarget = valueTargetTarget; spliceReal value' else # Don't be fancy about non-derivations. But we could have used used # `__functor__` for functions instead. } else defaultValue; }; in Loading @@ -111,7 +78,7 @@ let pkgsHostTarget, pkgsTargetTarget, }@args: if actuallySplice then spliceReal args else pkgsHostTarget; if actuallySplice then spliceReal (renameCrossIndexFrom "pkgs" args) else pkgsHostTarget; splicedPackages = splicePackages { Loading