aboutsummaryrefslogtreecommitdiff
path: root/systems
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2023-08-16 15:46:37 +0200
committerRobert Hensing <robert@roberthensing.nl>2023-08-16 15:46:37 +0200
commit63e0b5d081fed582ac6a0a66f402dc525953524b (patch)
tree1bdcd7fc8a6a40b2e805bad759b36e64e911036b /systems
GC root for fetched nixpkgs/lib content
Diffstat (limited to 'systems')
-rw-r--r--systems/architectures.nix114
-rw-r--r--systems/default.nix228
-rw-r--r--systems/doubles.nix119
-rw-r--r--systems/examples.nix335
-rw-r--r--systems/flake-systems.nix29
-rw-r--r--systems/inspect.nix117
-rw-r--r--systems/parse.nix503
-rw-r--r--systems/platforms.nix565
8 files changed, 2010 insertions, 0 deletions
diff --git a/systems/architectures.nix b/systems/architectures.nix
new file mode 100644
index 000000000..57b9184ca
--- /dev/null
+++ b/systems/architectures.nix
@@ -0,0 +1,114 @@
+{ lib }:
+
+rec {
+ # gcc.arch to its features (as in /proc/cpuinfo)
+ features = {
+ default = [ ];
+ # x86_64 Intel
+ 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" ];
+ # 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" ];
+ # 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 Intel
+ # https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
+ default = [ ];
+ westmere = [ ];
+ sandybridge = [ "westmere" ] ++ inferiors.westmere;
+ ivybridge = [ "sandybridge" ] ++ inferiors.sandybridge;
+ haswell = [ "ivybridge" ] ++ inferiors.ivybridge;
+ broadwell = [ "haswell" ] ++ inferiors.haswell;
+ skylake = [ "broadwell" ] ++ inferiors.broadwell;
+ skylake-avx512 = [ "skylake" ] ++ inferiors.skylake;
+ cannonlake = [ "skylake-avx512" ] ++ inferiors.skylake-avx512;
+ icelake-client = [ "cannonlake" ] ++ inferiors.cannonlake;
+ icelake-server = [ "icelake-client" ] ++ inferiors.icelake-client;
+ cascadelake = [ "skylake-avx512" ] ++ inferiors.cannonlake;
+ cooperlake = [ "cascadelake" ] ++ inferiors.cascadelake;
+ tigerlake = [ "icelake-server" ] ++ inferiors.icelake-server;
+
+ # 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" ] ++ inferiors.skylake;
+ znver2 = [ "znver1" ] ++ inferiors.znver1;
+ znver3 = [ "znver2" ] ++ inferiors.znver2;
+
+ # other
+ armv5te = [ ];
+ armv6 = [ ];
+ armv7-a = [ ];
+ armv8-a = [ ];
+ mips32 = [ ];
+ loongson2f = [ ];
+ };
+
+ predicates = let
+ featureSupport = feature: x: builtins.elem feature features.${x} or [];
+ in {
+ sse3Support = featureSupport "sse3";
+ ssse3Support = featureSupport "ssse3";
+ sse4_1Support = featureSupport "sse4_1";
+ sse4_2Support = featureSupport "sse4_2";
+ sse4_aSupport = featureSupport "sse4a";
+ avxSupport = featureSupport "avx";
+ avx2Support = featureSupport "avx2";
+ avx512Support = featureSupport "avx512";
+ aesSupport = featureSupport "aes";
+ fmaSupport = featureSupport "fma";
+ fma4Support = featureSupport "fma4";
+ };
+}
diff --git a/systems/default.nix b/systems/default.nix
new file mode 100644
index 000000000..f4784c61c
--- /dev/null
+++ b/systems/default.nix
@@ -0,0 +1,228 @@
+{ lib }:
+ let inherit (lib.attrsets) mapAttrs; in
+
+rec {
+ doubles = import ./doubles.nix { inherit lib; };
+ parse = import ./parse.nix { inherit lib; };
+ inspect = import ./inspect.nix { inherit lib; };
+ platforms = import ./platforms.nix { inherit lib; };
+ examples = import ./examples.nix { inherit lib; };
+ architectures = import ./architectures.nix { inherit lib; };
+
+ /* List of all Nix system doubles the nixpkgs flake will expose the package set
+ for. All systems listed here must be supported by nixpkgs as `localSystem`.
+
+ **Warning**: This attribute is considered experimental and is subject to change.
+ */
+ flakeExposed = import ./flake-systems.nix { };
+
+ # Elaborate a `localSystem` or `crossSystem` so that it contains everything
+ # necessary.
+ #
+ # `parsed` is inferred from args, both because there are two options with one
+ # clearly preferred, and to prevent cycles. A simpler fixed point where the RHS
+ # always just used `final.*` would fail on both counts.
+ elaborate = args': let
+ args = if lib.isString args' then { system = args'; }
+ else args';
+ final = {
+ # Prefer to parse `config` as it is strictly more informative.
+ 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;
+ # Determine whether we can execute binaries built for the provided platform.
+ canExecute = platform:
+ final.isAndroid == platform.isAndroid &&
+ parse.isCompatible final.parsed.cpu platform.parsed.cpu
+ && final.parsed.kernel == platform.parsed.kernel;
+ isCompatible = _: throw "2022-05-23: isCompatible has been removed in favor of canExecute, refer to the 22.11 changelog for details";
+ # Derived meta-data
+ libc =
+ /**/ if final.isDarwin then "libSystem"
+ else if final.isMinGW then "msvcrt"
+ else if final.isWasi then "wasilibc"
+ else if final.isRedox then "relibc"
+ else if final.isMusl then "musl"
+ else if final.isUClibc then "uclibc"
+ else if final.isAndroid then "bionic"
+ else if final.isLinux /* default */ then "glibc"
+ else if final.isFreeBSD then "fblibc"
+ else if final.isNetBSD then "nblibc"
+ else if final.isAvr then "avrlibc"
+ else if final.isGhcjs then null
+ else if final.isNone then "newlib"
+ # TODO(@Ericson2314) think more about other operating systems
+ else "native/impure";
+ # Choose what linker we wish to use by default. Someday we might also
+ # choose the C compiler, runtime library, C++ standard library, etc. in
+ # this way, nice and orthogonally, and deprecate `useLLVM`. But due to
+ # the monolithic GCC build we cannot actually make those choices
+ # independently, so we are just doing `linker` and keeping `useLLVM` for
+ # now.
+ linker =
+ /**/ if final.useLLVM or false then "lld"
+ else if final.isDarwin then "cctools"
+ # "bfd" and "gold" both come from GNU binutils. The existence of Gold
+ # is why we use the more obscure "bfd" and not "binutils" for this
+ # choice.
+ else "bfd";
+ extensions = rec {
+ sharedLibrary =
+ /**/ if final.isDarwin then ".dylib"
+ else if final.isWindows then ".dll"
+ else ".so";
+ staticLibrary =
+ /**/ if final.isWindows then ".lib"
+ else ".a";
+ library =
+ /**/ if final.isStatic then staticLibrary
+ else sharedLibrary;
+ executable =
+ /**/ if final.isWindows then ".exe"
+ else "";
+ };
+ # Misc boolean options
+ useAndroidPrebuilt = false;
+ useiOSPrebuilt = false;
+
+ # Output from uname
+ uname = {
+ # uname -s
+ system = {
+ linux = "Linux";
+ windows = "Windows";
+ darwin = "Darwin";
+ netbsd = "NetBSD";
+ freebsd = "FreeBSD";
+ openbsd = "OpenBSD";
+ wasi = "Wasi";
+ redox = "Redox";
+ genode = "Genode";
+ }.${final.parsed.kernel.name} or null;
+
+ # uname -m
+ processor =
+ if final.isPower64
+ then "ppc64${lib.optionalString final.isLittleEndian "le"}"
+ else if final.isPower
+ then "ppc${lib.optionalString final.isLittleEndian "le"}"
+ else if final.isMips64
+ then "mips64" # endianness is *not* included on mips64
+ else final.parsed.cpu.name;
+
+ # uname -r
+ release = null;
+ };
+ isStatic = final.isWasm || final.isRedox;
+
+ # Just a guess, based on `system`
+ inherit
+ ({
+ linux-kernel = args.linux-kernel or {};
+ gcc = args.gcc or {};
+ rustc = args.rustc or {};
+ } // platforms.select final)
+ linux-kernel gcc rustc;
+
+ linuxArch =
+ if final.isAarch32 then "arm"
+ else if final.isAarch64 then "arm64"
+ else if final.isx86_32 then "i386"
+ else if final.isx86_64 then "x86_64"
+ # linux kernel does not distinguish microblaze/microblazeel
+ else if final.isMicroBlaze then "microblaze"
+ else if final.isMips32 then "mips"
+ else if final.isMips64 then "mips" # linux kernel does not distinguish mips32/mips64
+ else if final.isPower then "powerpc"
+ else if final.isRiscV then "riscv"
+ else if final.isS390 then "s390"
+ else if final.isLoongArch64 then "loongarch"
+ else final.parsed.cpu.name;
+
+ qemuArch =
+ if final.isAarch32 then "arm"
+ else if final.isS390 && !final.isS390x then null
+ else if final.isx86_64 then "x86_64"
+ else if final.isx86 then "i386"
+ else if final.isMips64 then "mips64${lib.optionalString final.isLittleEndian "el"}"
+ else final.uname.processor;
+
+ # Name used by UEFI for architectures.
+ efiArch =
+ if final.isx86_32 then "ia32"
+ else if final.isx86_64 then "x64"
+ else if final.isAarch32 then "arm"
+ else if final.isAarch64 then "aa64"
+ else final.parsed.cpu.name;
+
+ darwinArch = {
+ armv7a = "armv7";
+ aarch64 = "arm64";
+ }.${final.parsed.cpu.name} or final.parsed.cpu.name;
+
+ darwinPlatform =
+ if final.isMacOS then "macos"
+ else if final.isiOS then "ios"
+ else null;
+ # The canonical name for this attribute is darwinSdkVersion, but some
+ # platforms define the old name "sdkVer".
+ darwinSdkVersion = final.sdkVer or (if final.isAarch64 then "11.0" else "10.12");
+ darwinMinVersion = final.darwinSdkVersion;
+ darwinMinVersionVariable =
+ if final.isMacOS then "MACOSX_DEPLOYMENT_TARGET"
+ else if final.isiOS then "IPHONEOS_DEPLOYMENT_TARGET"
+ else null;
+ } // (
+ let
+ selectEmulator = pkgs:
+ let
+ qemu-user = pkgs.qemu.override {
+ smartcardSupport = false;
+ spiceSupport = false;
+ openGLSupport = false;
+ virglSupport = false;
+ vncSupport = false;
+ gtkSupport = false;
+ sdlSupport = false;
+ pulseSupport = false;
+ smbdSupport = false;
+ seccompSupport = false;
+ enableDocs = false;
+ hostCpuTargets = [ "${final.qemuArch}-linux-user" ];
+ };
+ wine = (pkgs.winePackagesFor "wine${toString final.parsed.cpu.bits}").minimal;
+ in
+ if final.parsed.kernel.name == pkgs.stdenv.hostPlatform.parsed.kernel.name &&
+ pkgs.stdenv.hostPlatform.canExecute final
+ then "${pkgs.runtimeShell} -c '\"$@\"' --"
+ else if final.isWindows
+ then "${wine}/bin/wine${lib.optionalString (final.parsed.cpu.bits == 64) "64"}"
+ else if final.isLinux && pkgs.stdenv.hostPlatform.isLinux && final.qemuArch != null
+ then "${qemu-user}/bin/qemu-${final.qemuArch}"
+ else if final.isWasi
+ then "${pkgs.wasmtime}/bin/wasmtime"
+ else if final.isMmix
+ then "${pkgs.mmixware}/bin/mmix"
+ else null;
+ in {
+ emulatorAvailable = pkgs: (selectEmulator pkgs) != null;
+
+ emulator = pkgs:
+ if (final.emulatorAvailable pkgs)
+ then selectEmulator pkgs
+ else throw "Don't know how to run ${final.config} executables.";
+
+ }) // mapAttrs (n: v: v final.parsed) inspect.predicates
+ // mapAttrs (n: v: v final.gcc.arch or "default") architectures.predicates
+ // args;
+ in assert final.useAndroidPrebuilt -> final.isAndroid;
+ assert lib.foldl
+ (pass: { assertion, message }:
+ if assertion final
+ then pass
+ else throw message)
+ true
+ (final.parsed.abi.assertions or []);
+ final;
+}
diff --git a/systems/doubles.nix b/systems/doubles.nix
new file mode 100644
index 000000000..66bf3d872
--- /dev/null
+++ b/systems/doubles.nix
@@ -0,0 +1,119 @@
+{ lib }:
+let
+ inherit (lib) lists;
+ inherit (lib.systems) parse;
+ inherit (lib.systems.inspect) predicates;
+ inherit (lib.attrsets) matchAttrs;
+
+ 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" "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"
+ ];
+
+ allParsed = map parse.mkSystemFromString all;
+
+ filterDoubles = f: map parse.doubleFromSystem (lists.filter f allParsed);
+
+in {
+ inherit all;
+
+ none = [];
+
+ arm = filterDoubles predicates.isAarch32;
+ armv7 = filterDoubles predicates.isArmv7;
+ aarch64 = filterDoubles predicates.isAarch64;
+ x86 = filterDoubles predicates.isx86;
+ i686 = filterDoubles predicates.isi686;
+ x86_64 = filterDoubles predicates.isx86_64;
+ microblaze = filterDoubles predicates.isMicroBlaze;
+ mips = filterDoubles predicates.isMips;
+ mmix = filterDoubles predicates.isMmix;
+ power = filterDoubles predicates.isPower;
+ riscv = filterDoubles predicates.isRiscV;
+ riscv32 = filterDoubles predicates.isRiscV32;
+ riscv64 = filterDoubles predicates.isRiscV64;
+ rx = filterDoubles predicates.isRx;
+ vc4 = filterDoubles predicates.isVc4;
+ or1k = filterDoubles predicates.isOr1k;
+ m68k = filterDoubles predicates.isM68k;
+ s390 = filterDoubles predicates.isS390;
+ s390x = filterDoubles predicates.isS390x;
+ loongarch64 = filterDoubles predicates.isLoongArch64;
+ js = filterDoubles predicates.isJavaScript;
+
+ bigEndian = filterDoubles predicates.isBigEndian;
+ littleEndian = filterDoubles predicates.isLittleEndian;
+
+ cygwin = filterDoubles predicates.isCygwin;
+ darwin = filterDoubles predicates.isDarwin;
+ freebsd = filterDoubles predicates.isFreeBSD;
+ # Should be better, but MinGW is unclear.
+ gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; })
+ ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; })
+ ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; })
+ ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnuabin32; })
+ ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnuabi64; })
+ ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnuabielfv1; })
+ ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnuabielfv2; });
+ illumos = filterDoubles predicates.isSunOS;
+ linux = filterDoubles predicates.isLinux;
+ netbsd = filterDoubles predicates.isNetBSD;
+ openbsd = filterDoubles predicates.isOpenBSD;
+ unix = filterDoubles predicates.isUnix;
+ wasi = filterDoubles predicates.isWasi;
+ redox = filterDoubles predicates.isRedox;
+ windows = filterDoubles predicates.isWindows;
+ genode = filterDoubles predicates.isGenode;
+
+ embedded = filterDoubles predicates.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"];
+}
diff --git a/systems/examples.nix b/systems/examples.nix
new file mode 100644
index 000000000..45b95c150
--- /dev/null
+++ b/systems/examples.nix
@@ -0,0 +1,335 @@
+# These can be passed to nixpkgs as either the `localSystem` or
+# `crossSystem`. They are put here for user convenience, but also used by cross
+# tests and linux cross stdenv building, so handle with care!
+{ lib }:
+let
+ platforms = import ./platforms.nix { inherit lib; };
+
+ riscv = bits: {
+ config = "riscv${bits}-unknown-linux-gnu";
+ };
+in
+
+rec {
+ #
+ # Linux
+ #
+ powernv = {
+ config = "powerpc64le-unknown-linux-gnu";
+ };
+ musl-power = {
+ config = "powerpc64le-unknown-linux-musl";
+ };
+
+ ppc64 = {
+ config = "powerpc64-unknown-linux-gnuabielfv2";
+ };
+ ppc64-musl = {
+ config = "powerpc64-unknown-linux-musl";
+ gcc = { abi = "elfv2"; };
+ };
+
+ sheevaplug = {
+ config = "armv5tel-unknown-linux-gnueabi";
+ } // platforms.sheevaplug;
+
+ raspberryPi = {
+ config = "armv6l-unknown-linux-gnueabihf";
+ } // platforms.raspberrypi;
+
+ remarkable1 = {
+ config = "armv7l-unknown-linux-gnueabihf";
+ } // platforms.zero-gravitas;
+
+ remarkable2 = {
+ config = "armv7l-unknown-linux-gnueabihf";
+ } // platforms.zero-sugar;
+
+ armv7l-hf-multiplatform = {
+ config = "armv7l-unknown-linux-gnueabihf";
+ };
+
+ aarch64-multiplatform = {
+ config = "aarch64-unknown-linux-gnu";
+ };
+
+ armv7a-android-prebuilt = {
+ config = "armv7a-unknown-linux-androideabi";
+ rustc.config = "armv7-linux-androideabi";
+ sdkVer = "28";
+ ndkVer = "24";
+ useAndroidPrebuilt = true;
+ } // platforms.armv7a-android;
+
+ aarch64-android-prebuilt = {
+ config = "aarch64-unknown-linux-android";
+ rustc.config = "aarch64-linux-android";
+ sdkVer = "28";
+ ndkVer = "24";
+ useAndroidPrebuilt = true;
+ };
+
+ aarch64-android = {
+ config = "aarch64-unknown-linux-android";
+ sdkVer = "30";
+ ndkVer = "24";
+ libc = "bionic";
+ useAndroidPrebuilt = false;
+ useLLVM = true;
+ };
+
+ pogoplug4 = {
+ config = "armv5tel-unknown-linux-gnueabi";
+ } // platforms.pogoplug4;
+
+ ben-nanonote = {
+ config = "mipsel-unknown-linux-uclibc";
+ } // platforms.ben_nanonote;
+
+ fuloongminipc = {
+ config = "mipsel-unknown-linux-gnu";
+ } // platforms.fuloong2f_n32;
+
+ # can execute on 32bit chip
+ mips-linux-gnu = { config = "mips-unknown-linux-gnu"; } // platforms.gcc_mips32r2_o32;
+ mipsel-linux-gnu = { config = "mipsel-unknown-linux-gnu"; } // platforms.gcc_mips32r2_o32;
+
+ # require 64bit chip (for more registers, 64-bit floating point, 64-bit "long long") but use 32bit pointers
+ mips64-linux-gnuabin32 = { config = "mips64-unknown-linux-gnuabin32"; } // platforms.gcc_mips64r2_n32;
+ mips64el-linux-gnuabin32 = { config = "mips64el-unknown-linux-gnuabin32"; } // platforms.gcc_mips64r2_n32;
+
+ # 64bit pointers
+ mips64-linux-gnuabi64 = { config = "mips64-unknown-linux-gnuabi64"; } // platforms.gcc_mips64r2_64;
+ mips64el-linux-gnuabi64 = { config = "mips64el-unknown-linux-gnuabi64"; } // platforms.gcc_mips64r2_64;
+
+ muslpi = raspberryPi // {
+ config = "armv6l-unknown-linux-musleabihf";
+ };
+
+ aarch64-multiplatform-musl = {
+ config = "aarch64-unknown-linux-musl";
+ };
+
+ gnu64 = { config = "x86_64-unknown-linux-gnu"; };
+ gnu32 = { config = "i686-unknown-linux-gnu"; };
+
+ musl64 = { config = "x86_64-unknown-linux-musl"; };
+ musl32 = { config = "i686-unknown-linux-musl"; };
+
+ riscv64 = riscv "64";
+ riscv32 = riscv "32";
+
+ riscv64-embedded = {
+ config = "riscv64-none-elf";
+ libc = "newlib";
+ };
+
+ riscv32-embedded = {
+ config = "riscv32-none-elf";
+ libc = "newlib";
+ };
+
+ loongarch64-linux = {
+ config = "loongarch64-unknown-linux-gnu";
+ };
+
+ mmix = {
+ config = "mmix-unknown-mmixware";
+ libc = "newlib";
+ };
+
+ rx-embedded = {
+ config = "rx-none-elf";
+ libc = "newlib";
+ };
+
+ msp430 = {
+ config = "msp430-elf";
+ libc = "newlib";
+ };
+
+ avr = {
+ config = "avr";
+ };
+
+ vc4 = {
+ config = "vc4-elf";
+ libc = "newlib";
+ };
+
+ or1k = {
+ config = "or1k-elf";
+ libc = "newlib";
+ };
+
+ m68k = {
+ config = "m68k-unknown-linux-gnu";
+ };
+
+ s390 = {
+ config = "s390-unknown-linux-gnu";
+ };
+
+ s390x = {
+ config = "s390x-unknown-linux-gnu";
+ };
+
+ arm-embedded = {
+ config = "arm-none-eabi";
+ libc = "newlib";
+ };
+ armhf-embedded = {
+ config = "arm-none-eabihf";
+ libc = "newlib";
+ # GCC8+ does not build without this
+ # (https://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg552339.html):
+ gcc = {
+ arch = "armv5t";
+ fpu = "vfp";
+ };
+ };
+
+ aarch64-embedded = {
+ config = "aarch64-none-elf";
+ libc = "newlib";
+ };
+
+ aarch64be-embedded = {
+ config = "aarch64_be-none-elf";
+ libc = "newlib";
+ };
+
+ ppc-embedded = {
+ config = "powerpc-none-eabi";
+ libc = "newlib";
+ };
+
+ ppcle-embedded = {
+ config = "powerpcle-none-eabi";
+ libc = "newlib";
+ };
+
+ i686-embedded = {
+ config = "i686-elf";
+ libc = "newlib";
+ };
+
+ x86_64-embedded = {
+ config = "x86_64-elf";
+ libc = "newlib";
+ };
+
+ #
+ # Redox
+ #
+
+ x86_64-unknown-redox = {
+ config = "x86_64-unknown-redox";
+ libc = "relibc";
+ };
+
+ #
+ # Darwin
+ #
+
+ iphone64 = {
+ config = "aarch64-apple-ios";
+ # config = "aarch64-apple-darwin14";
+ sdkVer = "14.3";
+ xcodeVer = "12.3";
+ xcodePlatform = "iPhoneOS";
+ useiOSPrebuilt = true;
+ };
+
+ iphone32 = {
+ config = "armv7a-apple-ios";
+ # config = "arm-apple-darwin10";
+ sdkVer = "14.3";
+ xcodeVer = "12.3";
+ xcodePlatform = "iPhoneOS";
+ useiOSPrebuilt = true;
+ };
+
+ iphone64-simulator = {
+ config = "x86_64-apple-ios";
+ # config = "x86_64-apple-darwin14";
+ sdkVer = "14.3";
+ xcodeVer = "12.3";
+ xcodePlatform = "iPhoneSimulator";
+ darwinPlatform = "ios-simulator";
+ useiOSPrebuilt = true;
+ };
+
+ iphone32-simulator = {
+ config = "i686-apple-ios";
+ # config = "i386-apple-darwin11";
+ sdkVer = "14.3";
+ xcodeVer = "12.3";
+ xcodePlatform = "iPhoneSimulator";
+ darwinPlatform = "ios-simulator";
+ useiOSPrebuilt = true;
+ };
+
+ aarch64-darwin = {
+ config = "aarch64-apple-darwin";
+ xcodePlatform = "MacOSX";
+ platform = {};
+ };
+
+ x86_64-darwin = {
+ config = "x86_64-apple-darwin";
+ xcodePlatform = "MacOSX";
+ platform = {};
+ };
+
+ #
+ # Windows
+ #
+
+ # 32 bit mingw-w64
+ mingw32 = {
+ config = "i686-w64-mingw32";
+ libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
+ };
+
+ # 64 bit mingw-w64
+ mingwW64 = {
+ # That's the triplet they use in the mingw-w64 docs.
+ config = "x86_64-w64-mingw32";
+ libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
+ };
+
+ # BSDs
+
+ x86_64-freebsd = {
+ config = "x86_64-unknown-freebsd13";
+ useLLVM = true;
+ };
+
+ x86_64-netbsd = {
+ config = "x86_64-unknown-netbsd";
+ };
+
+ # this is broken and never worked fully
+ x86_64-netbsd-llvm = {
+ config = "x86_64-unknown-netbsd";
+ useLLVM = true;
+ };
+
+ #
+ # WASM
+ #
+
+ wasi32 = {
+ config = "wasm32-unknown-wasi";
+ useLLVM = true;
+ };
+
+ # Ghcjs
+ ghcjs = {
+ # This triple is special to GHC/Cabal/GHCJS and not recognized by autotools
+ # See: https://gitlab.haskell.org/ghc/ghc/-/commit/6636b670233522f01d002c9b97827d00289dbf5c
+ # https://github.com/ghcjs/ghcjs/issues/53
+ config = "javascript-unknown-ghcjs";
+ };
+}
diff --git a/systems/flake-systems.nix b/systems/flake-systems.nix
new file mode 100644
index 000000000..b1988c6a4
--- /dev/null
+++ b/systems/flake-systems.nix
@@ -0,0 +1,29 @@
+# See [RFC 46] for mandated platform support and ../../pkgs/stdenv for
+# implemented platform support. This list is mainly descriptive, i.e. all
+# system doubles for platforms where nixpkgs can do native compilation
+# reasonably well are included.
+#
+# [RFC 46]: https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md
+{ }:
+
+[
+ # Tier 1
+ "x86_64-linux"
+ # Tier 2
+ "aarch64-linux"
+ "x86_64-darwin"
+ # Tier 3
+ "armv6l-linux"
+ "armv7l-linux"
+ "i686-linux"
+ "mipsel-linux"
+
+ # Other platforms with sufficient support in stdenv which is not formally
+ # mandated by their platform tier.
+ "aarch64-darwin"
+ "armv5tel-linux"
+ "powerpc64le-linux"
+ "riscv64-linux"
+
+ # "x86_64-freebsd" is excluded because it is mostly broken
+]
diff --git a/systems/inspect.nix b/systems/inspect.nix
new file mode 100644
index 000000000..89e9f4231
--- /dev/null
+++ b/systems/inspect.nix
@@ -0,0 +1,117 @@
+{ lib }:
+with import ./parse.nix { inherit lib; };
+with lib.attrsets;
+with lib.lists;
+
+let abis_ = abis; in
+let abis = lib.mapAttrs (_: abi: builtins.removeAttrs abi [ "assertions" ]) abis_; in
+
+rec {
+ # these patterns are to be matched against {host,build,target}Platform.parsed
+ patterns = rec {
+ # The patterns below are lists in sum-of-products form.
+ #
+ # Each attribute is list of product conditions; non-list values are treated
+ # as a singleton list. If *any* product condition in the list matches then
+ # the predicate matches. Each product condition is tested by
+ # `lib.attrsets.matchAttrs`, which requires a match on *all* attributes of
+ # the product.
+
+ isi686 = { cpu = cpuTypes.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; }; })
+ (lib.filter (cpu: lib.hasPrefix "armv7" cpu.arch or "")
+ (lib.attrValues cpuTypes));
+ 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 = cpuTypes.javascript; };
+
+ is32bit = { cpu = { bits = 32; }; };
+ is64bit = { cpu = { bits = 64; }; };
+ isILP32 = map (a: { abi = { abi = a; }; }) [ "n32" "ilp32" "x32" ];
+ isBigEndian = { cpu = { significantByte = significantBytes.bigEndian; }; };
+ isLittleEndian = { cpu = { significantByte = significantBytes.littleEndian; }; };
+
+ isBSD = { kernel = { families = { inherit (kernelFamilies) bsd; }; }; };
+ isDarwin = { kernel = { families = { inherit (kernelFamilies) darwin; }; }; };
+ isUnix = [ isBSD isDarwin isLinux isSunOS isCygwin isRedox ];
+
+ isMacOS = { kernel = kernels.macos; };
+ isiOS = { kernel = kernels.ios; };
+ isLinux = { kernel = kernels.linux; };
+ isSunOS = { kernel = kernels.solaris; };
+ isFreeBSD = { kernel = { name = "freebsd"; }; };
+ isNetBSD = { kernel = kernels.netbsd; };
+ isOpenBSD = { kernel = kernels.openbsd; };
+ isWindows = { kernel = kernels.windows; };
+ isCygwin = { kernel = kernels.windows; abi = abis.cygnus; };
+ isMinGW = { kernel = kernels.windows; abi = abis.gnu; };
+ isWasi = { kernel = kernels.wasi; };
+ isRedox = { kernel = kernels.redox; };
+ isGhcjs = { kernel = kernels.ghcjs; };
+ isGenode = { kernel = kernels.genode; };
+ isNone = { kernel = kernels.none; };
+
+ isAndroid = [ { abi = abis.android; } { abi = abis.androideabi; } ];
+ isGnu = with abis; map (a: { abi = a; }) [ gnuabi64 gnu gnueabi gnueabihf gnuabielfv1 gnuabielfv2 ];
+ isMusl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf muslabin32 muslabi64 ];
+ isUClibc = with abis; map (a: { abi = a; }) [ uclibc uclibceabi uclibceabihf ];
+
+ isEfi = [
+ { cpu = { family = "arm"; version = "6"; }; }
+ { cpu = { family = "arm"; version = "7"; }; }
+ { cpu = { family = "arm"; version = "8"; }; }
+ { cpu = { family = "riscv"; }; }
+ { cpu = { family = "x86"; }; }
+ ];
+ };
+
+ matchAnyAttrs = patterns:
+ if builtins.isList patterns then attrs: any (pattern: matchAttrs pattern attrs) patterns
+ else matchAttrs patterns;
+
+ predicates = mapAttrs (_: matchAnyAttrs) patterns;
+
+ # these patterns are to be matched against the entire
+ # {host,build,target}Platform structure; they include a `parsed={}` marker so
+ # that `lib.meta.availableOn` can distinguish them from the patterns which
+ # apply only to the `parsed` field.
+
+ platformPatterns = mapAttrs (_: p: { parsed = {}; } // p) {
+ isStatic = { isStatic = true; };
+ };
+}
diff --git a/systems/parse.nix b/systems/parse.nix
new file mode 100644
index 000000000..6eb4f27cc
--- /dev/null
+++ b/systems/parse.nix
@@ -0,0 +1,503 @@
+# 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.
+#
+# 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.
+#
+{ lib }:
+with lib.lists;
+with lib.types;
+with lib.attrsets;
+with lib.strings;
+with (import ./inspect.nix { inherit lib; }).predicates;
+
+let
+ inherit (lib.options) mergeOneOption;
+
+ setTypes = type:
+ mapAttrs (name: value:
+ assert type.check value;
+ setType type.name ({ inherit name; } // value));
+
+in
+
+rec {
+
+ ################################################################################
+
+ types.openSignificantByte = mkOptionType {
+ name = "significant-byte";
+ description = "Endianness";
+ merge = mergeOneOption;
+ };
+
+ types.significantByte = enum (attrValues significantBytes);
+
+ significantBytes = setTypes types.openSignificantByte {
+ bigEndian = {};
+ littleEndian = {};
+ };
+
+ ################################################################################
+
+ # 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 {
+ arm = { bits = 32; significantByte = littleEndian; family = "arm"; };
+ 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"; };
+
+ microblaze = { bits = 32; significantByte = bigEndian; family = "microblaze"; };
+ microblazeel = { bits = 32; significantByte = littleEndian; family = "microblaze"; };
+
+ 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"; };
+
+ mmix = { bits = 64; significantByte = bigEndian; family = "mmix"; };
+
+ m68k = { bits = 32; significantByte = bigEndian; family = "m68k"; };
+
+ powerpc = { bits = 32; significantByte = bigEndian; family = "power"; };
+ powerpc64 = { bits = 64; significantByte = bigEndian; family = "power"; };
+ powerpc64le = { bits = 64; significantByte = littleEndian; family = "power"; };
+ powerpcle = { bits = 32; significantByte = littleEndian; family = "power"; };
+
+ riscv32 = { bits = 32; significantByte = littleEndian; family = "riscv"; };
+ riscv64 = { bits = 64; significantByte = littleEndian; family = "riscv"; };
+
+ s390 = { bits = 32; significantByte = bigEndian; family = "s390"; };
+ s390x = { bits = 64; significantByte = bigEndian; family = "s390"; };
+
+ sparc = { bits = 32; significantByte = bigEndian; family = "sparc"; };
+ sparc64 = { bits = 64; significantByte = bigEndian; family = "sparc"; };
+
+ wasm32 = { bits = 32; significantByte = littleEndian; family = "wasm"; };
+ wasm64 = { bits = 64; significantByte = littleEndian; family = "wasm"; };
+
+ alpha = { bits = 64; significantByte = littleEndian; family = "alpha"; };
+
+ rx = { bits = 32; significantByte = littleEndian; family = "rx"; };
+ msp430 = { bits = 16; significantByte = littleEndian; family = "msp430"; };
+ avr = { bits = 8; family = "avr"; };
+
+ vc4 = { bits = 32; significantByte = littleEndian; family = "vc4"; };
+
+ or1k = { bits = 32; significantByte = bigEndian; family = "or1k"; };
+
+ loongarch64 = { bits = 64; significantByte = littleEndian; family = "loongarch"; };
+
+ javascript = { bits = 32; significantByte = littleEndian; family = "javascript"; };
+ };
+
+ # GNU build systems assume that older NetBSD architectures are using a.out.
+ gnuNetBSDDefaultExecFormat = cpu:
+ 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 execFormats.aout
+ else execFormats.elf;
+
+ # 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.
+ #
+ # 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.
+ 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)
+
+ # XXX: Not true in some cases. Like in WSL mode.
+ (b == i686 && isCompatible a x86_64)
+
+ # ARMv4
+ (b == arm && isCompatible a armv5tel)
+
+ # 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)
+ (b == armv8r && isCompatible a armv8a)
+ (b == armv8m && isCompatible a armv8a)
+
+ # PowerPC
+ (b == powerpc && isCompatible a powerpc64)
+ (b == powerpcle && isCompatible a powerpc64le)
+
+ # MIPS
+ (b == mips && isCompatible a mips64)
+ (b == mipsel && isCompatible a mips64el)
+
+ # RISCV
+ (b == riscv32 && isCompatible a riscv64)
+
+ # SPARC
+ (b == sparc && isCompatible a sparc64)
+
+ # WASM
+ (b == wasm32 && isCompatible a wasm64)
+
+ # identity
+ (b == a)
+ ];
+
+ ################################################################################
+
+ types.openVendor = mkOptionType {
+ name = "vendor";
+ description = "vendor for the platform";
+ merge = mergeOneOption;
+ };
+
+ types.vendor = enum (attrValues vendors);
+
+ vendors = setTypes types.openVendor {
+ apple = {};
+ pc = {};
+ # 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 = {};
+ };
+
+ ################################################################################
+
+ types.openExecFormat = mkOptionType {
+ name = "exec-format";
+ description = "executable container used by the kernel";
+ merge = mergeOneOption;
+ };
+
+ types.execFormat = enum (attrValues execFormats);
+
+ execFormats = setTypes types.openExecFormat {
+ aout = {}; # a.out
+ elf = {};
+ macho = {};
+ pe = {};
+ wasm = {};
+
+ unknown = {};
+ };
+
+ ################################################################################
+
+ types.openKernelFamily = mkOptionType {
+ name = "exec-format";
+ description = "executable container used by the kernel";
+ merge = mergeOneOption;
+ };
+
+ types.kernelFamily = enum (attrValues kernelFamilies);
+
+ kernelFamilies = setTypes types.openKernelFamily {
+ bsd = {};
+ darwin = {};
+ };
+
+ ################################################################################
+
+ 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 {
+ # TODO(@Ericson2314): Don't want to mass-rebuild yet to keeping 'darwin' as
+ # the normalized name for macOS.
+ macos = { execFormat = macho; families = { inherit darwin; }; name = "darwin"; };
+ ios = { execFormat = macho; families = { inherit 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 = { execFormat = elf; families = { inherit bsd; }; name = "freebsd"; version = 12; };
+ freebsd13 = { execFormat = elf; families = { inherit bsd; }; name = "freebsd"; version = 13; };
+ 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 = { }; };
+ } // { # aliases
+ # 'darwin' is the kernel for all of them. We choose macOS by default.
+ darwin = kernels.macos;
+ watchos = kernels.ios;
+ tvos = kernels.ios;
+ win32 = kernels.windows;
+ };
+
+ ################################################################################
+
+ types.openAbi = mkOptionType {
+ name = "abi";
+ description = "binary interface for compiled code and syscalls";
+ merge = mergeOneOption;
+ };
+
+ types.abi = enum (attrValues abis);
+
+ abis = setTypes types.openAbi {
+ 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 = {};
+ };
+
+ ################################################################################
+
+ types.parsedPlatform = mkOptionType {
+ 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;
+ };
+
+ isSystem = isType "system";
+
+ mkSystem = components:
+ assert types.parsedPlatform.check components;
+ 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"; }
+ else if (elemAt l 1) == "elf"
+ then { cpu = elemAt l 0; vendor = "unknown"; kernel = "none"; abi = elemAt l 1; }
+ else { cpu = elemAt l 0; kernel = elemAt l 1; };
+ "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;
+ }
+ else throw "Target specification with 3 components is ambiguous";
+ "4" = { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; abi = elemAt l 3; };
+ }.${toString (length l)}
+ or (throw "system string has invalid number of hyphen-separated components");
+
+ # 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
+ , kernel
+ , # Also inferred below
+ abi ? assert false; null
+ } @ args: let
+ 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}");
+
+ 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;
+ 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 abis.gnu
+ else abis.unknown;
+ };
+
+ in mkSystem parsed;
+
+ mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s));
+
+ kernelName = kernel:
+ kernel.name + toString (kernel.version or "");
+
+ doubleFromSystem = { cpu, kernel, abi, ... }:
+ /**/ if abi == abis.cygnus then "${cpu.name}-cygwin"
+ else if kernel.families ? darwin then "${cpu.name}-darwin"
+ else "${cpu.name}-${kernelName kernel}";
+
+ 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}";
+
+ ################################################################################
+
+}
diff --git a/systems/platforms.nix b/systems/platforms.nix
new file mode 100644
index 000000000..d574943e4
--- /dev/null
+++ b/systems/platforms.nix
@@ -0,0 +1,565 @@
+# Note: lib/systems/default.nix takes care of producing valid,
+# fully-formed "platform" values (e.g. hostPlatform, buildPlatform,
+# targetPlatform, etc) containing at least the minimal set of attrs
+# required (see types.parsedPlatform in lib/systems/parse.nix). This
+# file takes an already-valid platform and further elaborates it with
+# optional fields; currently these are: linux-kernel, gcc, and rustc.
+
+{ lib }:
+rec {
+ 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.recursiveUpdate 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 = armv7l-hf-multiplatform;
+
+ 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 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 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
+ '';
+ };
+ };
+
+ # 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 pc
+
+ # ARM
+ else if platform.isAarch32 then let
+ version = platform.parsed.cpu.version or null;
+ in if version == null then pc
+ else if lib.versionOlder version "6" then sheevaplug
+ else if lib.versionOlder version "7" then raspberrypi
+ else armv7l-hf-multiplatform
+
+ else if platform.isAarch64 then
+ if platform.isDarwin then apple-m1
+ else aarch64-multiplatform
+
+ else if platform.isRiscV then riscv-multiplatform
+
+ else if platform.parsed.cpu == lib.systems.parse.cpuTypes.mipsel then (import ./examples.nix { inherit lib; }).mipsel-linux-gnu
+
+ else if platform.parsed.cpu == lib.systems.parse.cpuTypes.powerpc64le then powernv
+
+ else { };
+}