Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib.systems.parse: remove now-unnecessary windows hackery #249090

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
1182947
gnu-config: use the unpackPhase, so .override({patches=...}) works
Aug 14, 2023
2648eb2
lib/systems: replicate cygwin/msvc parsing hack when unparsing
May 31, 2023
693d04f
lib/systems: show respect where deserved
Jun 19, 2023
11b3084
lib/systems: factor tripleFromSkeleton out of tripleFromSystem
Jun 20, 2023
2c2c55a
lib/systems: rename vendors.none -> vendors.""
Jun 20, 2023
5d2c582
lib/systems: introduce tripleFromSystemLossy
Jun 20, 2023
98792f9
lib/systems: accomodate nonstandard `vc4-elf` triple
Jun 19, 2023
0bc216f
lib/systems: handle Solaris properly
Jun 19, 2023
e0da48b
lib/systems: add TODO regarding execFormats
Jun 19, 2023
ba1dba6
lib/systems: add and check valid kernels for each abi
Jun 19, 2023
62de3d0
lib/systems: move powerpc64-be ABI-defaulting out of the parser
Jun 20, 2023
c63f967
lib/systems: default arm-apple-linux to -gnu ABI
Jun 20, 2023
bb448a2
lib/systems: add vendors.{ibm,xilinx}
Jun 20, 2023
4577d3e
lib/systems: omit optExecFormat from triples
Jun 20, 2023
6048cc2
lib/systems: fix abi inference for aarch32-linux
Jun 20, 2023
af44940
lib/systems: fix vendor fallback logic
Jun 20, 2023
6d403ba
lib/tests/triples.nix: add gnu-config conformance test suite
Jun 19, 2023
493481b
lib/systems: add vendors.solo5
Jun 20, 2023
961e560
lib/systems: add kernels."", distinct from kernels.none
Jun 20, 2023
68260ed
implement formatting suggestion from @RaitoBezarius
Jun 28, 2023
e1015c7
lib.systems.parse: remove parts of windows hackery that are no longer…
Aug 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/systems/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ rec {
parsed = parse.mkSystemFromString (if args ? config then args.config else args.system);
# Either of these can be losslessly-extracted from `parsed` iff parsing succeeds.
system = parse.doubleFromSystem final.parsed;
config = parse.tripleFromSystem final.parsed;
config = parse.tripleFromSystemLossy final.parsed;
# Determine whether we can execute binaries built for the provided platform.
canExecute = platform:
final.isAndroid == platform.isAndroid &&
Expand Down
6 changes: 4 additions & 2 deletions lib/systems/doubles.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let
"aarch64-genode" "i686-genode" "x86_64-genode"

# illumos
"x86_64-solaris"
"x86_64-solaris2"

# JS
"javascript-ghcjs"
Expand All @@ -43,7 +43,9 @@ let
"aarch64_be-none" "aarch64-none" "arm-none" "armv6l-none" "avr-none" "i686-none"
"microblaze-none" "microblazeel-none" "mips-none" "mips64-none" "msp430-none" "or1k-none" "m68k-none"
"powerpc-none" "powerpcle-none" "riscv32-none" "riscv64-none" "rx-none"
"s390-none" "s390x-none" "vc4-none" "x86_64-none"
"s390-none" "s390x-none"
"vc4-elf" # nonstandard triple, requires many hacks
"x86_64-none"

# OpenBSD
"i686-openbsd" "x86_64-openbsd"
Expand Down
4 changes: 2 additions & 2 deletions lib/systems/inspect.nix
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ rec {
isMacOS = { kernel = kernels.macos; };
isiOS = { kernel = kernels.ios; };
isLinux = { kernel = kernels.linux; };
isSunOS = { kernel = kernels.solaris; };
isSunOS = { kernel = kernels.solaris2; };
isFreeBSD = { kernel = { name = "freebsd"; }; };
isNetBSD = { kernel = kernels.netbsd; };
isOpenBSD = { kernel = kernels.openbsd; };
Expand All @@ -84,7 +84,7 @@ rec {
isRedox = { kernel = kernels.redox; };
isGhcjs = { kernel = kernels.ghcjs; };
isGenode = { kernel = kernels.genode; };
isNone = { kernel = kernels.none; };
isNone = [ { kernel = kernels.none; } { kernel = kernels.""; } ];

isAndroid = [ { abi = abis.android; } { abi = abis.androideabi; } ];
isGnu = with abis; map (a: { abi = a; }) [ gnuabi64 gnuabin32 gnu gnueabi gnueabihf gnuabielfv1 gnuabielfv2 ];
Expand Down
211 changes: 156 additions & 55 deletions lib/systems/parse.nix
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,19 @@ rec {
vendors = setTypes types.openVendor {
apple = {};
pc = {};
ibm = {};
knuth = {};
xilinx = {};
solo5 = {};

# Actually matters, unlocking some MinGW-w64-specific options in GCC. See
# bottom of https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/
w64 = {};

none = {};
# gnu-config distinguishes between `foo-bar-baz` and
# `foo-unknown-bar-baz`; we use `""` to represent the
# former case.
"" = { name = ""; };
unknown = {};
};

Expand Down Expand Up @@ -276,6 +284,9 @@ rec {

types.kernel = enum (attrValues kernels);

# TODO (@amjoseph): we should eliminate execFormats or move it to
# abis; executable format is a property of the ABI not the kernel.
# This will also clear up the netbsd kludge in tripleFromSystem.
kernels = with execFormats; with kernelFamilies; setTypes types.openKernel {
# TODO(@Ericson2314): Don't want to mass-rebuild yet to keeping 'darwin' as
# the normalized name for macOS.
Expand All @@ -289,8 +300,9 @@ rec {
linux = { execFormat = elf; families = { }; };
netbsd = { execFormat = elf; families = { inherit bsd; }; };
none = { execFormat = unknown; families = { }; };
"" = { execFormat = unknown; families = { }; };
openbsd = { execFormat = elf; families = { inherit bsd; }; };
solaris = { execFormat = elf; families = { }; };
solaris2 = { execFormat = elf; families = { }; name = "solaris"; version = 2; };
wasi = { execFormat = wasm; families = { }; };
redox = { execFormat = elf; families = { }; };
windows = { execFormat = pe; families = { }; };
Expand All @@ -315,21 +327,21 @@ rec {

types.abi = enum (attrValues abis);

abis = setTypes types.openAbi {
cygnus = {};
msvc = {};
abis = setTypes types.openAbi rec {
cygnus = { kernels = [ "windows" ]; };
msvc = { kernels = [ "windows" ]; };

# Note: eabi is specific to ARM and PowerPC.
# On PowerPC, this corresponds to PPCEABI.
# On ARM, this corresponds to ARMEABI.
eabi = { float = "soft"; };
eabihf = { float = "hard"; };
eabi = { float = "soft"; kernels = builtins.attrNames kernels; };
eabihf = { float = "hard"; kernels = builtins.attrNames kernels; };

# Other architectures should use ELF in embedded situations.
elf = {};
elf = { kernels = [ "" ]; };

androideabi = {};
android = {
androideabi = { inherit (android) kernels; };
android = { kernels = [ "linux" ];
assertions = [
{ assertion = platform: !platform.isAarch32;
message = ''
Expand All @@ -339,9 +351,9 @@ rec {
];
};

gnueabi = { float = "soft"; };
gnueabihf = { float = "hard"; };
gnu = {
gnueabi = { float = "soft"; inherit (gnu) kernels; };
gnueabihf = { float = "hard"; inherit (gnu) kernels; };
gnu = { kernels = [ "freebsd12" "freebsd13" "linux" "windows" ];
assertions = [
{ assertion = platform: !platform.isAarch32;
message = ''
Expand All @@ -355,27 +367,28 @@ rec {
}
];
};
gnuabi64 = { abi = "64"; };
muslabi64 = { abi = "64"; };
gnuabi64 = { abi = "64"; inherit (gnu) kernels; };
muslabi64 = { abi = "64"; kernels = [ "linux" ]; };

# NOTE: abi=n32 requires a 64-bit MIPS chip! That is not a typo.
# It is basically the 64-bit abi with 32-bit pointers. Details:
# https://www.linux-mips.org/pub/linux/mips/doc/ABI/MIPS-N32-ABI-Handbook.pdf
gnuabin32 = { abi = "n32"; };
muslabin32 = { abi = "n32"; };
gnuabin32 = { abi = "n32"; inherit (gnu) kernels; };
muslabin32 = { abi = "n32"; inherit (musl) kernels; };

gnuabielfv2 = { abi = "elfv2"; };
gnuabielfv1 = { abi = "elfv1"; };
gnuabielfv2 = { abi = "elfv2"; kernels = [ "linux" ]; };
gnuabielfv1 = { abi = "elfv1"; kernels = [ "linux" ]; };

musleabi = { float = "soft"; };
musleabihf = { float = "hard"; };
musl = {};
musleabi = { float = "soft"; inherit (musl) kernels; };
musleabihf = { float = "hard"; inherit (musl) kernels; };
musl = { kernels = [ "linux" ]; };

uclibceabi = { float = "soft"; };
uclibceabihf = { float = "hard"; };
uclibc = {};
uclibceabi = { float = "soft"; inherit (uclibc) kernels; };
uclibceabihf = { float = "hard"; inherit (uclibc) kernels; };
uclibc = { kernels = [ "linux" ]; };

unknown = {};
# in gnu-config triples, this abi is actually the empty string "" rather than "-unknown"
unknown = { kernels = [ "darwin" "freebsd12" "freebsd13" "freebsd" "genode" "solaris2" "solaris" "ghcjs" "mmixware" "netbsd" "none" "" "openbsd" "redox" "wasi" "windows" ]; };
};

################################################################################
Expand All @@ -395,36 +408,69 @@ rec {

mkSystem = components:
assert types.parsedPlatform.check components;
assert with components;
(kernel == kernels.ghcjs) != (cpu == cpuTypes.javascript)
-> throw ''
cpu "javascript" and kernel "ghcjs" are valid only with each other;
you attempted to use cpu "${components.cpu.name}" with kernel
"${components.kernel.name}"
'';
assert with components;
!(lib.elem kernel.name (abi.kernels or [ kernel.name ])) &&
!(isVc4 components)
-> throw ''
kernel ${components.kernel.name} does not allow abi ${components.abi.name}
'';
assert with components;
!(isVc4 components -> (with components; vendor.name == "" && kernel.name == "" && abi.name == "elf"))
-> throw ''
Broadcom VC4 CPUs may be used only in the nonstandard triple "vc4-elf".
You tried to create "${cpu.name}-${vendor.name}-${kernel.name}-${abi.name}".
'';
assert with components;
!(isJavaScript components ->
(vendor.name == "unknown" || vendor.name == "") &&
kernel == kernels.ghcjs &&
abi == abis.unknown)
-> throw ''
The special "javascript" cpu may be used only in the nonstandard triple
"javascript-unknown-ghcjs". You tried to create
"${cpu.name}-${vendor.name}-${kernel.name}-${abi.name}"
'';

setType "system" components;

mkSkeletonFromList = l: {
"1" = if elemAt l 0 == "avr"
then { cpu = elemAt l 0; kernel = "none"; abi = "unknown"; }
else throw "Target specification with 1 components is ambiguous";
"2" = # We only do 2-part hacks for things Nix already supports
if elemAt l 1 == "cygwin"
then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; }
# MSVC ought to be the default ABI so this case isn't needed. But then it
# becomes difficult to handle the gnu* variants for Aarch32 correctly for
# minGW. So it's easier to make gnu* the default for the MinGW, but
# hack-in MSVC for the non-MinGW case right here.
else if elemAt l 1 == "windows"
then { cpu = elemAt l 0; kernel = "windows"; abi = "msvc"; }
if (elemAt l 1) == "cygwin"
then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; }
else if (elemAt l 1) == "elf"
then { cpu = elemAt l 0; vendor = "unknown"; kernel = "none"; abi = elemAt l 1; }
then { cpu = elemAt l 0; kernel = ""; abi = elemAt l 1; }
else { cpu = elemAt l 0; kernel = elemAt l 1; };
"3" =
# cpu-vendor-""-abi
if elemAt l 1 == "unknown" && elemAt l 2 == "elf"
then {
cpu = elemAt l 0;
vendor = elemAt l 1;
kernel = "";
abi = elemAt l 2;
}
# cpu-kernel-environment
if elemAt l 1 == "linux" ||
elem (elemAt l 2) ["eabi" "eabihf" "elf" "gnu"]
else if elemAt l 1 == "linux" ||
elemAt l 1 == "none" ||
elem (elemAt l 2) ["eabi" "eabihf" "elf" "gnu"]
then {
cpu = elemAt l 0;
kernel = elemAt l 1;
abi = elemAt l 2;
vendor = "unknown";
}
# cpu-vendor-os
else if elemAt l 1 == "apple" ||
elemAt l 1 == "solo5" ||
elem (elemAt l 2) [ "wasi" "redox" "mmixware" "ghcjs" "mingw32" ] ||
hasPrefix "freebsd" (elemAt l 2) ||
hasPrefix "netbsd" (elemAt l 2) ||
Expand All @@ -443,9 +489,7 @@ rec {

# This should revert the job done by config.guess from the gcc compiler.
mkSystemFromSkeleton = { cpu
, # Optional, but fallback too complex for here.
# Inferred below instead.
vendor ? assert false; null
, vendor ? ""
, kernel
, # Also inferred below
abi ? assert false; null
Expand All @@ -455,25 +499,44 @@ rec {
getKernel = name: kernels.${name} or (throw "Unknown kernel: ${name}");
getAbi = name: abis.${name} or (throw "Unknown ABI: ${name}");

vendor_ = getVendor vendor;

# These the three CPUs for which gnu-config will sometimes
# clobber an explicitly-specified `-unknown` vendor with
# something else.
clobberedVendor =
if isS390 parsed then vendors.ibm
else if isMicroBlaze parsed then vendors.xilinx
else if isMmix parsed then vendors.knuth
else if isVc4 parsed then vendors."" # hack for nonstandard triple
else vendors.unknown;

parsed = {
cpu = getCpu args.cpu;
vendor =
/**/ if args ? vendor then getVendor args.vendor
else if isDarwin parsed then vendors.apple
else if isWindows parsed then vendors.pc
else vendors.unknown;
if vendor_ == vendors.unknown then clobberedVendor
else if vendor_ != vendors."" then vendor_
else if ((isx86_64 parsed || isi686 parsed) && !isWindows parsed) &&
parsed.abi == abis.gnu then
vendors.unknown # nixpkgs-specific behavior
else if (isx86_64 parsed || isAarch64 parsed) &&
isLittleEndian parsed &&
parsed.kernel == kernels.darwin &&
parsed.abi == abis.unknown then
vendors.apple # nixpkgs-specific behavior
else if isx86 parsed && (isLinux parsed || isWindows parsed) then vendors.pc
else if isWindows parsed && vendor_ == vendors."" then clobberedVendor
else if (args?abi && (args.abi=="eabi" || args.abi=="eabihf")) && !(isLinux parsed || isNetBSD parsed) then vendor_
else if isx86 parsed then vendors.pc
else clobberedVendor;

kernel = if hasPrefix "darwin" args.kernel then getKernel "darwin"
else if hasPrefix "netbsd" args.kernel then getKernel "netbsd"
else getKernel args.kernel;
abi =
/**/ if args ? abi then getAbi args.abi
else if isLinux parsed || isWindows parsed then
if isAarch32 parsed then
if lib.versionAtLeast (parsed.cpu.version or "0") "6"
then abis.gnueabihf
else abis.gnueabi
# Default ppc64 BE to ELFv2
else if isPower64 parsed && isBigEndian parsed then abis.gnuabielfv2
else if isLinux parsed then
if isAarch32 parsed && parsed.vendor == vendors.apple then abis.gnu
else abis.gnu
else abis.unknown;
};
Expand All @@ -485,18 +548,56 @@ rec {
kernelName = kernel:
kernel.name + toString (kernel.version or "");

doubleFromSystem = { cpu, kernel, abi, ... }:
doubleFromSystem = { cpu, kernel, abi, ... }@platform:
/**/ if abi == abis.cygnus then "${cpu.name}-cygwin"
else if kernel.families ? darwin then "${cpu.name}-darwin"
else if isVc4 platform then "${cpu.name}-${abi.name}" # hack for nonstandard triple
else "${cpu.name}-${kernelName kernel}";

# Convert a system into a string triple
tripleFromSystem = { cpu, vendor, kernel, abi, ... } @ sys: assert isSystem sys; let
optExecFormat =
lib.optionalString (kernel.name == "netbsd" &&
gnuNetBSDDefaultExecFormat cpu != kernel.execFormat)
kernel.execFormat.name;
optAbi = lib.optionalString (abi != abis.unknown) "-${abi.name}";
in "${cpu.name}-${vendor.name}-${kernelName kernel}${optExecFormat}${optAbi}";
in
tripleFromSkeleton {
cpu = cpu.name;
vendor = vendor.name;
kernel = kernelName kernel;
#inherit optExecFormat;
abi = abi.name;
};

# Convert a system into a string triple, erasing the distinction
# between vendors."" and vendors.unknown -- i.e. `mips-linux-gnu`
# and `mips-unknown-linux-gnu` both become
# `"mips-unknown-linux-gnu"`.
tripleFromSystemLossy = { cpu, vendor, kernel, abi, ... } @ sys: assert isSystem sys;
tripleFromSystem (sys // lib.optionalAttrs (sys.vendor == vendors."") {
vendor = vendors.unknown;
});

tripleFromSkeleton = { cpu, vendor, kernel, optExecFormat?"", abi }: let
optAbi = lib.optionalString (abi != "unknown") "-${abi}";
optVendor = lib.optionalString (vendor != "") "-${vendor}";
optKernel = lib.optionalString (kernel != "") "-${kernel}";
in
# gnu-config considers "mingw32" and "cygwin" to be kernels.
# This is obviously bogus, which is why nixpkgs has historically
# parsed them differently. However for regression testing
# reasons (see lib/tests/triples.nix) we need to replicate this
# quirk when unparsing in order to round-trip correctly.
if abi == "cygnus" then "${cpu}${optVendor}-cygwin"
else "${cpu}${optVendor}${optKernel}${optExecFormat}${optAbi}";

# To "canonicalize" a triple is to parse it and then unparse (turn
# back into a string) it.
canonicalize = triple:
lib.pipe triple [
mkSystemFromString # parse
tripleFromSystem # unparse
];

################################################################################

Expand Down
Loading