lib/systems: elaborate properly with non-matching system / config / parsed args (#351608)

This commit is contained in:
Philip Taron 2024-11-29 15:48:15 -08:00 committed by GitHub
commit 9396352fba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 37 additions and 13 deletions

View File

@ -6,9 +6,9 @@ let
filterAttrs filterAttrs
foldl foldl
hasInfix hasInfix
isAttrs
isFunction isFunction
isList isList
isString
mapAttrs mapAttrs
optional optional
optionalAttrs optionalAttrs
@ -55,24 +55,34 @@ let
*/ */
flakeExposed = import ./flake-systems.nix { }; flakeExposed = import ./flake-systems.nix { };
# Turn localSystem or crossSystem, which could be system-string or attrset, into
# attrset.
systemToAttrs = systemOrArgs:
if isAttrs systemOrArgs then systemOrArgs else { system = systemOrArgs; };
# Elaborate a `localSystem` or `crossSystem` so that it contains everything # Elaborate a `localSystem` or `crossSystem` so that it contains everything
# necessary. # necessary.
# #
# `parsed` is inferred from args, both because there are two options with one # `parsed` is inferred from args, both because there are two options with one
# clearly preferred, and to prevent cycles. A simpler fixed point where the RHS # clearly preferred, and to prevent cycles. A simpler fixed point where the RHS
# always just used `final.*` would fail on both counts. # always just used `final.*` would fail on both counts.
elaborate = args': let elaborate = systemOrArgs: let
args = if isString args' then { system = args'; } allArgs = systemToAttrs systemOrArgs;
else args';
# Those two will always be derived from "config", if given, so they should NOT
# be overridden further down with "// args".
args = builtins.removeAttrs allArgs [ "parsed" "system" ];
# TODO: deprecate args.rustc in favour of args.rust after 23.05 is EOL. # TODO: deprecate args.rustc in favour of args.rust after 23.05 is EOL.
rust = args.rust or args.rustc or {}; rust = args.rust or args.rustc or {};
final = { final = {
# Prefer to parse `config` as it is strictly more informative. # Prefer to parse `config` as it is strictly more informative.
parsed = parse.mkSystemFromString (if args ? config then args.config else args.system); parsed = parse.mkSystemFromString (args.config or allArgs.system);
# Either of these can be losslessly-extracted from `parsed` iff parsing succeeds. # This can be losslessly-extracted from `parsed` iff parsing succeeds.
system = parse.doubleFromSystem final.parsed; system = parse.doubleFromSystem final.parsed;
# TODO: This currently can't be losslessly-extracted from `parsed`, for example
# because of -mingw32.
config = parse.tripleFromSystem final.parsed; config = parse.tripleFromSystem final.parsed;
# Determine whether we can execute binaries built for the provided platform. # Determine whether we can execute binaries built for the provided platform.
canExecute = platform: canExecute = platform:
@ -435,5 +445,6 @@ in
inspect inspect
parse parse
platforms platforms
systemToAttrs
; ;
} }

View File

@ -78,6 +78,18 @@ lib.runTests (
expr = toLosslessStringMaybe (lib.systems.elaborate "x86_64-linux" // { something = "extra"; }); expr = toLosslessStringMaybe (lib.systems.elaborate "x86_64-linux" // { something = "extra"; });
expected = null; expected = null;
}; };
test_elaborate_config_over_system = {
expr = (lib.systems.elaborate { config = "i686-unknown-linux-gnu"; system = "x86_64-linux"; }).system;
expected = "i686-linux";
};
test_elaborate_config_over_parsed = {
expr = (lib.systems.elaborate { config = "i686-unknown-linux-gnu"; parsed = (lib.systems.elaborate "x86_64-linux").parsed; }).parsed.cpu.arch;
expected = "i686";
};
test_elaborate_system_over_parsed = {
expr = (lib.systems.elaborate { system = "i686-linux"; parsed = (lib.systems.elaborate "x86_64-linux").parsed; }).parsed.cpu.arch;
expected = "i686";
};
} }
# Generate test cases to assert that a change in any non-function attribute makes a platform unequal # Generate test cases to assert that a change in any non-function attribute makes a platform unequal

View File

@ -246,7 +246,7 @@ let
})] ++ overlays; })] ++ overlays;
${if stdenv.hostPlatform == stdenv.buildPlatform ${if stdenv.hostPlatform == stdenv.buildPlatform
then "localSystem" else "crossSystem"} = { then "localSystem" else "crossSystem"} = {
parsed = makeMuslParsedPlatform stdenv.hostPlatform.parsed; config = lib.systems.parse.tripleFromSystem (makeMuslParsedPlatform stdenv.hostPlatform.parsed);
}; };
} else throw "Musl libc only supports 64-bit Linux systems."; } else throw "Musl libc only supports 64-bit Linux systems.";
@ -258,9 +258,9 @@ let
})] ++ overlays; })] ++ overlays;
${if stdenv.hostPlatform == stdenv.buildPlatform ${if stdenv.hostPlatform == stdenv.buildPlatform
then "localSystem" else "crossSystem"} = { then "localSystem" else "crossSystem"} = {
parsed = stdenv.hostPlatform.parsed // { config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // {
cpu = lib.systems.parse.cpuTypes.i686; cpu = lib.systems.parse.cpuTypes.i686;
}; });
}; };
} else throw "i686 Linux package set can only be used with the x86 family."; } else throw "i686 Linux package set can only be used with the x86 family.";
@ -270,9 +270,9 @@ let
pkgsx86_64Darwin = super'; pkgsx86_64Darwin = super';
})] ++ overlays; })] ++ overlays;
localSystem = { localSystem = {
parsed = stdenv.hostPlatform.parsed // { config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // {
cpu = lib.systems.parse.cpuTypes.x86_64; cpu = lib.systems.parse.cpuTypes.x86_64;
}; });
}; };
} else throw "x86_64 Darwin package set can only be used on Darwin systems."; } else throw "x86_64 Darwin package set can only be used on Darwin systems.";
@ -311,10 +311,11 @@ let
})] ++ overlays; })] ++ overlays;
crossSystem = { crossSystem = {
isStatic = true; isStatic = true;
parsed = config = lib.systems.parse.tripleFromSystem (
if stdenv.hostPlatform.isLinux if stdenv.hostPlatform.isLinux
then makeMuslParsedPlatform stdenv.hostPlatform.parsed then makeMuslParsedPlatform stdenv.hostPlatform.parsed
else stdenv.hostPlatform.parsed; else stdenv.hostPlatform.parsed
);
gcc = lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") { abi = "elfv2"; } // gcc = lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") { abi = "elfv2"; } //
stdenv.hostPlatform.gcc or {}; stdenv.hostPlatform.gcc or {};
}; };