labs/tidepool/src/lib/systems.nix
Victor Fuentes 8174d3a494 fix lib.systems.validate.compatible (#35)
Use builtins and aux `lib.fp.id` instead of nixpkgs functions for `lib.systems.validate.compatible`.

Reviewed-on: #35
Reviewed-by: Ruby Iris Juric <ruby+auxolotl@srxl.me>
Co-authored-by: Victor Fuentes <vlinkz@snowflakeos.org>
Co-committed-by: Victor Fuentes <vlinkz@snowflakeos.org>
2025-10-06 15:10:56 +00:00

2801 lines
76 KiB
Nix

{ config }:
let
inherit (config) lib;
types = config.lib.systems.types;
setTypes =
type:
let
assign =
name: value:
assert lib.errors.trace (type.check value)
"${name} is not of type ${type.name}: ${lib.generators.pretty { } value}";
lib.types.set type.name ({ inherit name; } // value);
in
builtins.mapAttrs assign;
matchAnyAttrs =
patterns:
if builtins.isList patterns then
value:
builtins.any (
pattern: if builtins.isFunction pattern then pattern value else matchAnyAttrs pattern value
) patterns
else
lib.attrs.match patterns;
getDoubles =
predicate:
builtins.map lib.systems.into.double (builtins.filter predicate lib.systems.doubles.resolved);
in
{
config = {
lib.systems = {
match = builtins.mapAttrs (lib.fp.const matchAnyAttrs) lib.systems.patterns;
platforms = {
pc = {
linux-kernel = {
name = "pc";
baseConfig = "defconfig";
# Build whatever possible as a module, if not stated in the extra config.
autoModules = true;
target = "bzImage";
};
};
pc_simplekernel = lib.attrs.mergeRecursive lib.systems.platforms.pc {
linux-kernel.autoModules = false;
};
powernv = {
linux-kernel = {
name = "PowerNV";
baseConfig = "powernv_defconfig";
target = "vmlinux";
autoModules = true;
# avoid driver/FS trouble arising from unusual page size
extraConfig = ''
PPC_64K_PAGES n
PPC_4K_PAGES y
IPV6 y
ATA_BMDMA y
ATA_SFF y
VIRTIO_MENU y
'';
};
};
##
## ARM
##
pogoplug4 = {
linux-kernel = {
name = "pogoplug4";
baseConfig = "multi_v5_defconfig";
autoModules = false;
extraConfig = ''
# Ubi for the mtd
MTD_UBI y
UBIFS_FS y
UBIFS_FS_XATTR y
UBIFS_FS_ADVANCED_COMPR y
UBIFS_FS_LZO y
UBIFS_FS_ZLIB y
UBIFS_FS_DEBUG n
'';
makeFlags = [ "LOADADDR=0x8000" ];
target = "uImage";
# TODO reenable once manual-config's config actually builds a .dtb and this is checked to be working
#DTB = true;
};
gcc = {
arch = "armv5te";
};
};
sheevaplug = {
linux-kernel = {
name = "sheevaplug";
baseConfig = "multi_v5_defconfig";
autoModules = false;
extraConfig = ''
BLK_DEV_RAM y
BLK_DEV_INITRD y
BLK_DEV_CRYPTOLOOP m
BLK_DEV_DM m
DM_CRYPT m
MD y
REISERFS_FS m
BTRFS_FS m
XFS_FS m
JFS_FS m
EXT4_FS m
USB_STORAGE_CYPRESS_ATACB m
# mv cesa requires this sw fallback, for mv-sha1
CRYPTO_SHA1 y
# Fast crypto
CRYPTO_TWOFISH y
CRYPTO_TWOFISH_COMMON y
CRYPTO_BLOWFISH y
CRYPTO_BLOWFISH_COMMON y
IP_PNP y
IP_PNP_DHCP y
NFS_FS y
ROOT_NFS y
TUN m
NFS_V4 y
NFS_V4_1 y
NFS_FSCACHE y
NFSD m
NFSD_V2_ACL y
NFSD_V3 y
NFSD_V3_ACL y
NFSD_V4 y
NETFILTER y
IP_NF_IPTABLES y
IP_NF_FILTER y
IP_NF_MATCH_ADDRTYPE y
IP_NF_TARGET_LOG y
IP_NF_MANGLE y
IPV6 m
VLAN_8021Q m
CIFS y
CIFS_XATTR y
CIFS_POSIX y
CIFS_FSCACHE y
CIFS_ACL y
WATCHDOG y
WATCHDOG_CORE y
ORION_WATCHDOG m
ZRAM m
NETCONSOLE m
# Disable OABI to have seccomp_filter (required for systemd)
# https://github.com/raspberrypi/firmware/issues/651
OABI_COMPAT n
# Fail to build
DRM n
SCSI_ADVANSYS n
USB_ISP1362_HCD n
SND_SOC n
SND_ALI5451 n
FB_SAVAGE n
SCSI_NSP32 n
ATA_SFF n
SUNGEM n
IRDA n
ATM_HE n
SCSI_ACARD n
BLK_DEV_CMD640_ENHANCED n
FUSE_FS m
# systemd uses cgroups
CGROUPS y
# Latencytop
LATENCYTOP y
# Ubi for the mtd
MTD_UBI y
UBIFS_FS y
UBIFS_FS_XATTR y
UBIFS_FS_ADVANCED_COMPR y
UBIFS_FS_LZO y
UBIFS_FS_ZLIB y
UBIFS_FS_DEBUG n
# Kdb, for kernel troubles
KGDB y
KGDB_SERIAL_CONSOLE y
KGDB_KDB y
'';
makeFlags = [ "LOADADDR=0x0200000" ];
target = "uImage";
DTB = true; # Beyond 3.10
};
gcc = {
arch = "armv5te";
};
};
raspberrypi = {
linux-kernel = {
name = "raspberrypi";
baseConfig = "bcm2835_defconfig";
DTB = true;
autoModules = true;
preferBuiltin = true;
extraConfig = ''
# Disable OABI to have seccomp_filter (required for systemd)
# https://github.com/raspberrypi/firmware/issues/651
OABI_COMPAT n
'';
target = "zImage";
};
gcc = {
arch = "armv6";
fpu = "vfp";
};
};
# Legacy attribute, for compatibility with existing configs only.
raspberrypi2 = lib.systems.platforms.armv7l-hf-multiplatform;
# Nvidia Bluefield 2 (w. crypto support)
bluefield2 = {
gcc = {
arch = "armv8-a+fp+simd+crc+crypto";
};
};
zero-gravitas = {
linux-kernel = {
name = "zero-gravitas";
baseConfig = "zero-gravitas_defconfig";
# Target verified by checking /boot on reMarkable 1 device
target = "zImage";
autoModules = false;
DTB = true;
};
gcc = {
fpu = "neon";
cpu = "cortex-a9";
};
};
zero-sugar = {
linux-kernel = {
name = "zero-sugar";
baseConfig = "zero-sugar_defconfig";
DTB = true;
autoModules = false;
preferBuiltin = true;
target = "zImage";
};
gcc = {
cpu = "cortex-a7";
fpu = "neon-vfpv4";
float-abi = "hard";
};
};
utilite = {
linux-kernel = {
name = "utilite";
maseConfig = "multi_v7_defconfig";
autoModules = false;
extraConfig = ''
# Ubi for the mtd
MTD_UBI y
UBIFS_FS y
UBIFS_FS_XATTR y
UBIFS_FS_ADVANCED_COMPR y
UBIFS_FS_LZO y
UBIFS_FS_ZLIB y
UBIFS_FS_DEBUG n
'';
makeFlags = [ "LOADADDR=0x10800000" ];
target = "uImage";
DTB = true;
};
gcc = {
cpu = "cortex-a9";
fpu = "neon";
};
};
guruplug = lib.recursiveUpdate lib.systems.platforms.sheevaplug {
# Define `CONFIG_MACH_GURUPLUG' (see
# <http://kerneltrap.org/mailarchive/git-commits-head/2010/5/19/33618>)
# and other GuruPlug-specific things. Requires the `guruplug-defconfig'
# patch.
linux-kernel.baseConfig = "guruplug_defconfig";
};
beaglebone = lib.recursiveUpdate lib.systems.platforms.armv7l-hf-multiplatform {
linux-kernel = {
name = "beaglebone";
baseConfig = "bb.org_defconfig";
autoModules = false;
extraConfig = ""; # TBD kernel config
target = "zImage";
};
};
# https://developer.android.com/ndk/guides/abis#v7a
armv7a-android = {
linux-kernel.name = "armeabi-v7a";
gcc = {
arch = "armv7-a";
float-abi = "softfp";
fpu = "vfpv3-d16";
};
};
armv7l-hf-multiplatform = {
linux-kernel = {
name = "armv7l-hf-multiplatform";
Major = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
baseConfig = "multi_v7_defconfig";
DTB = true;
autoModules = true;
preferBuiltin = true;
target = "zImage";
extraConfig = ''
# Serial port for Raspberry Pi 3. Wasn't included in ARMv7 defconfig
# until 4.17.
SERIAL_8250_BCM2835AUX y
SERIAL_8250_EXTENDED y
SERIAL_8250_SHARE_IRQ y
# Hangs ODROID-XU4
ARM_BIG_LITTLE_CPUIDLE n
# Disable OABI to have seccomp_filter (required for systemd)
# https://github.com/raspberrypi/firmware/issues/651
OABI_COMPAT n
# >=5.12 fails with:
# drivers/net/ethernet/micrel/ks8851_common.o: in function `ks8851_probe_common':
# ks8851_common.c:(.text+0x179c): undefined reference to `__this_module'
# See: https://lore.kernel.org/netdev/20210116164828.40545-1-marex@denx.de/T/
KS8851_MLL y
'';
};
gcc = {
# Some table about fpu flags:
# http://community.arm.com/servlet/JiveServlet/showImage/38-1981-3827/blogentry-103749-004812900+1365712953_thumb.png
# Cortex-A5: -mfpu=neon-fp16
# Cortex-A7 (rpi2): -mfpu=neon-vfpv4
# Cortex-A8 (beaglebone): -mfpu=neon
# Cortex-A9: -mfpu=neon-fp16
# Cortex-A15: -mfpu=neon-vfpv4
# More about FPU:
# https://wiki.debian.org/ArmHardFloatPort/VfpComparison
# vfpv3-d16 is what Debian uses and seems to be the best compromise: NEON is not supported in e.g. Scaleway or Tegra 2,
# and the above page suggests NEON is only an improvement with hand-written assembly.
arch = "armv7-a";
fpu = "vfpv3-d16";
# For Raspberry Pi the 2 the best would be:
# cpu = "cortex-a7";
# fpu = "neon-vfpv4";
};
};
aarch64-multiplatform = {
linux-kernel = {
name = "aarch64-multiplatform";
baseConfig = "defconfig";
DTB = true;
autoModules = true;
preferBuiltin = true;
extraConfig = ''
# Raspberry Pi 3 stuff. Not needed for s >= 4.10.
ARCH_BCM2835 y
BCM2835_MBOX y
BCM2835_WDT y
RASPBERRYPI_FIRMWARE y
RASPBERRYPI_POWER y
SERIAL_8250_BCM2835AUX y
SERIAL_8250_EXTENDED y
SERIAL_8250_SHARE_IRQ y
# Cavium ThunderX stuff.
PCI_HOST_THUNDER_ECAM y
# Nvidia Tegra stuff.
PCI_TEGRA y
# The default (=y) forces us to have the XHCI firmware available in initrd,
# which our initrd builder can't currently do easily.
USB_XHCI_TEGRA m
'';
target = "Image";
};
gcc = {
arch = "armv8-a";
};
};
apple-m1 = {
gcc = {
arch = "armv8.3-a+crypto+sha2+aes+crc+fp16+lse+simd+ras+rdm+rcpc";
cpu = "apple-a13";
};
};
##
## MIPS
##
ben_nanonote = {
linux-kernel = {
name = "ben_nanonote";
};
gcc = {
arch = "mips32";
float = "soft";
};
};
fuloong2f_n32 = {
linux-kernel = {
name = "fuloong2f_n32";
baseConfig = "lemote2f_defconfig";
autoModules = false;
extraConfig = ''
MIGRATION n
COMPACTION n
# nixos mounts some cgroup
CGROUPS y
BLK_DEV_RAM y
BLK_DEV_INITRD y
BLK_DEV_CRYPTOLOOP m
BLK_DEV_DM m
DM_CRYPT m
MD y
REISERFS_FS m
EXT4_FS m
USB_STORAGE_CYPRESS_ATACB m
IP_PNP y
IP_PNP_DHCP y
IP_PNP_BOOTP y
NFS_FS y
ROOT_NFS y
TUN m
NFS_V4 y
NFS_V4_1 y
NFS_FSCACHE y
NFSD m
NFSD_V2_ACL y
NFSD_V3 y
NFSD_V3_ACL y
NFSD_V4 y
# Fail to build
DRM n
SCSI_ADVANSYS n
USB_ISP1362_HCD n
SND_SOC n
SND_ALI5451 n
FB_SAVAGE n
SCSI_NSP32 n
ATA_SFF n
SUNGEM n
IRDA n
ATM_HE n
SCSI_ACARD n
BLK_DEV_CMD640_ENHANCED n
FUSE_FS m
# Needed for udev >= 150
SYSFS_DEPRECATED_V2 n
VGA_CONSOLE n
VT_HW_CONSOLE_BINDING y
SERIAL_8250_CONSOLE y
FRAMEBUFFER_CONSOLE y
EXT2_FS y
EXT3_FS y
REISERFS_FS y
MAGIC_SYSRQ y
# The kernel doesn't boot at all, with FTRACE
FTRACE n
'';
target = "vmlinux";
};
gcc = {
arch = "loongson2f";
float = "hard";
abi = "n32";
};
};
# can execute on 32bit chip
gcc_mips32r2_o32 = {
gcc = {
arch = "mips32r2";
abi = "32";
};
};
gcc_mips32r6_o32 = {
gcc = {
arch = "mips32r6";
abi = "32";
};
};
gcc_mips64r2_n32 = {
gcc = {
arch = "mips64r2";
abi = "n32";
};
};
gcc_mips64r6_n32 = {
gcc = {
arch = "mips64r6";
abi = "n32";
};
};
gcc_mips64r2_64 = {
gcc = {
arch = "mips64r2";
abi = "64";
};
};
gcc_mips64r6_64 = {
gcc = {
arch = "mips64r6";
abi = "64";
};
};
# based on:
# https://www.mail-archive.com/qemu-discuss@nongnu.org/msg05179.html
# https://gmplib.org/~tege/qemu.html#mips64-debian
mips64el-qemu-linux-gnuabi64 = {
linux-kernel = {
name = "mips64el";
baseConfig = "64r2el_defconfig";
target = "vmlinuz";
autoModules = false;
DTB = true;
# for qemu 9p passthrough filesystem
extraConfig = ''
MIPS_MALTA y
PAGE_SIZE_4KB y
CPU_LITTLE_ENDIAN y
CPU_MIPS64_R2 y
64BIT y
CPU_MIPS64_R2 y
NET_9P y
NET_9P_VIRTIO y
9P_FS y
9P_FS_POSIX_ACL y
PCI y
VIRTIO_PCI y
'';
};
};
##
## Other
##
riscv-multiplatform = {
linux-kernel = {
name = "riscv-multiplatform";
target = "Image";
autoModules = true;
baseConfig = "defconfig";
DTB = true;
extraConfig = ''
SERIAL_OF_PLATFORM y
'';
};
};
mipsel-linux-gnu = {
triple = "mipsel-unknown-linux-gnu";
}
// lib.systems.platforms.gcc_mips32r2_o32;
# This function takes a minimally-valid "platform" and returns an
# attrset containing zero or more additional attrs which should be
# included in the platform in order to further elaborate it.
select =
platform:
# x86
if platform.isx86 then
lib.systems.platforms.pc
# ARM
else if platform.isAarch32 then
let
version = platform.system.cpu.version or null;
in
if version == null then
lib.systems.platforms.pc
else if lib.versions.gte "6" version then
lib.systems.platforms.sheevaplug
else if lib.versions.gte "7" version then
lib.systems.platforms.raspberrypi
else
lib.systems.platforms.armv7l-hf-multiplatform
else if platform.isAarch64 then
if platform.isDarwin then
lib.systems.platforms.apple-m1
else
lib.systems.platforms.aarch64-multiplatform
else if platform.isRiscV then
lib.systems.platforms.riscv-multiplatform
else if platform.system.cpu == types.cpus.mipsel then
lib.systems.platforms.mipsel-linux-gnu
else if platform.system.cpu == types.cpus.powerpc64le then
lib.systems.platforms.powernv
else
{ };
};
architectures = {
features = {
# x86_64 Generic
# Spec: https://gitlab.com/x86-psABIs/x86-64-ABI/
default = [ ];
x86-64 = [ ];
x86-64-v2 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
];
x86-64-v3 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"avx"
"avx2"
"fma"
];
x86-64-v4 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"avx"
"avx2"
"avx512"
"fma"
];
# x86_64 Intel
nehalem = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
];
westmere = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
];
sandybridge = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
];
ivybridge = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
];
haswell = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"fma"
];
broadwell = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"fma"
];
skylake = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"fma"
];
skylake-avx512 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"avx512"
"fma"
];
cannonlake = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"avx512"
"fma"
];
icelake-client = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"avx512"
"fma"
];
icelake-server = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"avx512"
"fma"
];
cascadelake = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"avx512"
"fma"
];
cooperlake = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"avx512"
"fma"
];
tigerlake = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"avx512"
"fma"
];
alderlake = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
"avx2"
"fma"
];
# x86_64 AMD
btver1 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
];
btver2 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"aes"
"avx"
];
bdver1 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"sse4a"
"aes"
"avx"
"fma"
"fma4"
];
bdver2 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"sse4a"
"aes"
"avx"
"fma"
"fma4"
];
bdver3 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"sse4a"
"aes"
"avx"
"fma"
"fma4"
];
bdver4 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"sse4a"
"aes"
"avx"
"avx2"
"fma"
"fma4"
];
znver1 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"sse4a"
"aes"
"avx"
"avx2"
"fma"
];
znver2 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"sse4a"
"aes"
"avx"
"avx2"
"fma"
];
znver3 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"sse4a"
"aes"
"avx"
"avx2"
"fma"
];
znver4 = [
"sse3"
"ssse3"
"sse4_1"
"sse4_2"
"sse4a"
"aes"
"avx"
"avx2"
"avx512"
"fma"
];
# other
armv5te = [ ];
armv6 = [ ];
armv7-a = [ ];
armv8-a = [ ];
mips32 = [ ];
loongson2f = [ ];
};
# a superior CPU has all the features of an inferior and is able to build and test code for it
inferiors = {
# x86_64 Generic
default = [ ];
x86-64 = [ ];
x86-64-v2 = [ "x86-64" ];
x86-64-v3 = [ "x86-64-v2" ] ++ lib.systems.architectures.inferiors.x86-64-v2;
x86-64-v4 = [ "x86-64-v3" ] ++ lib.systems.architectures.inferiors.x86-64-v3;
# x86_64 Intel
# https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
nehalem = [ "x86-64-v2" ] ++ lib.systems.architectures.inferiors.x86-64-v2;
westmere = [ "nehalem" ] ++ lib.systems.architectures.inferiors.nehalem;
sandybridge = [ "westmere" ] ++ lib.systems.architectures.inferiors.westmere;
ivybridge = [ "sandybridge" ] ++ lib.systems.architectures.inferiors.sandybridge;
haswell = lib.unique (
[
"ivybridge"
"x86-64-v3"
]
++ lib.systems.architectures.inferiors.ivybridge
++ lib.systems.architectures.inferiors.x86-64-v3
);
broadwell = [ "haswell" ] ++ lib.systems.architectures.inferiors.haswell;
skylake = [ "broadwell" ] ++ lib.systems.architectures.inferiors.broadwell;
skylake-avx512 = lib.unique (
[
"skylake"
"x86-64-v4"
]
++ lib.systems.architectures.inferiors.skylake
++ lib.systems.architectures.inferiors.x86-64-v4
);
cannonlake = [ "skylake-avx512" ] ++ lib.systems.architectures.inferiors.skylake-avx512;
icelake-client = [ "cannonlake" ] ++ lib.systems.architectures.inferiors.cannonlake;
icelake-server = [ "icelake-client" ] ++ lib.systems.architectures.inferiors.icelake-client;
cascadelake = [ "cannonlake" ] ++ lib.systems.architectures.inferiors.cannonlake;
cooperlake = [ "cascadelake" ] ++ lib.systems.architectures.inferiors.cascadelake;
tigerlake = [ "icelake-server" ] ++ lib.systems.architectures.inferiors.icelake-server;
# CX16 does not exist on alderlake, while it does on nearly all other intel CPUs
alderlake = [ ];
# x86_64 AMD
# TODO: fill this (need testing)
btver1 = [ ];
btver2 = [ ];
bdver1 = [ ];
bdver2 = [ ];
bdver3 = [ ];
bdver4 = [ ];
# Regarding `skylake` as inferior of `znver1`, there are reports of
# successful usage by Gentoo users and Phoronix benchmarking of different
# `-march` targets.
#
# The GCC documentation on extensions used and wikichip documentation
# regarding supperted extensions on znver1 and skylake was used to create
# this partial order.
#
# Note:
#
# - The successors of `skylake` (`cannonlake`, `icelake`, etc) use `avx512`
# which no current AMD Zen michroarch support.
# - `znver1` uses `ABM`, `CLZERO`, `CX16`, `MWAITX`, and `SSE4A` which no
# current Intel microarch support.
#
# https://www.phoronix.com/scan.php?page=article&item=amd-znver3-gcc11&num=1
# https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
# https://en.wikichip.org/wiki/amd/microarchitectures/zen
# https://en.wikichip.org/wiki/intel/microarchitectures/skylake
znver1 = [ "skylake" ] ++ lib.systems.architectures.inferiors.skylake; # Includes haswell and x86-64-v3
znver2 = [ "znver1" ] ++ lib.systems.architectures.inferiors.znver1;
znver3 = [ "znver2" ] ++ lib.systems.architectures.inferiors.znver2;
znver4 = lib.unique (
[
"znver3"
"x86-64-v4"
]
++ lib.systems.architectures.inferiors.znver3
++ lib.systems.architectures.inferiors.x86-64-v4
);
# other
armv5te = [ ];
armv6 = [ ];
armv7-a = [ ];
armv8-a = [ ];
mips32 = [ ];
loongson2f = [ ];
};
};
validate = {
architecture =
let
isSupported = feature: x: builtins.elem feature (lib.systems.architectures.features.${x} or [ ]);
in
{
sse3Support = isSupported "sse3";
ssse3Support = isSupported "ssse3";
sse4_1Support = isSupported "sse4_1";
sse4_2Support = isSupported "sse4_2";
sse4_aSupport = isSupported "sse4a";
avxSupport = isSupported "avx";
avx2Support = isSupported "avx2";
avx512Support = isSupported "avx512";
aesSupport = isSupported "aes";
fmaSupport = isSupported "fma";
fma4Support = isSupported "fma4";
};
compatible =
a: b:
builtins.any lib.fp.id [
# x86
(b == lib.systems.types.cpus.i386 && lib.systems.validate.compatible a lib.systems.types.cpus.i486)
(b == lib.systems.types.cpus.i486 && lib.systems.validate.compatible a lib.systems.types.cpus.i586)
(b == lib.systems.types.cpus.i586 && lib.systems.validate.compatible a lib.systems.types.cpus.i686)
# XXX: Not true in some cases. Like in WSL mode.
(
b == lib.systems.types.cpus.i686 && lib.systems.validate.compatible a lib.systems.types.cpus.x86_64
)
# ARMv4
(
b == lib.systems.types.cpus.arm && lib.systems.validate.compatible a lib.systems.types.cpus.armv5tel
)
# ARMv5
(
b == lib.systems.types.cpus.armv5tel
&& lib.systems.validate.compatible a lib.systems.types.cpus.armv6l
)
# ARMv6
(
b == lib.systems.types.cpus.armv6l
&& lib.systems.validate.compatible a lib.systems.types.cpus.armv6m
)
(
b == lib.systems.types.cpus.armv6m
&& lib.systems.validate.compatible a lib.systems.types.cpus.armv7l
)
# ARMv7
(
b == lib.systems.types.cpus.armv7l
&& lib.systems.validate.compatible a lib.systems.types.cpus.armv7a
)
(
b == lib.systems.types.cpus.armv7l
&& lib.systems.validate.compatible a lib.systems.types.cpus.armv7r
)
(
b == lib.systems.types.cpus.armv7l
&& lib.systems.validate.compatible a lib.systems.types.cpus.armv7m
)
# ARMv8
(b == lib.systems.types.cpus.aarch64 && a == lib.systems.types.cpus.armv8a)
(
b == lib.systems.types.cpus.armv8a
&& lib.systems.validate.compatible a lib.systems.types.cpus.aarch64
)
(
b == lib.systems.types.cpus.armv8r
&& lib.systems.validate.compatible a lib.systems.types.cpus.armv8a
)
(
b == lib.systems.types.cpus.armv8m
&& lib.systems.validate.compatible a lib.systems.types.cpus.armv8a
)
# PowerPC
(
b == lib.systems.types.cpus.powerpc
&& lib.systems.validate.compatible a lib.systems.types.cpus.powerpc64
)
(
b == lib.systems.types.cpus.powerpcle
&& lib.systems.validate.compatible a lib.systems.types.cpus.powerpc64le
)
# MIPS
(
b == lib.systems.types.cpus.mips && lib.systems.validate.compatible a lib.systems.types.cpus.mips64
)
(
b == lib.systems.types.cpus.mipsel
&& lib.systems.validate.compatible a lib.systems.types.cpus.mips64el
)
# RISCV
(
b == lib.systems.types.cpus.riscv32
&& lib.systems.validate.compatible a lib.systems.types.cpus.riscv64
)
# SPARC
(
b == lib.systems.types.cpus.sparc
&& lib.systems.validate.compatible a lib.systems.types.cpus.sparc64
)
# WASM
(
b == lib.systems.types.cpus.wasm32
&& lib.systems.validate.compatible a lib.systems.types.cpus.wasm64
)
# identity
(b == a)
];
};
types = {
generic = {
endian = lib.types.create {
name = "Endian";
description = "Endianness";
merge = lib.options.merge.one;
};
cpu = lib.types.create {
name = "Cpu";
description = "Instruction set architecture name and information";
merge = lib.options.merge.one;
check =
x: types.bits.check x.bits && (if 8 < x.bits then types.endian.check x.endian else !(x ? endian));
};
family = lib.types.create {
name = "Family";
description = "The kernel family.";
merge = lib.options.merge.one;
};
exec = lib.types.create {
name = "Exec";
description = "Executable container used by the kernel";
merge = lib.options.merge.one;
};
kernel = lib.types.create {
name = "Kernel";
description = "Kernel name and information";
merge = lib.options.merge.one;
check =
value:
types.exec.check value.exec && builtins.all types.family.check (builtins.attrValues value.families);
};
abi = lib.types.create {
name = "Abi";
description = "Binary interface for compiled code and syscalls";
merge = lib.options.merge.one;
};
vendor = lib.types.create {
name = "Vendor";
description = "Vendor for the platform";
merge = lib.options.merge.one;
};
};
platform = lib.types.create {
name = "system";
description = "fully parsed representation of llvm- or nix-style platform tuple";
merge = lib.options.merge.one;
check =
{
cpu,
vendor,
kernel,
abi,
...
}:
types.cpu.check cpu
&& types.vendor.check vendor
&& types.kernel.check kernel
&& types.abi.check abi;
};
platformWithBuildInfo = lib.types.create {
name = "systemWithBuildInfo";
description = "fully parsed representation of llvm- or nix-style platform tuple with build information";
merge = lib.options.merge.one;
check =
value:
lib.types.is "systemWithBuildInfo" value
&& value ? system
&& lib.systems.types.platform.check value.system;
};
endian = lib.types.enum (builtins.attrValues types.endians);
endians = setTypes types.generic.endian {
big = { };
little = { };
};
bits = lib.types.enum [
8
16
32
64
128
];
exec = lib.types.enum (builtins.attrValues types.execs);
execs = setTypes types.generic.exec {
aout = { }; # a.out
elf = { };
macho = { };
pe = { };
wasm = { };
unknown = { };
};
vendor = lib.types.enum (builtins.attrValues types.vendors);
vendors = setTypes types.generic.vendor {
apple = { };
pc = { };
knuth = { };
# Actually matters, unlocking some MinGW-w64-specific options in GCC. See
# bottom of https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/
w64 = { };
none = { };
unknown = { };
};
family = lib.types.enum (builtins.attrValues types.families);
families = setTypes types.generic.family {
bsd = { };
darwin = { };
};
kernel = lib.types.enum (builtins.attrValues types.kernels);
kernels = setTypes types.generic.kernel {
# TODO(@Ericson2314): Don't want to mass-rebuild yet to keeping 'darwin' as
# the normalized name for macOS.
macos = {
exec = types.execs.macho;
families = {
darwin = types.families.darwin;
};
name = "darwin";
};
ios = {
exec = types.execs.macho;
families = {
darwin = types.families.darwin;
};
};
# 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 = {
exec = types.execs.elf;
families = {
bsd = types.families.bsd;
};
name = "freebsd";
version = 12;
};
freebsd13 = {
exec = types.execs.elf;
families = {
bsd = types.families.bsd;
};
name = "freebsd";
version = 13;
};
linux = {
exec = types.execs.elf;
families = { };
};
netbsd = {
exec = types.execs.elf;
families = {
bsd = types.families.bsd;
};
};
none = {
exec = types.execs.unknown;
families = { };
};
openbsd = {
exec = types.execs.elf;
families = {
bsd = types.families.bsd;
};
};
solaris = {
exec = types.execs.elf;
families = { };
};
wasi = {
exec = types.execs.wasm;
families = { };
};
redox = {
exec = types.execs.elf;
families = { };
};
windows = {
exec = types.execs.pe;
families = { };
};
ghcjs = {
exec = types.execs.unknown;
families = { };
};
genode = {
exec = types.execs.elf;
families = { };
};
mmixware = {
exec = types.execs.unknown;
families = { };
};
# aliases
# 'darwin' is the kernel for all of them. We choose macOS by default.
darwin = types.kernels.macos;
watchos = types.kernels.ios;
tvos = types.kernels.ios;
win32 = types.kernels.windows;
};
cpu = lib.types.enum (builtins.attrValues types.cpus);
cpus = setTypes types.generic.cpu {
arm = {
bits = 32;
endian = types.endians.little;
family = "arm";
};
armv5tel = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "5";
arch = "armv5t";
};
armv6m = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "6";
arch = "armv6-m";
};
armv6l = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "6";
arch = "armv6";
};
armv7a = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "7";
arch = "armv7-a";
};
armv7r = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "7";
arch = "armv7-r";
};
armv7m = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "7";
arch = "armv7-m";
};
armv7l = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "7";
arch = "armv7";
};
armv8a = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "8";
arch = "armv8-a";
};
armv8r = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "8";
arch = "armv8-a";
};
armv8m = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "8";
arch = "armv8-m";
};
aarch64 = {
bits = 64;
endian = types.endians.little;
family = "arm";
version = "8";
arch = "armv8-a";
};
aarch64_be = {
bits = 64;
endian = types.endians.big;
family = "arm";
version = "8";
arch = "armv8-a";
};
i386 = {
bits = 32;
endian = types.endians.little;
family = "x86";
arch = "i386";
};
i486 = {
bits = 32;
endian = types.endians.little;
family = "x86";
arch = "i486";
};
i586 = {
bits = 32;
endian = types.endians.little;
family = "x86";
arch = "i586";
};
i686 = {
bits = 32;
endian = types.endians.little;
family = "x86";
arch = "i686";
};
x86_64 = {
bits = 64;
endian = types.endians.little;
family = "x86";
arch = "x86-64";
};
microblaze = {
bits = 32;
endian = types.endians.big;
family = "microblaze";
};
microblazeel = {
bits = 32;
endian = types.endians.little;
family = "microblaze";
};
mips = {
bits = 32;
endian = types.endians.big;
family = "mips";
};
mipsel = {
bits = 32;
endian = types.endians.little;
family = "mips";
};
mips64 = {
bits = 64;
endian = types.endians.big;
family = "mips";
};
mips64el = {
bits = 64;
endian = types.endians.little;
family = "mips";
};
mmix = {
bits = 64;
endian = types.endians.big;
family = "mmix";
};
m68k = {
bits = 32;
endian = types.endians.big;
family = "m68k";
};
powerpc = {
bits = 32;
endian = types.endians.big;
family = "power";
};
powerpc64 = {
bits = 64;
endian = types.endians.big;
family = "power";
};
powerpc64le = {
bits = 64;
endian = types.endians.little;
family = "power";
};
powerpcle = {
bits = 32;
endian = types.endians.little;
family = "power";
};
riscv32 = {
bits = 32;
endian = types.endians.little;
family = "riscv";
};
riscv64 = {
bits = 64;
endian = types.endians.little;
family = "riscv";
};
s390 = {
bits = 32;
endian = types.endians.big;
family = "s390";
};
s390x = {
bits = 64;
endian = types.endians.big;
family = "s390";
};
sparc = {
bits = 32;
endian = types.endians.big;
family = "sparc";
};
sparc64 = {
bits = 64;
endian = types.endians.big;
family = "sparc";
};
wasm32 = {
bits = 32;
endian = types.endians.little;
family = "wasm";
};
wasm64 = {
bits = 64;
endian = types.endians.little;
family = "wasm";
};
alpha = {
bits = 64;
endian = types.endians.little;
family = "alpha";
};
rx = {
bits = 32;
endian = types.endians.little;
family = "rx";
};
msp430 = {
bits = 16;
endian = types.endians.little;
family = "msp430";
};
avr = {
bits = 8;
family = "avr";
};
vc4 = {
bits = 32;
endian = types.endians.little;
family = "vc4";
};
or1k = {
bits = 32;
endian = types.endians.big;
family = "or1k";
};
loongarch64 = {
bits = 64;
endian = types.endians.little;
family = "loongarch";
};
javascript = {
bits = 32;
endian = types.endians.little;
family = "javascript";
};
};
abi = lib.types.enum (builtins.attrValues types.abis);
abis = setTypes types.generic.abi {
cygnus = { };
msvc = { };
# 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 = { };
androideabi = { };
android = {
assertions = [
{
assertion = platform: !platform.isAarch32;
message = ''
The "android" ABI is not for 32-bit ARM. Use "androideabi" instead.
'';
}
];
};
gnueabi = {
float = "soft";
};
gnueabihf = {
float = "hard";
};
gnu = {
assertions = [
{
assertion = platform: !platform.isAarch32;
message = ''
The "gnu" ABI is ambiguous on 32-bit ARM. Use "gnueabi" or "gnueabihf" instead.
'';
}
{
assertion = platform: with platform; !(isPower64 && isBigEndian);
message = ''
The "gnu" ABI is ambiguous on big-endian 64-bit PowerPC. Use "gnuabielfv2" or "gnuabielfv1" instead.
'';
}
];
};
gnuabi64 = {
abi = "64";
};
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";
};
gnuabielfv2 = {
abi = "elfv2";
};
gnuabielfv1 = {
abi = "elfv1";
};
musleabi = {
float = "soft";
};
musleabihf = {
float = "hard";
};
musl = { };
uclibceabi = {
float = "soft";
};
uclibceabihf = {
float = "hard";
};
uclibc = { };
unknown = { };
};
};
from = {
string =
value:
let
parts = lib.strings.split "-" value;
skeleton = lib.systems.skeleton parts;
system = lib.systems.create (lib.systems.from.skeleton skeleton);
in
system;
skeleton =
spec@{
cpu,
vendor ?
assert false;
null,
kernel,
abi ?
assert false;
null,
}:
let
getCpu = name: types.cpus.${name} or (throw "Unknown CPU type: ${name}");
getVendor = name: types.vendors.${name} or (throw "Unknown vendor: ${name}");
getKernel = name: types.kernels.${name} or (throw "Unknown kernel: ${name}");
getAbi = name: types.abis.${name} or (throw "Unknown ABI: ${name}");
resolved = {
cpu = getCpu spec.cpu;
vendor =
if spec ? vendor then
getVendor spec.vendor
else if lib.systems.match.isDarwin resolved then
types.vendors.apple
else if lib.systems.match.isWindows resolved then
types.vendors.pc
else
types.vendors.unknown;
kernel =
if lib.strings.hasPrefix "darwin" spec.kernel then
getKernel "darwin"
else if lib.strings.hasPrefix "netbsd" spec.kernel then
getKernel "netbsd"
else
getKernel spec.kernel;
abi =
if spec ? abi then
getAbi spec.abi
else if lib.systems.match.isLinux resolved || lib.systems.match.isWindows resolved then
if lib.systems.match.isAarch32 resolved then
if lib.versions.gte "6" (resolved.cpu.version) then types.abis.gnueabihf else types.abis.gnueabi
else if lib.systems.match.isPower64 resolved && lib.systems.match.isBigEndian resolved then
types.abis.gnuabielfv2
else
types.abis.gnu
else
types.abis.unknown;
};
in
resolved;
};
into = {
double =
{
cpu,
kernel,
abi,
...
}:
let
kernelName = kernel.name + builtins.toString (kernel.version or "");
in
if abi == types.abis.cygnus then
"${cpu.name}-cygwin"
else if kernel.families ? darwin then
"${cpu.name}-darwin"
else
"${cpu.name}-${kernelName}";
triple =
{
cpu,
vendor,
kernel,
abi,
...
}:
let
kernelName = kernel.name + builtins.toString (kernel.version or "");
netbsdExec =
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)
then
types.execs.aout
else
types.execs.elf;
exec = lib.strings.when (kernel.name == "netbsd" && netbsdExec != kernel.exec) kernel.exec.name;
abi' = lib.strings.when (abi != types.abis.unknown) "-${abi.name}";
in
"${cpu.name}-${vendor.name}-${kernelName}${exec}${abi'}";
};
create =
components:
assert types.platform.check components;
lib.types.set "system" components;
skeleton =
parts:
let
length = builtins.length parts;
first = builtins.elemAt parts 0;
second = builtins.elemAt parts 1;
third = builtins.elemAt parts 2;
fourth = builtins.elemAt parts 3;
in
if length == 1 then
if first == "avr" then
{
cpu = first;
kernel = "none";
abi = "unknown";
}
else
builtins.throw "Target specification with 1 component is ambiguous."
else if length == 2 then
if second == "cygwin" then
{
cpu = first;
kernel = "windows";
abi = "cygnus";
}
else if second == "windows" then
{
cpu = first;
kernel = "windows";
abi = "msvc";
}
else if second == "elf" then
{
cpu = first;
vendor = "unkonwn";
kernel = "none";
abi = second;
}
else
{
cpu = first;
kernel = second;
}
else if length == 3 then
if
second == "linux"
|| (builtins.elem third [
"eabi"
"eabihf"
"elf"
"gnu"
])
then
{
cpu = first;
vendor = "unknown";
kernel = second;
abi = third;
}
else if
(second == "apple")
|| lib.strings.hasPrefix "freebsd" third
|| lib.strings.hasPrefix "netbsd" third
|| lib.strings.hasPrefix "genode" third
|| (builtins.elem third [
"wasi"
"redox"
"mmixware"
"ghcjs"
"mingw32"
])
then
{
cpu = first;
vendor = second;
kernel = if third == "mingw32" then "windows" else third;
}
else
builtins.throw "Target specification with 3 components is ambiguous."
else if length == 4 then
{
cpu = first;
vendor = second;
kernel = third;
abi = fourth;
}
else
builtins.throw "Invalid component count for creating system skeleton. Expected 1-4, but got ${builtins.toString length}.";
patterns = {
isi686 = {
cpu = types.cpus.i686;
};
isx86_32 = {
cpu = {
family = "x86";
bits = 32;
};
};
isx86_64 = {
cpu = {
family = "x86";
bits = 64;
};
};
isPower = {
cpu = {
family = "power";
};
};
isPower64 = {
cpu = {
family = "power";
bits = 64;
};
};
# This ABI is the default in NixOS PowerPC64 BE, but not on mainline GCC,
# so it sometimes causes issues in certain packages that makes the wrong
# assumption on the used ABI.
isAbiElfv2 = [
{
abi = {
abi = "elfv2";
};
}
{
abi = {
name = "musl";
};
cpu = {
family = "power";
bits = 64;
};
}
];
isx86 = {
cpu = {
family = "x86";
};
};
isAarch32 = {
cpu = {
family = "arm";
bits = 32;
};
};
isArmv7 =
map
(
{ arch, ... }:
{
cpu = {
inherit arch;
};
}
)
(
builtins.filter (cpu: lib.strings.hasPrefix "armv7" cpu.arch or "") (builtins.attrValues types.cpus)
);
isAarch64 = {
cpu = {
family = "arm";
bits = 64;
};
};
isAarch = {
cpu = {
family = "arm";
};
};
isMicroBlaze = {
cpu = {
family = "microblaze";
};
};
isMips = {
cpu = {
family = "mips";
};
};
isMips32 = {
cpu = {
family = "mips";
bits = 32;
};
};
isMips64 = {
cpu = {
family = "mips";
bits = 64;
};
};
isMips64n32 = {
cpu = {
family = "mips";
bits = 64;
};
abi = {
abi = "n32";
};
};
isMips64n64 = {
cpu = {
family = "mips";
bits = 64;
};
abi = {
abi = "64";
};
};
isMmix = {
cpu = {
family = "mmix";
};
};
isRiscV = {
cpu = {
family = "riscv";
};
};
isRiscV32 = {
cpu = {
family = "riscv";
bits = 32;
};
};
isRiscV64 = {
cpu = {
family = "riscv";
bits = 64;
};
};
isRx = {
cpu = {
family = "rx";
};
};
isSparc = {
cpu = {
family = "sparc";
};
};
isWasm = {
cpu = {
family = "wasm";
};
};
isMsp430 = {
cpu = {
family = "msp430";
};
};
isVc4 = {
cpu = {
family = "vc4";
};
};
isAvr = {
cpu = {
family = "avr";
};
};
isAlpha = {
cpu = {
family = "alpha";
};
};
isOr1k = {
cpu = {
family = "or1k";
};
};
isM68k = {
cpu = {
family = "m68k";
};
};
isS390 = {
cpu = {
family = "s390";
};
};
isS390x = {
cpu = {
family = "s390";
bits = 64;
};
};
isLoongArch64 = {
cpu = {
family = "loongarch";
bits = 64;
};
};
isJavaScript = {
cpu = types.cpus.javascript;
};
is32bit = {
cpu = {
bits = 32;
};
};
is64bit = {
cpu = {
bits = 64;
};
};
isILP32 =
builtins.map
(a: {
abi = {
abi = a;
};
})
[
"n32"
"ilp32"
"x32"
];
isBigEndian = {
cpu = {
endian = types.endians.big;
};
};
isLittleEndian = {
cpu = {
endian = types.endians.little;
};
};
isBSD = {
kernel = {
families = {
bsd = types.families.bsd;
};
};
};
isDarwin = {
kernel = {
families = {
darwin = types.families.darwin;
};
};
};
isUnix = [
lib.systems.match.isBSD
lib.systems.match.isDarwin
lib.systems.match.isLinux
lib.systems.match.isSunOS
lib.systems.match.isCygwin
lib.systems.match.isRedox
];
isMacOS = {
kernel = types.kernels.macos;
};
isiOS = {
kernel = types.kernels.ios;
};
isLinux = {
kernel = types.kernels.linux;
};
isSunOS = {
kernel = types.kernels.solaris;
};
isFreeBSD = {
kernel = {
name = "freebsd";
};
};
isNetBSD = {
kernel = types.kernels.netbsd;
};
isOpenBSD = {
kernel = types.kernels.openbsd;
};
isWindows = {
kernel = types.kernels.windows;
};
isCygwin = {
kernel = types.kernels.windows;
abi = types.abis.cygnus;
};
isMinGW = {
kernel = types.kernels.windows;
abi = types.abis.gnu;
};
isWasi = {
kernel = types.kernels.wasi;
};
isRedox = {
kernel = types.kernels.redox;
};
isGhcjs = {
kernel = types.kernels.ghcjs;
};
isGenode = {
kernel = types.kernels.genode;
};
isNone = {
kernel = types.kernels.none;
};
isAndroid = [
{ abi = types.abis.android; }
{ abi = types.abis.androideabi; }
];
isGnu = builtins.map (value: { abi = value; }) [
types.abis.gnuabi64
types.abis.gnuabin32
types.abis.gnu
types.abis.gnueabi
types.abis.gnueabihf
types.abis.gnuabielfv1
types.abis.gnuabielfv2
];
isMusl = builtins.map (value: { abi = value; }) [
types.abis.musl
types.abis.musleabi
types.abis.musleabihf
types.abis.muslabin32
types.abis.muslabi64
];
isUClibc = builtins.map (value: { abi = value; }) [
types.abis.uclibc
types.abis.uclibceabi
types.abis.uclibceabihf
];
isEfi = [
{
cpu = {
family = "arm";
version = "6";
};
}
{
cpu = {
family = "arm";
version = "7";
};
}
{
cpu = {
family = "arm";
version = "8";
};
}
{
cpu = {
family = "riscv";
};
}
{
cpu = {
family = "x86";
};
}
];
};
doubles = {
resolved = builtins.map lib.systems.from.string lib.systems.doubles.all;
all = [
# Cygwin
"i686-cygwin"
"x86_64-cygwin"
# Darwin
"x86_64-darwin"
"i686-darwin"
"aarch64-darwin"
"armv7a-darwin"
# FreeBSD
"i686-freebsd13"
"x86_64-freebsd13"
# Genode
"aarch64-genode"
"i686-genode"
"x86_64-genode"
# illumos
"x86_64-solaris"
# JS
"javascript-ghcjs"
# Linux
"aarch64-linux"
"armv5tel-linux"
"armv6l-linux"
"armv7a-linux"
"armv7l-linux"
"i686-linux"
"loongarch64-linux"
"m68k-linux"
"microblaze-linux"
"microblazeel-linux"
"mips-linux"
"mips64-linux"
"mips64el-linux"
"mipsel-linux"
"powerpc64-linux"
"powerpc64le-linux"
"riscv32-linux"
"riscv64-linux"
"s390-linux"
"s390x-linux"
"x86_64-linux"
# MMIXware
"mmix-mmixware"
# NetBSD
"aarch64-netbsd"
"armv6l-netbsd"
"armv7a-netbsd"
"armv7l-netbsd"
"i686-netbsd"
"m68k-netbsd"
"mipsel-netbsd"
"powerpc-netbsd"
"riscv32-netbsd"
"riscv64-netbsd"
"x86_64-netbsd"
# none
"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"
# OpenBSD
"i686-openbsd"
"x86_64-openbsd"
# Redox
"x86_64-redox"
# WASI
"wasm64-wasi"
"wasm32-wasi"
# Windows
"x86_64-windows"
"i686-windows"
];
arm = getDoubles lib.systems.match.isAarch32;
armv7 = getDoubles lib.systems.match.isArmv7;
aarch64 = getDoubles lib.systems.match.isAarch64;
x86 = getDoubles lib.systems.match.isx86;
i686 = getDoubles lib.systems.match.isi686;
x86_64 = getDoubles lib.systems.match.isx86_64;
microblaze = getDoubles lib.systems.match.isMicroBlaze;
mips = getDoubles lib.systems.match.isMips;
mmix = getDoubles lib.systems.match.isMmix;
power = getDoubles lib.systems.match.isPower;
riscv = getDoubles lib.systems.match.isRiscV;
riscv32 = getDoubles lib.systems.match.isRiscV32;
riscv64 = getDoubles lib.systems.match.isRiscV64;
rx = getDoubles lib.systems.match.isRx;
vc4 = getDoubles lib.systems.match.isVc4;
or1k = getDoubles lib.systems.match.isOr1k;
m68k = getDoubles lib.systems.match.isM68k;
s390 = getDoubles lib.systems.match.isS390;
s390x = getDoubles lib.systems.match.isS390x;
loongarch64 = getDoubles lib.systems.match.isLoongArch64;
js = getDoubles lib.systems.match.isJavaScript;
bigEndian = getDoubles lib.systems.match.isBigEndian;
littleEndian = getDoubles lib.systems.match.isLittleEndian;
cygwin = getDoubles lib.systems.match.isCygwin;
darwin = getDoubles lib.systems.match.isDarwin;
freebsd = getDoubles lib.systems.match.isFreeBSD;
# Should be better, but MinGW is unclear.
gnu =
getDoubles (
lib.attrs.match {
kernel = types.kernels.linux;
abi = types.abis.gnu;
}
)
++ getDoubles (
lib.attrs.match {
kernel = types.kernels.linux;
abi = types.abis.gnueabi;
}
)
++ getDoubles (
lib.attrs.match {
kernel = types.kernels.linux;
abi = types.abis.gnueabihf;
}
)
++ getDoubles (
lib.attrs.match {
kernel = types.kernels.linux;
abi = types.abis.gnuabin32;
}
)
++ getDoubles (
lib.attrs.match {
kernel = types.kernels.linux;
abi = types.abis.gnuabi64;
}
)
++ getDoubles (
lib.attrs.match {
kernel = types.kernels.linux;
abi = types.abis.gnuabielfv1;
}
)
++ getDoubles (
lib.attrs.match {
kernel = types.kernels.linux;
abi = types.abis.gnuabielfv2;
}
);
illumos = getDoubles lib.systems.match.isSunOS;
linux = getDoubles lib.systems.match.isLinux;
netbsd = getDoubles lib.systems.match.isNetBSD;
openbsd = getDoubles lib.systems.match.isOpenBSD;
unix = getDoubles lib.systems.match.isUnix;
wasi = getDoubles lib.systems.match.isWasi;
redox = getDoubles lib.systems.match.isRedox;
windows = getDoubles lib.systems.match.isWindows;
genode = getDoubles lib.systems.match.isGenode;
embedded = getDoubles lib.systems.match.isNone;
mesaPlatforms = [
"i686-linux"
"x86_64-linux"
"x86_64-darwin"
"armv5tel-linux"
"armv6l-linux"
"armv7l-linux"
"armv7a-linux"
"aarch64-linux"
"powerpc64-linux"
"powerpc64le-linux"
"aarch64-darwin"
"riscv64-linux"
];
};
withBuildInfo =
args:
let
settings = if builtins.isString args then { system = args; } else args;
resolved = {
system = lib.systems.from.string (if settings ? triple then settings.triple else settings.system);
inherit
(
{
linux-kernel = settings.linux-kernel or { };
gcc = settings.gcc or { };
rustc = settings.rustc or { };
}
// lib.systems.platforms.select resolved
)
linux-kernel
gcc
rustc
;
double = lib.systems.into.double resolved.system;
triple = lib.systems.into.triple resolved.system;
isExecutable =
platform:
(resolved.isAndroid == platform.isAndroid)
&& resolved.system.kernel == platform.system.kernel
&& lib.systems.validate.compatible resolved.system.cpu platform.system.cpu;
# The difference between `isStatic` and `hasSharedLibraries` is mainly the
# addition of the `staticMarker` (see make-derivation.nix). Some
# platforms, like embedded machines without a libc (e.g. arm-none-eabi)
# don't support dynamic linking, but don't get the `staticMarker`.
# `pkgsStatic` sets `isStatic=true`, so `pkgsStatic.hostPlatform` always
# has the `staticMarker`.
isStatic = resolved.isWasm || resolved.isRedox;
# It is important that hasSharedLibraries==false when the platform has no
# dynamic library loader. Various tools (including the gcc build system)
# have knowledge of which platforms are incapable of dynamic linking, and
# will still build on/for those platforms with --enable-shared, but simply
# omit any `.so` build products such as libgcc_s.so. When that happens,
# it causes hard-to-troubleshoot build failures.
hasSharedLibraries =
!resolved.isStatic
&& (
# Linux (allows multiple libcs)
resolved.isAndroid
|| resolved.isGnu
|| resolved.isMusl
# BSDs
|| resolved.isDarwin
|| resolved.isSunOS
|| resolved.isOpenBSD
|| resolved.isFreeBSD
|| resolved.isNetBSD
# Windows
|| resolved.isCygwin
|| resolved.isMinGW
);
libc =
if resolved.isDarwin then
"libSystem"
else if resolved.isMinGW then
"msvcrt"
else if resolved.isWasi then
"wasilibc"
else if resolved.isRedox then
"relibc"
else if resolved.isMusl then
"musl"
else if resolved.isUClibc then
"uclibc"
else if resolved.isAndroid then
"bionic"
else if resolved.isLinux then
"glibc"
else if resolved.isFreeBSD then
"fblibc"
else if resolved.isNetBSD then
"nblibc"
else if resolved.isAvr then
"avrlibc"
else if resolved.isGhcjs then
null
else if resolved.isNone then
"newlib"
else
"native/impure";
linker = if resolved.isDarwin then "cctools" else "bfd";
extensions =
(lib.attrs.when resolved.hasSharedLibraries {
shared =
if resolved.isDarwin then
".dylib"
else if resolved.isWindows then
".dll"
else
".so";
})
// {
static = if resolved.isWindows then ".lib" else ".a";
library = if resolved.isStatic then resolved.extensions.static else resolved.extensions.shared;
executable = if resolved.isWindows then ".exe" else "";
};
uname = {
system =
if resolved.system.kernel.name == "linux" then
"Linux"
else if resolved.system.kernel.name == "windows" then
"Windows"
else if resolved.system.kernel.name == "darwin" then
"Darwin"
else if resolved.system.kernel.name == "netbsd" then
"NetBSD"
else if resolved.system.kernel.name == "freebsd" then
"FreeBSD"
else if resolved.system.kernel.name == "openbsd" then
"OpenBSD"
else if resolved.system.kernel.name == "wasi" then
"Wasi"
else if resolved.system.kernel.name == "redox" then
"Redox"
else if resolved.system.kernel.name == "redox" then
"Genode"
else
null;
processor =
if resolved.isPower64 then
"ppc64${lib.strings.when resolved.isLittleEndian "le"}"
else if resolved.isPower then
"ppc${lib.strings.when resolved.isLittleEndian "le"}"
else if resolved.isMips64 then
"mips64"
else
resolved.system.cpu.name;
release = null;
};
useAndroidPrebuilt = false;
useiOSPrebuilt = false;
linux.arch =
if resolved.isAarch32 then
"arm"
else if resolved.isAarch64 then
"arm64"
else if resolved.isx86_32 then
"i386"
else if resolved.isx86_64 then
"x86_64"
# linux kernel does not distinguish microblaze/microblazeel
else if resolved.isMicroBlaze then
"microblaze"
else if resolved.isMips32 then
"mips"
else if resolved.isMips64 then
"mips" # linux kernel does not distinguish mips32/mips64
else if resolved.isPower then
"powerpc"
else if resolved.isRiscV then
"riscv"
else if resolved.isS390 then
"s390"
else if resolved.isLoongArch64 then
"loongarch"
else
resolved.system.cpu.name;
uboot.arch =
if resolved.isx86_32 then
"x86" # not i386
else if resolved.isMips64 then
"mips64" # uboot *does* distinguish between mips32/mips64
else
resolved.linux.arch; # other cases appear to agree with linuxArch
qemu.arch =
if resolved.isAarch32 then
"arm"
else if resolved.isS390 && !resolved.isS390x then
null
else if resolved.isx86_64 then
"x86_64"
else if resolved.isx86 then
"i386"
else if resolved.isMips64n32 then
"mipsn32${lib.strings.when resolved.isLittleEndian "el"}"
else if resolved.isMips64 then
"mips64${lib.strings.when resolved.isLittleEndian "el"}"
else
resolved.uname.processor;
efi.arch =
if resolved.isx86_32 then
"ia32"
else if resolved.isx86_64 then
"x64"
else if resolved.isAarch32 then
"arm"
else if resolved.isAarch64 then
"aa64"
else
resolved.system.cpu.name;
darwin = {
arch =
if resolved.system.cpu.name == "armv7a" then
"armv7"
else if resolved.system.cpu.name == "aarch64" then
"arm64"
else
resolved.system.cpu.name;
platform =
if resolved.isMacOS then
"macos"
else if resolved.isiOS then
"ios"
else
null;
sdk = {
version = resolved.darwinSdkVersion or (if resolved.isAarch64 then "11.0" else "10.12");
min = resolved.darwin.sdk.version;
variable =
if resolved.isMacOS then
"MACOSX_DEPLOYMENT_TARGET"
else if resolved.isiOS then
"IPHONEOS_DEPLOYMENT_TARGET"
else
null;
};
};
}
// builtins.mapAttrs (name: match: match resolved.system) lib.systems.match
// builtins.mapAttrs (
name: validate: validate (resolved.gcc.arch or "default")
) lib.systems.validate.architecture
// (builtins.removeAttrs settings [ "system" ]);
assertions = builtins.foldl' (
result: { assertion, message }: if assertion resolved then result else builtins.throw message
) true (resolved.system.abi.assertions or [ ]);
in
assert resolved.useAndroidPrebuilt -> resolved.isAndroid;
assert assertions;
# And finally, return the generated system info.
lib.types.set "systemWithBuildInfo" resolved;
};
};
}