2017-05-17 17:04:27 +02:00
|
|
|
# Define the list of system with their properties.
|
|
|
|
#
|
|
|
|
# See https://clang.llvm.org/docs/CrossCompilation.html and
|
|
|
|
# http://llvm.org/docs/doxygen/html/Triple_8cpp_source.html especially
|
|
|
|
# Triple::normalize. Parsing should essentially act as a more conservative
|
|
|
|
# version of that last function.
|
2018-01-29 23:50:13 +01:00
|
|
|
#
|
|
|
|
# Most of the types below come in "open" and "closed" pairs. The open ones
|
|
|
|
# specify what information we need to know about systems in general, and the
|
|
|
|
# closed ones are sub-types representing the whitelist of systems we support in
|
|
|
|
# practice.
|
|
|
|
#
|
|
|
|
# Code in the remainder of nixpkgs shouldn't rely on the closed ones in
|
|
|
|
# e.g. exhaustive cases. Its more a sanity check to make sure nobody defines
|
|
|
|
# systems that overlap with existing ones and won't notice something amiss.
|
|
|
|
#
|
2017-07-29 02:05:35 +02:00
|
|
|
{ lib }:
|
|
|
|
with lib.lists;
|
|
|
|
with lib.types;
|
|
|
|
with lib.attrsets;
|
2018-07-25 03:02:46 +02:00
|
|
|
with lib.strings;
|
2017-07-29 02:05:35 +02:00
|
|
|
with (import ./inspect.nix { inherit lib; }).predicates;
|
2009-11-19 18:19:39 +01:00
|
|
|
|
|
|
|
let
|
2018-01-29 23:50:13 +01:00
|
|
|
inherit (lib.options) mergeOneOption;
|
|
|
|
|
|
|
|
setTypes = type:
|
2009-11-19 18:19:39 +01:00
|
|
|
mapAttrs (name: value:
|
2018-01-29 23:50:13 +01:00
|
|
|
assert type.check value;
|
|
|
|
setType type.name ({ inherit name; } // value));
|
2017-02-09 22:09:47 +01:00
|
|
|
|
2023-06-07 18:39:42 +02:00
|
|
|
# gnu-config will ignore the portion of a triple matching the
|
|
|
|
# regex `e?abi.*$` when determining the validity of a triple. In
|
|
|
|
# other words, `i386-linuxabichickenlips` is a valid triple.
|
|
|
|
removeAbiSuffix = x:
|
|
|
|
let match = builtins.match "(.*)e?abi.*" x;
|
|
|
|
in if match==null
|
|
|
|
then x
|
|
|
|
else lib.elemAt match 0;
|
|
|
|
|
2009-11-19 18:19:39 +01:00
|
|
|
in
|
|
|
|
|
|
|
|
rec {
|
|
|
|
|
2018-01-29 23:50:13 +01:00
|
|
|
################################################################################
|
|
|
|
|
2018-04-14 03:41:04 +02:00
|
|
|
types.openSignificantByte = mkOptionType {
|
2018-01-29 23:50:13 +01:00
|
|
|
name = "significant-byte";
|
|
|
|
description = "Endianness";
|
|
|
|
merge = mergeOneOption;
|
|
|
|
};
|
|
|
|
|
|
|
|
types.significantByte = enum (attrValues significantBytes);
|
|
|
|
|
2018-04-14 03:41:04 +02:00
|
|
|
significantBytes = setTypes types.openSignificantByte {
|
2009-11-19 18:19:39 +01:00
|
|
|
bigEndian = {};
|
|
|
|
littleEndian = {};
|
|
|
|
};
|
|
|
|
|
2018-01-29 23:50:13 +01:00
|
|
|
################################################################################
|
|
|
|
|
|
|
|
# Reasonable power of 2
|
|
|
|
types.bitWidth = enum [ 8 16 32 64 128 ];
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
|
|
|
|
types.openCpuType = mkOptionType {
|
|
|
|
name = "cpu-type";
|
|
|
|
description = "instruction set architecture name and information";
|
|
|
|
merge = mergeOneOption;
|
|
|
|
check = x: types.bitWidth.check x.bits
|
|
|
|
&& (if 8 < x.bits
|
|
|
|
then types.significantByte.check x.significantByte
|
|
|
|
else !(x ? significantByte));
|
|
|
|
};
|
|
|
|
|
|
|
|
types.cpuType = enum (attrValues cpuTypes);
|
|
|
|
|
|
|
|
cpuTypes = with significantBytes; setTypes types.openCpuType {
|
2017-02-09 22:09:47 +01:00
|
|
|
arm = { bits = 32; significantByte = littleEndian; family = "arm"; };
|
2019-04-09 20:21:54 +02:00
|
|
|
armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; version = "5"; arch = "armv5t"; };
|
|
|
|
armv6m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; arch = "armv6-m"; };
|
|
|
|
armv6l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; arch = "armv6"; };
|
|
|
|
armv7a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7-a"; };
|
|
|
|
armv7r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7-r"; };
|
|
|
|
armv7m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7-m"; };
|
|
|
|
armv7l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7"; };
|
|
|
|
armv8a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
|
|
|
|
armv8r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
|
|
|
|
armv8m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-m"; };
|
|
|
|
aarch64 = { bits = 64; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
|
|
|
|
aarch64_be = { bits = 64; significantByte = bigEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
|
|
|
|
|
|
|
|
i386 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i386"; };
|
|
|
|
i486 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i486"; };
|
|
|
|
i586 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i586"; };
|
|
|
|
i686 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i686"; };
|
|
|
|
x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; arch = "x86-64"; };
|
2018-05-11 21:02:18 +02:00
|
|
|
|
2022-06-20 09:56:34 +02:00
|
|
|
microblaze = { bits = 32; significantByte = bigEndian; family = "microblaze"; };
|
|
|
|
microblazeel = { bits = 32; significantByte = littleEndian; family = "microblaze"; };
|
|
|
|
|
2023-05-29 12:55:40 +02:00
|
|
|
mips = { bits = 32; significantByte = bigEndian; family = "mips"; };
|
|
|
|
mipsel = { bits = 32; significantByte = littleEndian; family = "mips"; };
|
|
|
|
mips64 = { bits = 64; significantByte = bigEndian; family = "mips"; };
|
|
|
|
mips64el = { bits = 64; significantByte = littleEndian; family = "mips"; };
|
2018-05-11 21:02:18 +02:00
|
|
|
|
2020-11-04 15:13:06 +01:00
|
|
|
mmix = { bits = 64; significantByte = bigEndian; family = "mmix"; };
|
|
|
|
|
2021-07-23 20:20:02 +02:00
|
|
|
m68k = { bits = 32; significantByte = bigEndian; family = "m68k"; };
|
|
|
|
|
2017-07-09 21:12:32 +02:00
|
|
|
powerpc = { bits = 32; significantByte = bigEndian; family = "power"; };
|
2018-08-21 21:31:34 +02:00
|
|
|
powerpc64 = { bits = 64; significantByte = bigEndian; family = "power"; };
|
|
|
|
powerpc64le = { bits = 64; significantByte = littleEndian; family = "power"; };
|
2018-11-01 15:00:55 +01:00
|
|
|
powerpcle = { bits = 32; significantByte = littleEndian; family = "power"; };
|
2018-05-11 21:02:18 +02:00
|
|
|
|
2018-01-25 22:30:03 +01:00
|
|
|
riscv32 = { bits = 32; significantByte = littleEndian; family = "riscv"; };
|
|
|
|
riscv64 = { bits = 64; significantByte = littleEndian; family = "riscv"; };
|
2018-05-11 21:02:18 +02:00
|
|
|
|
2021-07-23 20:20:02 +02:00
|
|
|
s390 = { bits = 32; significantByte = bigEndian; family = "s390"; };
|
2021-09-07 11:10:38 +02:00
|
|
|
s390x = { bits = 64; significantByte = bigEndian; family = "s390"; };
|
2021-07-23 20:20:02 +02:00
|
|
|
|
2018-07-26 15:33:36 +02:00
|
|
|
sparc = { bits = 32; significantByte = bigEndian; family = "sparc"; };
|
|
|
|
sparc64 = { bits = 64; significantByte = bigEndian; family = "sparc"; };
|
|
|
|
|
2018-01-25 22:30:03 +01:00
|
|
|
wasm32 = { bits = 32; significantByte = littleEndian; family = "wasm"; };
|
|
|
|
wasm64 = { bits = 64; significantByte = littleEndian; family = "wasm"; };
|
2019-08-23 18:53:22 +02:00
|
|
|
|
2018-11-02 14:38:47 +01:00
|
|
|
alpha = { bits = 64; significantByte = littleEndian; family = "alpha"; };
|
2018-10-12 22:09:59 +02:00
|
|
|
|
2022-05-23 02:52:36 +02:00
|
|
|
rx = { bits = 32; significantByte = littleEndian; family = "rx"; };
|
2019-03-26 03:17:37 +01:00
|
|
|
msp430 = { bits = 16; significantByte = littleEndian; family = "msp430"; };
|
2018-10-12 22:09:59 +02:00
|
|
|
avr = { bits = 8; family = "avr"; };
|
2019-08-23 18:53:22 +02:00
|
|
|
|
2019-11-02 16:47:38 +01:00
|
|
|
vc4 = { bits = 32; significantByte = littleEndian; family = "vc4"; };
|
|
|
|
|
2020-11-09 21:06:44 +01:00
|
|
|
or1k = { bits = 32; significantByte = bigEndian; family = "or1k"; };
|
|
|
|
|
2023-04-27 19:04:17 +02:00
|
|
|
loongarch64 = { bits = 64; significantByte = littleEndian; family = "loongarch"; };
|
|
|
|
|
2023-02-19 16:21:57 +01:00
|
|
|
javascript = { bits = 32; significantByte = littleEndian; family = "javascript"; };
|
2017-02-09 22:09:47 +01:00
|
|
|
};
|
2009-11-19 18:19:39 +01:00
|
|
|
|
2021-06-01 16:54:14 +02:00
|
|
|
# GNU build systems assume that older NetBSD architectures are using a.out.
|
|
|
|
gnuNetBSDDefaultExecFormat = cpu:
|
2021-08-01 14:25:45 +02:00
|
|
|
if (cpu.family == "arm" && cpu.bits == 32) ||
|
|
|
|
(cpu.family == "sparc" && cpu.bits == 32) ||
|
|
|
|
(cpu.family == "m68k" && cpu.bits == 32) ||
|
|
|
|
(cpu.family == "x86" && cpu.bits == 32)
|
2021-06-01 16:54:14 +02:00
|
|
|
then execFormats.aout
|
|
|
|
else execFormats.elf;
|
|
|
|
|
2021-02-22 10:29:47 +01:00
|
|
|
# Determine when two CPUs are compatible with each other. That is,
|
|
|
|
# can code built for system B run on system A? For that to happen,
|
|
|
|
# the programs that system B accepts must be a subset of the
|
|
|
|
# programs that system A accepts.
|
|
|
|
#
|
|
|
|
# We have the following properties of the compatibility relation,
|
|
|
|
# which must be preserved when adding compatibility information for
|
|
|
|
# additional CPUs.
|
|
|
|
# - (reflexivity)
|
|
|
|
# Every CPU is compatible with itself.
|
|
|
|
# - (transitivity)
|
|
|
|
# If A is compatible with B and B is compatible with C then A is compatible with C.
|
2022-04-26 22:08:44 +02:00
|
|
|
#
|
|
|
|
# Note: Since 22.11 the archs of a mode switching CPU are no longer considered
|
|
|
|
# pairwise compatible. Mode switching implies that binaries built for A
|
|
|
|
# and B respectively can't be executed at the same time.
|
2019-02-22 04:17:51 +01:00
|
|
|
isCompatible = a: b: with cpuTypes; lib.any lib.id [
|
|
|
|
# x86
|
|
|
|
(b == i386 && isCompatible a i486)
|
|
|
|
(b == i486 && isCompatible a i586)
|
|
|
|
(b == i586 && isCompatible a i686)
|
2019-04-10 23:16:48 +02:00
|
|
|
|
|
|
|
# XXX: Not true in some cases. Like in WSL mode.
|
2019-02-22 04:17:51 +01:00
|
|
|
(b == i686 && isCompatible a x86_64)
|
|
|
|
|
2019-04-10 23:16:48 +02:00
|
|
|
# ARMv4
|
2019-02-22 04:17:51 +01:00
|
|
|
(b == arm && isCompatible a armv5tel)
|
2019-04-10 23:16:48 +02:00
|
|
|
|
|
|
|
# ARMv5
|
|
|
|
(b == armv5tel && isCompatible a armv6l)
|
|
|
|
|
|
|
|
# ARMv6
|
|
|
|
(b == armv6l && isCompatible a armv6m)
|
|
|
|
(b == armv6m && isCompatible a armv7l)
|
|
|
|
|
|
|
|
# ARMv7
|
|
|
|
(b == armv7l && isCompatible a armv7a)
|
|
|
|
(b == armv7l && isCompatible a armv7r)
|
|
|
|
(b == armv7l && isCompatible a armv7m)
|
|
|
|
|
|
|
|
# ARMv8
|
|
|
|
(b == aarch64 && a == armv8a)
|
|
|
|
(b == armv8a && isCompatible a aarch64)
|
2023-01-21 16:03:35 +01:00
|
|
|
(b == armv8r && isCompatible a armv8a)
|
|
|
|
(b == armv8m && isCompatible a armv8a)
|
2019-04-10 23:16:48 +02:00
|
|
|
|
2019-02-22 04:17:51 +01:00
|
|
|
# PowerPC
|
|
|
|
(b == powerpc && isCompatible a powerpc64)
|
2022-04-26 22:08:44 +02:00
|
|
|
(b == powerpcle && isCompatible a powerpc64le)
|
2019-02-22 04:17:51 +01:00
|
|
|
|
|
|
|
# MIPS
|
|
|
|
(b == mips && isCompatible a mips64)
|
2022-04-26 22:08:44 +02:00
|
|
|
(b == mipsel && isCompatible a mips64el)
|
2019-02-22 04:17:51 +01:00
|
|
|
|
|
|
|
# RISCV
|
|
|
|
(b == riscv32 && isCompatible a riscv64)
|
|
|
|
|
|
|
|
# SPARC
|
|
|
|
(b == sparc && isCompatible a sparc64)
|
|
|
|
|
|
|
|
# WASM
|
|
|
|
(b == wasm32 && isCompatible a wasm64)
|
|
|
|
|
|
|
|
# identity
|
|
|
|
(b == a)
|
|
|
|
];
|
|
|
|
|
2018-01-29 23:50:13 +01:00
|
|
|
################################################################################
|
|
|
|
|
|
|
|
types.openVendor = mkOptionType {
|
|
|
|
name = "vendor";
|
|
|
|
description = "vendor for the platform";
|
|
|
|
merge = mergeOneOption;
|
|
|
|
};
|
|
|
|
|
|
|
|
types.vendor = enum (attrValues vendors);
|
|
|
|
|
|
|
|
vendors = setTypes types.openVendor {
|
2017-02-09 22:09:47 +01:00
|
|
|
apple = {};
|
|
|
|
pc = {};
|
2023-06-19 05:57:47 +02:00
|
|
|
knuth = {};
|
|
|
|
|
2019-11-11 02:02:44 +01:00
|
|
|
# Actually matters, unlocking some MinGW-w64-specific options in GCC. See
|
|
|
|
# bottom of https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/
|
|
|
|
w64 = {};
|
2017-05-17 17:04:27 +02:00
|
|
|
|
2018-10-19 18:47:43 +02:00
|
|
|
none = {};
|
2017-02-09 22:09:47 +01:00
|
|
|
unknown = {};
|
|
|
|
};
|
2009-11-19 18:19:39 +01:00
|
|
|
|
2018-01-29 23:50:13 +01:00
|
|
|
################################################################################
|
|
|
|
|
|
|
|
types.openExecFormat = mkOptionType {
|
|
|
|
name = "exec-format";
|
|
|
|
description = "executable container used by the kernel";
|
|
|
|
merge = mergeOneOption;
|
|
|
|
};
|
|
|
|
|
|
|
|
types.execFormat = enum (attrValues execFormats);
|
|
|
|
|
|
|
|
execFormats = setTypes types.openExecFormat {
|
2009-11-19 18:19:39 +01:00
|
|
|
aout = {}; # a.out
|
|
|
|
elf = {};
|
|
|
|
macho = {};
|
|
|
|
pe = {};
|
2019-01-30 03:01:24 +01:00
|
|
|
wasm = {};
|
2017-05-17 17:04:27 +02:00
|
|
|
|
2017-02-09 22:09:47 +01:00
|
|
|
unknown = {};
|
2009-11-19 18:19:39 +01:00
|
|
|
};
|
|
|
|
|
2018-01-29 23:50:13 +01:00
|
|
|
################################################################################
|
|
|
|
|
|
|
|
types.openKernelFamily = mkOptionType {
|
|
|
|
name = "exec-format";
|
|
|
|
description = "executable container used by the kernel";
|
|
|
|
merge = mergeOneOption;
|
|
|
|
};
|
|
|
|
|
|
|
|
types.kernelFamily = enum (attrValues kernelFamilies);
|
|
|
|
|
|
|
|
kernelFamilies = setTypes types.openKernelFamily {
|
2017-02-09 22:09:47 +01:00
|
|
|
bsd = {};
|
2018-03-19 05:16:25 +01:00
|
|
|
darwin = {};
|
2009-11-19 18:19:39 +01:00
|
|
|
};
|
|
|
|
|
2018-01-29 23:50:13 +01:00
|
|
|
################################################################################
|
|
|
|
|
|
|
|
types.openKernel = mkOptionType {
|
|
|
|
name = "kernel";
|
|
|
|
description = "kernel name and information";
|
|
|
|
merge = mergeOneOption;
|
|
|
|
check = x: types.execFormat.check x.execFormat
|
|
|
|
&& all types.kernelFamily.check (attrValues x.families);
|
|
|
|
};
|
|
|
|
|
|
|
|
types.kernel = enum (attrValues kernels);
|
|
|
|
|
|
|
|
kernels = with execFormats; with kernelFamilies; setTypes types.openKernel {
|
2018-03-19 05:16:25 +01:00
|
|
|
# TODO(@Ericson2314): Don't want to mass-rebuild yet to keeping 'darwin' as
|
2021-06-01 16:52:18 +02:00
|
|
|
# the normalized name for macOS.
|
2020-11-04 15:13:06 +01:00
|
|
|
macos = { execFormat = macho; families = { inherit darwin; }; name = "darwin"; };
|
|
|
|
ios = { execFormat = macho; families = { inherit darwin; }; };
|
2022-10-31 13:35:51 +01:00
|
|
|
# A tricky thing about FreeBSD is that there is no stable ABI across
|
|
|
|
# versions. That means that putting in the version as part of the
|
|
|
|
# config string is paramount.
|
|
|
|
freebsd12 = { execFormat = elf; families = { inherit bsd; }; name = "freebsd"; version = 12; };
|
|
|
|
freebsd13 = { execFormat = elf; families = { inherit bsd; }; name = "freebsd"; version = 13; };
|
2020-11-04 15:13:06 +01:00
|
|
|
linux = { execFormat = elf; families = { }; };
|
|
|
|
netbsd = { execFormat = elf; families = { inherit bsd; }; };
|
|
|
|
none = { execFormat = unknown; families = { }; };
|
|
|
|
openbsd = { execFormat = elf; families = { inherit bsd; }; };
|
|
|
|
solaris = { execFormat = elf; families = { }; };
|
|
|
|
wasi = { execFormat = wasm; families = { }; };
|
|
|
|
redox = { execFormat = elf; families = { }; };
|
|
|
|
windows = { execFormat = pe; families = { }; };
|
|
|
|
ghcjs = { execFormat = unknown; families = { }; };
|
|
|
|
genode = { execFormat = elf; families = { }; };
|
|
|
|
mmixware = { execFormat = unknown; families = { }; };
|
2017-05-17 17:04:27 +02:00
|
|
|
} // { # aliases
|
2018-03-19 05:16:25 +01:00
|
|
|
# 'darwin' is the kernel for all of them. We choose macOS by default.
|
|
|
|
darwin = kernels.macos;
|
|
|
|
watchos = kernels.ios;
|
|
|
|
tvos = kernels.ios;
|
2017-05-17 17:04:27 +02:00
|
|
|
win32 = kernels.windows;
|
2017-02-09 22:09:47 +01:00
|
|
|
};
|
2009-11-19 18:19:39 +01:00
|
|
|
|
2018-01-29 23:50:13 +01:00
|
|
|
################################################################################
|
|
|
|
|
|
|
|
types.openAbi = mkOptionType {
|
|
|
|
name = "abi";
|
|
|
|
description = "binary interface for compiled code and syscalls";
|
|
|
|
merge = mergeOneOption;
|
|
|
|
};
|
|
|
|
|
|
|
|
types.abi = enum (attrValues abis);
|
|
|
|
|
|
|
|
abis = setTypes types.openAbi {
|
2018-05-10 23:31:07 +02:00
|
|
|
cygnus = {};
|
|
|
|
msvc = {};
|
2018-12-03 00:47:53 +01:00
|
|
|
|
|
|
|
# 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"; };
|
|
|
|
|
|
|
|
# Other architectures should use ELF in embedded situations.
|
|
|
|
elf = {};
|
2018-05-10 23:31:07 +02:00
|
|
|
|
2018-05-12 02:14:38 +02:00
|
|
|
androideabi = {};
|
2018-05-11 23:35:56 +02:00
|
|
|
android = {
|
|
|
|
assertions = [
|
|
|
|
{ assertion = platform: !platform.isAarch32;
|
|
|
|
message = ''
|
|
|
|
The "android" ABI is not for 32-bit ARM. Use "androideabi" instead.
|
|
|
|
'';
|
|
|
|
}
|
|
|
|
];
|
|
|
|
};
|
2018-05-10 23:31:07 +02:00
|
|
|
|
|
|
|
gnueabi = { float = "soft"; };
|
|
|
|
gnueabihf = { float = "hard"; };
|
2018-05-11 00:13:00 +02:00
|
|
|
gnu = {
|
2018-05-10 00:50:51 +02:00
|
|
|
assertions = [
|
|
|
|
{ assertion = platform: !platform.isAarch32;
|
|
|
|
message = ''
|
|
|
|
The "gnu" ABI is ambiguous on 32-bit ARM. Use "gnueabi" or "gnueabihf" instead.
|
|
|
|
'';
|
|
|
|
}
|
2022-07-25 12:20:58 +02:00
|
|
|
{ assertion = platform: with platform; !(isPower64 && isBigEndian);
|
|
|
|
message = ''
|
|
|
|
The "gnu" ABI is ambiguous on big-endian 64-bit PowerPC. Use "gnuabielfv2" or "gnuabielfv1" instead.
|
|
|
|
'';
|
|
|
|
}
|
2018-05-10 00:50:51 +02:00
|
|
|
];
|
|
|
|
};
|
2019-11-03 06:17:33 +01:00
|
|
|
gnuabi64 = { abi = "64"; };
|
lib/systems: add mips64el definitions
MIPS has a large space of {architecture,abi,endianness}; this commit
adds all of them to lib/systems/platforms.nix so we can be done with
it.
Currently lib/systems/inspect.nix has a single "isMips" predicate,
which is a bit ambiguous now that we will have both mips32 and mips64
support, with the latter having two ABIs. Let's add four new
predicates (isMips32, isMips64, isMips64n32, and isMips64n64) and
treat the now-ambiguous isMips as deprecated in favor of the
more-specific predicates. These predicates are used mainly for
enabling/disabling target-specific workarounds, and it is extremely
rare that a platform-specific workaround is needed, and both mips32
and mips64 need exactly the same workaround.
The separate predicates (isMips64n32 and isMips64n64) for ABI
distinctions are, unfortunately, useful. Boost's user-scheduled
threading (used by nix) does does not currently supports mips64n32,
which is a very desirable ABI on routers since they rarely have
more than 2**32 bytes of DRAM.
2022-02-21 05:32:52 +01:00
|
|
|
muslabi64 = { abi = "64"; };
|
|
|
|
|
|
|
|
# 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"; };
|
2018-05-10 23:31:07 +02:00
|
|
|
|
2022-07-25 12:20:58 +02:00
|
|
|
gnuabielfv2 = { abi = "elfv2"; };
|
|
|
|
gnuabielfv1 = { abi = "elfv1"; };
|
|
|
|
|
2018-05-10 23:31:07 +02:00
|
|
|
musleabi = { float = "soft"; };
|
|
|
|
musleabihf = { float = "hard"; };
|
|
|
|
musl = {};
|
|
|
|
|
2022-03-07 18:05:51 +01:00
|
|
|
uclibceabi = { float = "soft"; };
|
|
|
|
uclibceabihf = { float = "hard"; };
|
2018-05-10 23:31:07 +02:00
|
|
|
uclibc = {};
|
2017-05-17 17:04:27 +02:00
|
|
|
|
2017-02-09 22:09:47 +01:00
|
|
|
unknown = {};
|
2009-11-19 18:19:39 +01:00
|
|
|
};
|
|
|
|
|
2018-01-29 23:50:13 +01:00
|
|
|
################################################################################
|
|
|
|
|
2018-04-05 21:22:45 +02:00
|
|
|
types.parsedPlatform = mkOptionType {
|
2018-01-29 23:50:13 +01:00
|
|
|
name = "system";
|
|
|
|
description = "fully parsed representation of llvm- or nix-style platform tuple";
|
|
|
|
merge = mergeOneOption;
|
|
|
|
check = { cpu, vendor, kernel, abi }:
|
|
|
|
types.cpuType.check cpu
|
|
|
|
&& types.vendor.check vendor
|
|
|
|
&& types.kernel.check kernel
|
|
|
|
&& types.abi.check abi;
|
|
|
|
};
|
|
|
|
|
2017-02-09 22:09:47 +01:00
|
|
|
isSystem = isType "system";
|
2018-01-29 23:50:13 +01:00
|
|
|
|
|
|
|
mkSystem = components:
|
2018-04-05 21:22:45 +02:00
|
|
|
assert types.parsedPlatform.check components;
|
2018-01-29 23:50:13 +01:00
|
|
|
setType "system" components;
|
2009-11-19 18:19:39 +01:00
|
|
|
|
2017-02-09 22:09:47 +01:00
|
|
|
mkSkeletonFromList = l: {
|
2018-10-12 22:09:59 +02:00
|
|
|
"1" = if elemAt l 0 == "avr"
|
|
|
|
then { cpu = elemAt l 0; kernel = "none"; abi = "unknown"; }
|
|
|
|
else throw "Target specification with 1 components is ambiguous";
|
2017-05-17 17:04:27 +02:00
|
|
|
"2" = # We only do 2-part hacks for things Nix already supports
|
|
|
|
if elemAt l 1 == "cygwin"
|
2017-05-22 18:42:03 +02:00
|
|
|
then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; }
|
2018-12-29 09:25:20 +01:00
|
|
|
# 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"; }
|
2018-12-03 00:47:53 +01:00
|
|
|
else if (elemAt l 1) == "elf"
|
2018-12-29 09:25:20 +01:00
|
|
|
then { cpu = elemAt l 0; vendor = "unknown"; kernel = "none"; abi = elemAt l 1; }
|
2017-05-17 17:04:27 +02:00
|
|
|
else { cpu = elemAt l 0; kernel = elemAt l 1; };
|
2022-07-10 10:59:54 +02:00
|
|
|
"3" =
|
|
|
|
# cpu-kernel-environment
|
|
|
|
if elemAt l 1 == "linux" ||
|
|
|
|
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" ||
|
|
|
|
elem (elemAt l 2) [ "wasi" "redox" "mmixware" "ghcjs" "mingw32" ] ||
|
|
|
|
hasPrefix "freebsd" (elemAt l 2) ||
|
|
|
|
hasPrefix "netbsd" (elemAt l 2) ||
|
|
|
|
hasPrefix "genode" (elemAt l 2)
|
|
|
|
then {
|
|
|
|
cpu = elemAt l 0;
|
|
|
|
vendor = elemAt l 1;
|
|
|
|
kernel = if elemAt l 2 == "mingw32"
|
|
|
|
then "windows" # autotools breaks on -gnu for window
|
|
|
|
else elemAt l 2;
|
|
|
|
}
|
2017-02-09 22:09:47 +01:00
|
|
|
else throw "Target specification with 3 components is ambiguous";
|
2017-05-17 17:04:27 +02:00
|
|
|
"4" = { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; abi = elemAt l 3; };
|
2017-02-09 22:09:47 +01:00
|
|
|
}.${toString (length l)}
|
|
|
|
or (throw "system string has invalid number of hyphen-separated components");
|
2009-11-19 18:19:39 +01:00
|
|
|
|
|
|
|
# This should revert the job done by config.guess from the gcc compiler.
|
2017-02-09 22:09:47 +01:00
|
|
|
mkSystemFromSkeleton = { cpu
|
|
|
|
, # Optional, but fallback too complex for here.
|
|
|
|
# Inferred below instead.
|
|
|
|
vendor ? assert false; null
|
|
|
|
, kernel
|
|
|
|
, # Also inferred below
|
|
|
|
abi ? assert false; null
|
|
|
|
} @ args: let
|
2017-05-17 17:04:27 +02:00
|
|
|
getCpu = name: cpuTypes.${name} or (throw "Unknown CPU type: ${name}");
|
|
|
|
getVendor = name: vendors.${name} or (throw "Unknown vendor: ${name}");
|
|
|
|
getKernel = name: kernels.${name} or (throw "Unknown kernel: ${name}");
|
|
|
|
getAbi = name: abis.${name} or (throw "Unknown ABI: ${name}");
|
2017-02-09 22:09:47 +01:00
|
|
|
|
2019-08-13 23:52:01 +02:00
|
|
|
parsed = {
|
2017-02-09 22:09:47 +01:00
|
|
|
cpu = getCpu args.cpu;
|
|
|
|
vendor =
|
|
|
|
/**/ if args ? vendor then getVendor args.vendor
|
2017-05-21 19:39:23 +02:00
|
|
|
else if isDarwin parsed then vendors.apple
|
|
|
|
else if isWindows parsed then vendors.pc
|
2017-02-09 22:09:47 +01:00
|
|
|
else vendors.unknown;
|
2018-07-25 03:02:46 +02:00
|
|
|
kernel = if hasPrefix "darwin" args.kernel then getKernel "darwin"
|
|
|
|
else if hasPrefix "netbsd" args.kernel then getKernel "netbsd"
|
2023-06-07 18:39:42 +02:00
|
|
|
else getKernel (removeAbiSuffix args.kernel);
|
2017-02-09 22:09:47 +01:00
|
|
|
abi =
|
|
|
|
/**/ if args ? abi then getAbi args.abi
|
2018-12-29 09:25:20 +01:00
|
|
|
else if isLinux parsed || isWindows parsed then
|
2018-05-12 21:07:31 +02:00
|
|
|
if isAarch32 parsed then
|
|
|
|
if lib.versionAtLeast (parsed.cpu.version or "0") "6"
|
|
|
|
then abis.gnueabihf
|
|
|
|
else abis.gnueabi
|
2022-07-25 12:21:33 +02:00
|
|
|
# Default ppc64 BE to ELFv2
|
|
|
|
else if isPower64 parsed && isBigEndian parsed then abis.gnuabielfv2
|
2018-05-12 21:07:31 +02:00
|
|
|
else abis.gnu
|
2017-02-09 22:09:47 +01:00
|
|
|
else abis.unknown;
|
|
|
|
};
|
|
|
|
|
2017-05-21 19:39:23 +02:00
|
|
|
in mkSystem parsed;
|
2017-02-09 22:09:47 +01:00
|
|
|
|
|
|
|
mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s));
|
|
|
|
|
2022-10-31 13:35:51 +01:00
|
|
|
kernelName = kernel:
|
|
|
|
kernel.name + toString (kernel.version or "");
|
|
|
|
|
2019-06-16 21:59:06 +02:00
|
|
|
doubleFromSystem = { cpu, kernel, abi, ... }:
|
2018-03-19 05:16:25 +01:00
|
|
|
/**/ if abi == abis.cygnus then "${cpu.name}-cygwin"
|
|
|
|
else if kernel.families ? darwin then "${cpu.name}-darwin"
|
2022-10-31 13:35:51 +01:00
|
|
|
else "${cpu.name}-${kernelName kernel}";
|
2017-02-09 22:09:47 +01:00
|
|
|
|
|
|
|
tripleFromSystem = { cpu, vendor, kernel, abi, ... } @ sys: assert isSystem sys; let
|
2021-06-01 16:54:14 +02:00
|
|
|
optExecFormat =
|
|
|
|
lib.optionalString (kernel.name == "netbsd" &&
|
|
|
|
gnuNetBSDDefaultExecFormat cpu != kernel.execFormat)
|
|
|
|
kernel.execFormat.name;
|
2017-02-09 22:09:47 +01:00
|
|
|
optAbi = lib.optionalString (abi != abis.unknown) "-${abi.name}";
|
2022-10-31 13:35:51 +01:00
|
|
|
in "${cpu.name}-${vendor.name}-${kernelName kernel}${optExecFormat}${optAbi}";
|
2009-11-19 18:19:39 +01:00
|
|
|
|
2018-01-29 23:50:13 +01:00
|
|
|
################################################################################
|
|
|
|
|
2009-11-19 18:19:39 +01:00
|
|
|
}
|