about summary refs log tree commit diff
path: root/lib/systems
diff options
context:
space:
mode:
authorJohn Ericson <git@JohnEricson.me>2019-09-02 01:31:31 -0400
committerJohn Ericson <git@JohnEricson.me>2019-09-02 01:31:31 -0400
commitc33d80c071927d783bd10943e723ed408ec89e48 (patch)
treeee0d82edaae37f797995468b8dbd5ce4beffab27 /lib/systems
parent446f8c851d599326373a2c910841d092ff8e68ae (diff)
parent74b42e28b94cc42f93b50c5aeee8794f66795fd0 (diff)
Merge remote-tracking branch 'upstream/master' into feature/js-unknown-ghcjs
Diffstat (limited to 'lib/systems')
-rw-r--r--lib/systems/default.nix31
-rw-r--r--lib/systems/doubles.nix18
-rw-r--r--lib/systems/examples.nix49
-rw-r--r--lib/systems/for-meta.nix37
-rw-r--r--lib/systems/inspect.nix4
-rw-r--r--lib/systems/parse.nix123
-rw-r--r--lib/systems/platforms.nix11
7 files changed, 182 insertions, 91 deletions
diff --git a/lib/systems/default.nix b/lib/systems/default.nix
index 77f200952958b..8aa413f53817b 100644
--- a/lib/systems/default.nix
+++ b/lib/systems/default.nix
@@ -3,7 +3,6 @@
 
 rec {
   doubles = import ./doubles.nix { inherit lib; };
-  forMeta = import ./for-meta.nix { inherit lib; };
   parse = import ./parse.nix { inherit lib; };
   inspect = import ./inspect.nix { inherit lib; };
   platforms = import ./platforms.nix { inherit lib; };
@@ -15,7 +14,9 @@ rec {
   # `parsed` is inferred from args, both because there are two options with one
   # clearly prefered, and to prevent cycles. A simpler fixed point where the RHS
   # always just used `final.*` would fail on both counts.
-  elaborate = args: let
+  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);
@@ -24,15 +25,20 @@ rec {
       config = parse.tripleFromSystem final.parsed;
       # Just a guess, based on `system`
       platform = platforms.selectBySystem final.system;
+      # Determine whether we are compatible with the provided CPU
+      isCompatible = platform: parse.isCompatible final.parsed.cpu platform.parsed.cpu;
       # Derived meta-data
       libc =
         /**/ if final.isDarwin              then "libSystem"
         else if final.isMinGW               then "msvcrt"
+        else if final.isWasi                then "wasilibc"
         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.isMsp430              then "newlib"
         else if final.isAvr                 then "avrlibc"
+        else if final.isNetBSD              then "nblibc"
         # TODO(@Ericson2314) think more about other operating systems
         else                                     "native/impure";
       extensions = {
@@ -58,7 +64,7 @@ rec {
           "netbsd" = "NetBSD";
           "freebsd" = "FreeBSD";
           "openbsd" = "OpenBSD";
-          "wasm" = "Wasm";
+          "wasi" = "Wasi";
         }.${final.parsed.kernel.name} or null;
 
          # uname -p
@@ -68,16 +74,22 @@ rec {
          release = null;
       };
 
+      kernelArch =
+        if final.isAarch32 then "arm"
+        else if final.isAarch64 then "arm64"
+        else if final.isx86_32 then "x86"
+        else if final.isx86_64 then "ia64"
+        else final.parsed.cpu.name;
+
       qemuArch =
         if final.isArm then "arm"
         else if final.isx86_64 then "x86_64"
         else if final.isx86 then "i386"
         else {
           "powerpc" = "ppc";
+          "powerpcle" = "ppc";
           "powerpc64" = "ppc64";
-          "powerpc64le" = "ppc64";
-          "mips64" = "mips";
-          "mipsel64" = "mipsel";
+          "powerpc64le" = "ppc64le";
         }.${final.parsed.cpu.name} or final.parsed.cpu.name;
 
       emulator = pkgs: let
@@ -98,13 +110,14 @@ rec {
         wine = (pkgs.winePackagesFor wine-name).minimal;
       in
         if final.parsed.kernel.name == pkgs.stdenv.hostPlatform.parsed.kernel.name &&
-           (final.parsed.cpu.name == pkgs.stdenv.hostPlatform.parsed.cpu.name ||
-            (final.isi686 && pkgs.stdenv.hostPlatform.isx86_64))
-        then pkgs.runtimeShell
+           pkgs.stdenv.hostPlatform.isCompatible final
+        then "${pkgs.runtimeShell} -c '\"$@\"' --"
         else if final.isWindows
         then "${wine}/bin/${wine-name}"
         else if final.isLinux && pkgs.stdenv.hostPlatform.isLinux
         then "${qemu-user}/bin/qemu-${final.qemuArch}"
+        else if final.isWasi
+        then "${pkgs.wasmtime}/bin/wasmtime"
         else throw "Don't know how to run ${final.config} executables.";
 
     } // mapAttrs (n: v: v final.parsed) inspect.predicates
diff --git a/lib/systems/doubles.nix b/lib/systems/doubles.nix
index 58677c0bdd900..823f6a915d6e7 100644
--- a/lib/systems/doubles.nix
+++ b/lib/systems/doubles.nix
@@ -13,10 +13,20 @@ let
 
     "i686-cygwin" "i686-freebsd" "i686-linux" "i686-netbsd" "i686-openbsd"
 
-    "x86_64-cygwin" "x86_64-darwin" "x86_64-freebsd" "x86_64-linux"
+    "x86_64-cygwin" "x86_64-freebsd" "x86_64-linux"
     "x86_64-netbsd" "x86_64-openbsd" "x86_64-solaris"
 
+    "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin"
+
     "x86_64-windows" "i686-windows"
+
+    "wasm64-wasi" "wasm32-wasi"
+
+    "powerpc64le-linux"
+
+    "riscv32-linux" "riscv64-linux"
+
+    "aarch64-none" "avr-none" "arm-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none" "riscv64-none" "riscv32-none"
   ];
 
   allParsed = map parse.mkSystemFromString all;
@@ -34,6 +44,7 @@ in rec {
   i686    = filterDoubles predicates.isi686;
   x86_64  = filterDoubles predicates.isx86_64;
   mips    = filterDoubles predicates.isMips;
+  riscv   = filterDoubles predicates.isRiscV;
 
   cygwin  = filterDoubles predicates.isCygwin;
   darwin  = filterDoubles predicates.isDarwin;
@@ -45,7 +56,10 @@ in rec {
   netbsd  = filterDoubles predicates.isNetBSD;
   openbsd = filterDoubles predicates.isOpenBSD;
   unix    = filterDoubles predicates.isUnix;
+  wasi    = filterDoubles predicates.isWasi;
   windows = filterDoubles predicates.isWindows;
 
-  mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux" "powerpc64le-linux"];
+  embedded = filterDoubles predicates.isNone;
+
+  mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "armv7a-linux" "aarch64-linux" "powerpc64le-linux"];
 }
diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix
index 90068f566ed08..4861fe634a02e 100644
--- a/lib/systems/examples.nix
+++ b/lib/systems/examples.nix
@@ -44,14 +44,6 @@ rec {
     platform = platforms.aarch64-multiplatform;
   };
 
-  armv5te-android-prebuilt = rec {
-    config = "armv5tel-unknown-linux-androideabi";
-    sdkVer = "21";
-    ndkVer = "18b";
-    platform = platforms.armv5te-android;
-    useAndroidPrebuilt = true;
-  };
-
   armv7a-android-prebuilt = rec {
     config = "armv7a-unknown-linux-androideabi";
     sdkVer = "24";
@@ -96,12 +88,32 @@ rec {
     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";
+    platform = platforms.riscv-multiplatform "64";
+  };
+
+  riscv32-embedded = {
+    config = "riscv32-none-elf";
+    libc = "newlib";
+    platform = platforms.riscv-multiplatform "32";
+  };
+
+  msp430 = {
+    config = "msp430-elf";
+    libc = "newlib";
+  };
+
   avr = {
     config = "avr";
   };
@@ -135,11 +147,6 @@ rec {
     libc = "newlib";
   };
 
-  alpha-embedded = {
-    config = "alpha-elf";
-    libc = "newlib";
-  };
-
   i686-embedded = {
     config = "i686-elf";
     libc = "newlib";
@@ -213,6 +220,22 @@ rec {
     platform = {};
   };
 
+  # BSDs
+
+  amd64-netbsd = {
+    config = "x86_64-unknown-netbsd";
+    libc = "nblibc";
+  };
+
+  #
+  # WASM
+  #
+
+  wasi32 = {
+    config = "wasm32-unknown-wasi";
+    useLLVM = true;
+  };
+
   # Ghcjs
   ghcjs = {
     config = "js-unknown-ghcjs";
diff --git a/lib/systems/for-meta.nix b/lib/systems/for-meta.nix
deleted file mode 100644
index 51fb6ae760d1e..0000000000000
--- a/lib/systems/for-meta.nix
+++ /dev/null
@@ -1,37 +0,0 @@
-{ lib }:
-let
-  inherit (lib.systems) parse;
-  inherit (lib.systems.inspect) patterns;
-
-  abis = lib.mapAttrs (_: abi: builtins.removeAttrs abi [ "assertions" ]) parse.abis;
-
-in rec {
-  all     = [ {} ]; # `{}` matches anything
-  none    = [];
-
-  arm     = [ patterns.isAarch32 ];
-  aarch64 = [ patterns.isAarch64 ];
-  x86     = [ patterns.isx86 ];
-  i686    = [ patterns.isi686 ];
-  x86_64  = [ patterns.isx86_64 ];
-  mips    = [ patterns.isMips ];
-  riscv   = [ patterns.isRiscV ];
-
-  cygwin  = [ patterns.isCygwin ];
-  darwin  = [ patterns.isDarwin ];
-  freebsd = [ patterns.isFreeBSD ];
-  # Should be better, but MinGW is unclear.
-  gnu     = [
-    { kernel = parse.kernels.linux; abi = abis.gnu; }
-    { kernel = parse.kernels.linux; abi = abis.gnueabi; }
-    { kernel = parse.kernels.linux; abi = abis.gnueabihf; }
-  ];
-  illumos = [ patterns.isSunOS ];
-  linux   = [ patterns.isLinux ];
-  netbsd  = [ patterns.isNetBSD ];
-  openbsd = [ patterns.isOpenBSD ];
-  unix    = patterns.isUnix; # Actually a list
-  windows = [ patterns.isWindows ];
-
-  inherit (lib.systems.doubles) mesaPlatforms;
-}
diff --git a/lib/systems/inspect.nix b/lib/systems/inspect.nix
index bf186126d4a9b..8a95787110b82 100644
--- a/lib/systems/inspect.nix
+++ b/lib/systems/inspect.nix
@@ -20,7 +20,9 @@ rec {
     isRiscV        = { cpu = { family = "riscv"; }; };
     isSparc        = { cpu = { family = "sparc"; }; };
     isWasm         = { cpu = { family = "wasm"; }; };
+    isMsp430       = { cpu = { family = "msp430"; }; };
     isAvr          = { cpu = { family = "avr"; }; };
+    isAlpha        = { cpu = { family = "alpha"; }; };
 
     is32bit        = { cpu = { bits = 32; }; };
     is64bit        = { cpu = { bits = 64; }; };
@@ -41,6 +43,8 @@ rec {
     isWindows      = { kernel = kernels.windows; };
     isCygwin       = { kernel = kernels.windows; abi = abis.cygnus; };
     isMinGW        = { kernel = kernels.windows; abi = abis.gnu; };
+    isWasi         = { kernel = kernels.wasi; };
+    isNone         = { kernel = kernels.none; };
 
     isAndroid      = [ { abi = abis.android; } { abi = abis.androideabi; } ];
     isMusl         = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ];
diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix
index a20b334311efa..0c42689a9b137 100644
--- a/lib/systems/parse.nix
+++ b/lib/systems/parse.nix
@@ -69,24 +69,24 @@ rec {
 
   cpuTypes = with significantBytes; setTypes types.openCpuType {
     arm      = { bits = 32; significantByte = littleEndian; family = "arm"; };
-    armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; version = "5"; };
-    armv6m   = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; };
-    armv6l   = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; };
-    armv7a   = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; };
-    armv7r   = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; };
-    armv7m   = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; };
-    armv7l   = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; };
-    armv8a   = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; };
-    armv8r   = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; };
-    armv8m   = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; };
-    aarch64  = { bits = 64; significantByte = littleEndian; family = "arm"; version = "8"; };
-    aarch64_be = { bits = 64; significantByte = bigEndian; family = "arm"; version = "8"; };
-
-    i386     = { bits = 32; significantByte = littleEndian; family = "x86"; };
-    i486     = { bits = 32; significantByte = littleEndian; family = "x86"; };
-    i586     = { bits = 32; significantByte = littleEndian; family = "x86"; };
-    i686     = { bits = 32; significantByte = littleEndian; family = "x86"; };
-    x86_64   = { bits = 64; significantByte = littleEndian; family = "x86"; };
+    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"; };
 
     mips     = { bits = 32; significantByte = bigEndian;    family = "mips"; };
     mipsel   = { bits = 32; significantByte = littleEndian; family = "mips"; };
@@ -109,11 +109,92 @@ rec {
 
     alpha    = { bits = 64; significantByte = littleEndian; family = "alpha"; };
 
+    msp430   = { bits = 16; significantByte = littleEndian; family = "msp430"; };
     avr      = { bits = 8; family = "avr"; };
 
     js       = { bits = 32; significantByte = littleEndian; family = "js"; };
   };
 
+  # Determine where two CPUs are compatible with each other. That is,
+  # can we run code built for system b on system a? For that to
+  # happen, then the set of all possible possible programs that system
+  # b accepts must be a subset of the set of all programs that system
+  # a accepts. This compatibility relation forms a category where each
+  # CPU is an object and each arrow from a to b represents
+  # compatibility. CPUs with multiple modes of Endianness are
+  # isomorphic while all CPUs are endomorphic because any program
+  # built for a CPU can run on that CPU.
+  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)
+    (b == armv7a && isCompatible a armv8a)
+    (b == armv7r && isCompatible a armv8a)
+    (b == armv7m && isCompatible a armv8a)
+    (b == armv7a && isCompatible a armv8r)
+    (b == armv7r && isCompatible a armv8r)
+    (b == armv7m && isCompatible a armv8r)
+    (b == armv7a && isCompatible a armv8m)
+    (b == armv7r && isCompatible a armv8m)
+    (b == armv7m && isCompatible a armv8m)
+
+    # ARMv8
+    (b == armv8r && isCompatible a armv8a)
+    (b == armv8m && isCompatible a armv8a)
+
+    # XXX: not always true! Some arm64 cpus don’t support arm32 mode.
+    (b == aarch64 && a == armv8a)
+    (b == armv8a && isCompatible a aarch64)
+
+    (b == aarch64 && a == aarch64_be)
+    (b == aarch64_be && isCompatible a aarch64)
+
+    # PowerPC
+    (b == powerpc && isCompatible a powerpc64)
+    (b == powerpcle && isCompatible a powerpc)
+    (b == powerpc && a == powerpcle)
+    (b == powerpc64le && isCompatible a powerpc64)
+    (b == powerpc64 && a == powerpc64le)
+
+    # MIPS
+    (b == mips && isCompatible a mips64)
+    (b == mips && a == mipsel)
+    (b == mipsel && isCompatible a mips)
+    (b == mips64 && a == mips64el)
+    (b == mips64el && isCompatible a mips64)
+
+    # RISCV
+    (b == riscv32 && isCompatible a riscv64)
+
+    # SPARC
+    (b == sparc && isCompatible a sparc64)
+
+    # WASM
+    (b == wasm32 && isCompatible a wasm64)
+
+    # identity
+    (b == a)
+  ];
+
   ################################################################################
 
   types.openVendor = mkOptionType {
@@ -147,6 +228,7 @@ rec {
     elf = {};
     macho = {};
     pe = {};
+    wasm = {};
 
     unknown = {};
   };
@@ -189,6 +271,7 @@ rec {
     none    = { execFormat = unknown; families = { }; };
     openbsd = { execFormat = elf;     families = { inherit bsd; }; };
     solaris = { execFormat = elf;     families = { }; };
+    wasi    = { execFormat = wasm;    families = { }; };
     windows = { execFormat = pe;      families = { }; };
     ghcjs   = { execFormat = unknown; families = { }; };
   } // { # aliases
@@ -298,6 +381,8 @@ rec {
         then { cpu = elemAt l 0;                      kernel = elemAt l 1; abi = elemAt l 2; }
       else if (elemAt l 2 == "mingw32") # autotools breaks on -gnu for window
         then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "windows";                    }
+      else if (elemAt l 2 == "wasi")
+        then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "wasi";                       }
       else if hasPrefix "netbsd" (elemAt l 2)
         then { cpu = elemAt l 0; vendor = elemAt l 1;    kernel = elemAt l 2;                }
       else if (elem (elemAt l 2) ["eabi" "eabihf" "elf"])
@@ -348,7 +433,7 @@ rec {
 
   mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s));
 
-  doubleFromSystem = { cpu, vendor, kernel, abi, ... }:
+  doubleFromSystem = { cpu, kernel, abi, ... }:
     /**/ if abi == abis.cygnus       then "${cpu.name}-cygwin"
     else if kernel.families ? darwin then "${cpu.name}-darwin"
     else "${cpu.name}-${kernel.name}";
diff --git a/lib/systems/platforms.nix b/lib/systems/platforms.nix
index 03bfce256103c..a2b43c970a411 100644
--- a/lib/systems/platforms.nix
+++ b/lib/systems/platforms.nix
@@ -253,22 +253,11 @@ rec {
     kernelTarget = "zImage";
   };
 
-  # https://developer.android.com/ndk/guides/abis#armeabi
-  armv5te-android = {
-    name = "armeabi";
-    gcc = {
-      arch = "armv5te";
-      float = "soft";
-      float-abi = "soft";
-    };
-  };
-
   # https://developer.android.com/ndk/guides/abis#v7a
   armv7a-android =  {
     name = "armeabi-v7a";
     gcc = {
       arch = "armv7-a";
-      float = "hard";
       float-abi = "softfp";
       fpu = "vfpv3-d16";
     };