Skip to content

Commit 9396352

Browse files
authored
lib/systems: elaborate properly with non-matching system / config / parsed args (#351608)
2 parents 3b56519 + 3c21a5c commit 9396352

File tree

3 files changed

+37
-13
lines changed

3 files changed

+37
-13
lines changed

lib/systems/default.nix

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ let
66
filterAttrs
77
foldl
88
hasInfix
9+
isAttrs
910
isFunction
1011
isList
11-
isString
1212
mapAttrs
1313
optional
1414
optionalAttrs
@@ -55,24 +55,34 @@ let
5555
*/
5656
flakeExposed = import ./flake-systems.nix { };
5757

58+
# Turn localSystem or crossSystem, which could be system-string or attrset, into
59+
# attrset.
60+
systemToAttrs = systemOrArgs:
61+
if isAttrs systemOrArgs then systemOrArgs else { system = systemOrArgs; };
62+
5863
# Elaborate a `localSystem` or `crossSystem` so that it contains everything
5964
# necessary.
6065
#
6166
# `parsed` is inferred from args, both because there are two options with one
6267
# clearly preferred, and to prevent cycles. A simpler fixed point where the RHS
6368
# always just used `final.*` would fail on both counts.
64-
elaborate = args': let
65-
args = if isString args' then { system = args'; }
66-
else args';
69+
elaborate = systemOrArgs: let
70+
allArgs = systemToAttrs systemOrArgs;
71+
72+
# Those two will always be derived from "config", if given, so they should NOT
73+
# be overridden further down with "// args".
74+
args = builtins.removeAttrs allArgs [ "parsed" "system" ];
6775

6876
# TODO: deprecate args.rustc in favour of args.rust after 23.05 is EOL.
6977
rust = args.rust or args.rustc or {};
7078

7179
final = {
7280
# Prefer to parse `config` as it is strictly more informative.
73-
parsed = parse.mkSystemFromString (if args ? config then args.config else args.system);
74-
# Either of these can be losslessly-extracted from `parsed` iff parsing succeeds.
81+
parsed = parse.mkSystemFromString (args.config or allArgs.system);
82+
# This can be losslessly-extracted from `parsed` iff parsing succeeds.
7583
system = parse.doubleFromSystem final.parsed;
84+
# TODO: This currently can't be losslessly-extracted from `parsed`, for example
85+
# because of -mingw32.
7686
config = parse.tripleFromSystem final.parsed;
7787
# Determine whether we can execute binaries built for the provided platform.
7888
canExecute = platform:
@@ -435,5 +445,6 @@ in
435445
inspect
436446
parse
437447
platforms
448+
systemToAttrs
438449
;
439450
}

lib/tests/systems.nix

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ lib.runTests (
7878
expr = toLosslessStringMaybe (lib.systems.elaborate "x86_64-linux" // { something = "extra"; });
7979
expected = null;
8080
};
81+
test_elaborate_config_over_system = {
82+
expr = (lib.systems.elaborate { config = "i686-unknown-linux-gnu"; system = "x86_64-linux"; }).system;
83+
expected = "i686-linux";
84+
};
85+
test_elaborate_config_over_parsed = {
86+
expr = (lib.systems.elaborate { config = "i686-unknown-linux-gnu"; parsed = (lib.systems.elaborate "x86_64-linux").parsed; }).parsed.cpu.arch;
87+
expected = "i686";
88+
};
89+
test_elaborate_system_over_parsed = {
90+
expr = (lib.systems.elaborate { system = "i686-linux"; parsed = (lib.systems.elaborate "x86_64-linux").parsed; }).parsed.cpu.arch;
91+
expected = "i686";
92+
};
8193
}
8294

8395
# Generate test cases to assert that a change in any non-function attribute makes a platform unequal

pkgs/top-level/stage.nix

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ let
246246
})] ++ overlays;
247247
${if stdenv.hostPlatform == stdenv.buildPlatform
248248
then "localSystem" else "crossSystem"} = {
249-
parsed = makeMuslParsedPlatform stdenv.hostPlatform.parsed;
249+
config = lib.systems.parse.tripleFromSystem (makeMuslParsedPlatform stdenv.hostPlatform.parsed);
250250
};
251251
} else throw "Musl libc only supports 64-bit Linux systems.";
252252

@@ -258,9 +258,9 @@ let
258258
})] ++ overlays;
259259
${if stdenv.hostPlatform == stdenv.buildPlatform
260260
then "localSystem" else "crossSystem"} = {
261-
parsed = stdenv.hostPlatform.parsed // {
261+
config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // {
262262
cpu = lib.systems.parse.cpuTypes.i686;
263-
};
263+
});
264264
};
265265
} else throw "i686 Linux package set can only be used with the x86 family.";
266266

@@ -270,9 +270,9 @@ let
270270
pkgsx86_64Darwin = super';
271271
})] ++ overlays;
272272
localSystem = {
273-
parsed = stdenv.hostPlatform.parsed // {
273+
config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // {
274274
cpu = lib.systems.parse.cpuTypes.x86_64;
275-
};
275+
});
276276
};
277277
} else throw "x86_64 Darwin package set can only be used on Darwin systems.";
278278

@@ -311,10 +311,11 @@ let
311311
})] ++ overlays;
312312
crossSystem = {
313313
isStatic = true;
314-
parsed =
314+
config = lib.systems.parse.tripleFromSystem (
315315
if stdenv.hostPlatform.isLinux
316316
then makeMuslParsedPlatform stdenv.hostPlatform.parsed
317-
else stdenv.hostPlatform.parsed;
317+
else stdenv.hostPlatform.parsed
318+
);
318319
gcc = lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") { abi = "elfv2"; } //
319320
stdenv.hostPlatform.gcc or {};
320321
};

0 commit comments

Comments
 (0)