about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/attrsets.nix13
-rw-r--r--lib/default.nix9
-rw-r--r--lib/platforms.nix24
-rw-r--r--lib/systems.nix126
-rw-r--r--lib/systems/default.nix23
-rw-r--r--lib/systems/doubles.nix44
-rw-r--r--lib/systems/parse.nix173
-rw-r--r--lib/systems/platforms.nix486
-rw-r--r--lib/tests/release.nix57
-rw-r--r--lib/tests/systems.nix31
10 files changed, 800 insertions, 186 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index f9e6b7495fc5..c686e1d20eb8 100644
--- a/lib/attrsets.nix
+++ b/lib/attrsets.nix
@@ -2,7 +2,7 @@
 
 let
   inherit (builtins) head tail length;
-  inherit (import ./trivial.nix) or;
+  inherit (import ./trivial.nix) and or;
   inherit (import ./default.nix) fold;
   inherit (import ./strings.nix) concatStringsSep;
   inherit (import ./lists.nix) concatMap concatLists all deepSeqList;
@@ -417,18 +417,15 @@ rec {
 
   /* Returns true if the pattern is contained in the set. False otherwise.
 
-     FIXME(zimbatm): this example doesn't work !!!
-
      Example:
-       sys = mkSystem { }
-       matchAttrs { cpu = { bits = 64; }; } sys
+       matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
        => true
    */
-  matchAttrs = pattern: attrs:
-    fold or false (attrValues (zipAttrsWithNames (attrNames pattern) (n: values:
+  matchAttrs = pattern: attrs: assert isAttrs pattern;
+    fold and true (attrValues (zipAttrsWithNames (attrNames pattern) (n: values:
       let pat = head values; val = head (tail values); in
       if length values == 1 then false
-      else if isAttrs pat then isAttrs val && matchAttrs head values
+      else if isAttrs pat then isAttrs val && matchAttrs pat val
       else pat == val
     ) [pattern attrs]));
 
diff --git a/lib/default.nix b/lib/default.nix
index 632b12510e82..e692637abf19 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -27,8 +27,7 @@ let
 
   # constants
   licenses = import ./licenses.nix;
-  platforms = import ./platforms.nix;
-  systems = import ./systems.nix;
+  systems = import ./systems;
 
   # misc
   debug = import ./debug.nix;
@@ -47,13 +46,15 @@ in
             attrsets lists strings stringsWithDeps
             customisation maintainers meta sources
             modules options types
-            licenses platforms systems
+            licenses systems
             debug generators misc
             sandbox fetchers filesystem;
+
+    # back-compat aliases
+    platforms = systems.doubles;
   }
   # !!! don't include everything at top-level; perhaps only the most
   # commonly used functions.
   // trivial // lists // strings // stringsWithDeps // attrsets // sources
   // options // types // meta // debug // misc // modules
-  // systems
   // customisation
diff --git a/lib/platforms.nix b/lib/platforms.nix
deleted file mode 100644
index 6b56e1734ad6..000000000000
--- a/lib/platforms.nix
+++ /dev/null
@@ -1,24 +0,0 @@
-let lists = import ./lists.nix; in
-
-rec {
-  all = linux ++ darwin ++ cygwin ++ freebsd ++ openbsd ++ netbsd ++ illumos;
-  allBut = platforms: lists.filter (x: !(builtins.elem x platforms)) all;
-  none = [];
-
-  arm = ["armv5tel-linux" "armv6l-linux" "armv7l-linux" ];
-  i686 = ["i686-linux" "i686-freebsd" "i686-netbsd" "i686-cygwin"];
-  mips = [ "mips64el-linux" ];
-  x86_64 = ["x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin"];
-
-  cygwin = ["i686-cygwin" "x86_64-cygwin"];
-  darwin = ["x86_64-darwin"];
-  freebsd = ["i686-freebsd" "x86_64-freebsd"];
-  gnu = linux; /* ++ hurd ++ kfreebsd ++ ... */
-  illumos = ["x86_64-solaris"];
-  linux = ["i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux" "mips64el-linux"];
-  netbsd = ["i686-netbsd" "x86_64-netbsd"];
-  openbsd = ["i686-openbsd" "x86_64-openbsd"];
-  unix = linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos;
-
-  mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux"];
-}
diff --git a/lib/systems.nix b/lib/systems.nix
deleted file mode 100644
index 92d8bdf892b4..000000000000
--- a/lib/systems.nix
+++ /dev/null
@@ -1,126 +0,0 @@
-# Define the list of system with their properties.  Only systems tested for
-# Nixpkgs are listed below
-
-with import ./lists.nix;
-with import ./types.nix;
-with import ./attrsets.nix;
-
-let
-  lib = import ./default.nix;
-  setTypes = type:
-    mapAttrs (name: value:
-      setType type ({inherit name;} // value)
-    );
-in
-
-rec {
-
-  isSignificantByte = isType "significant-byte";
-  significantBytes = setTypes "significant-byte" {
-    bigEndian = {};
-    littleEndian = {};
-  };
-
-
-  isCpuType = x: isType "cpu-type" x
-    && elem x.bits [8 16 32 64 128]
-    && (8 < x.bits -> isSignificantByte x.significantByte);
-
-  cpuTypes = with significantBytes;
-    setTypes "cpu-type" {
-      arm =      { bits = 32; significantByte = littleEndian; };
-      armv5tel = { bits = 32; significantByte = littleEndian; };
-      armv7l   = { bits = 32; significantByte = littleEndian; };
-      i686 =     { bits = 32; significantByte = littleEndian; };
-      powerpc =  { bits = 32; significantByte = bigEndian; };
-      x86_64 =   { bits = 64; significantByte = littleEndian; };
-    };
-
-
-  isExecFormat = isType "exec-format";
-  execFormats = setTypes "exec-format" {
-    aout = {}; # a.out
-    elf = {};
-    macho = {};
-    pe = {};
-    unknow = {};
-  };
-
-
-  isKernel = isType "kernel";
-  kernels = with execFormats;
-    setTypes "kernel" {
-      cygwin =  { execFormat = pe; };
-      darwin =  { execFormat = macho; };
-      freebsd = { execFormat = elf; };
-      linux =   { execFormat = elf; };
-      netbsd =  { execFormat = elf; };
-      none =    { execFormat = unknow; };
-      openbsd = { execFormat = elf; };
-      win32 =   { execFormat = pe; };
-    };
-
-
-  isArchitecture = isType "architecture";
-  architectures = setTypes "architecture" {
-    apple = {};
-    pc = {};
-    unknow = {};
-  };
-
-
-  isSystem = x: isType "system" x
-    && isCpuType x.cpu
-    && isArchitecture x.arch
-    && isKernel x.kernel;
-
-  mkSystem = {
-    cpu ? cpuTypes.i686,
-    arch ? architectures.pc,
-    kernel ? kernels.linux,
-    name ? "${cpu.name}-${arch.name}-${kernel.name}"
-  }: setType "system" {
-    inherit name cpu arch kernel;
-  };
-
-
-  is64Bit = matchAttrs { cpu = { bits = 64; }; };
-  isDarwin = matchAttrs { kernel = kernels.darwin; };
-  isi686 = matchAttrs { cpu = cpuTypes.i686; };
-  isLinux = matchAttrs { kernel = kernels.linux; };
-
-
-  # This should revert the job done by config.guess from the gcc compiler.
-  mkSystemFromString = s: let
-    l = lib.splitString "-" s;
-
-    getCpu = name:
-      attrByPath [name] (throw "Unknow cpuType `${name}'.")
-        cpuTypes;
-    getArch = name:
-      attrByPath [name] (throw "Unknow architecture `${name}'.")
-        architectures;
-    getKernel = name:
-      attrByPath [name] (throw "Unknow kernel `${name}'.")
-        kernels;
-
-    system =
-      if builtins.length l == 2 then
-        mkSystem rec {
-          name = s;
-          cpu = getCpu (head l);
-          arch =
-            if isDarwin system
-            then architectures.apple
-            else architectures.pc;
-          kernel = getKernel (head (tail l));
-        }
-      else
-        mkSystem {
-          name = s;
-          cpu = getCpu (head l);
-          arch = getArch (head (tail l));
-          kernel = getKernel (head (tail (tail l)));
-        };
-  in assert isSystem system; system;
-}
diff --git a/lib/systems/default.nix b/lib/systems/default.nix
new file mode 100644
index 000000000000..d956969a18f9
--- /dev/null
+++ b/lib/systems/default.nix
@@ -0,0 +1,23 @@
+rec {
+  doubles = import ./doubles.nix;
+  parse = import ./parse.nix;
+  platforms = import ./platforms.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 prefered, and to prevent cycles. A simpler fixed point where the RHS
+  # always just used `final.*` would fail on both counts.
+  elaborate = args: let
+    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;
+      # Just a guess, based on `system`
+      platform = platforms.selectBySystem final.system;
+    } // args;
+  in final;
+}
diff --git a/lib/systems/doubles.nix b/lib/systems/doubles.nix
new file mode 100644
index 000000000000..2622ddf4be1f
--- /dev/null
+++ b/lib/systems/doubles.nix
@@ -0,0 +1,44 @@
+let lists = import ../lists.nix; in
+let parse = import ./parse.nix; in
+let inherit (import ../attrsets.nix) matchAttrs; in
+
+let
+  all = [
+    "aarch64-linux"
+    "armv5tel-linux" "armv6l-linux" "armv7l-linux"
+
+    "mips64el-linux"
+
+    "i686-cygwin" "i686-freebsd" "i686-linux" "i686-netbsd" "i686-openbsd"
+
+    "x86_64-cygwin" "x86_64-darwin" "x86_64-freebsd" "x86_64-linux"
+    "x86_64-netbsd" "x86_64-openbsd" "x86_64-solaris"
+  ];
+
+  allParsed = map parse.mkSystemFromString all;
+
+  filterDoubles = f: map parse.doubleFromSystem (lists.filter f allParsed);
+
+in rec {
+  inherit all;
+
+  allBut = platforms: lists.filter (x: !(builtins.elem x platforms)) all;
+  none = [];
+
+  arm = filterDoubles (matchAttrs { cpu = { family = "arm"; bits = 32; }; });
+  i686 = filterDoubles parse.isi686;
+  mips = filterDoubles (matchAttrs { cpu = { family = "mips"; }; });
+  x86_64 = filterDoubles parse.isx86_64;
+
+  cygwin = filterDoubles (matchAttrs { kernel = parse.kernels.cygwin; });
+  darwin = filterDoubles parse.isDarwin;
+  freebsd = filterDoubles (matchAttrs { kernel = parse.kernels.freebsd; });
+  gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }); # Should be better
+  illumos = filterDoubles (matchAttrs { kernel = parse.kernels.solaris; });
+  linux = filterDoubles parse.isLinux;
+  netbsd = filterDoubles (matchAttrs { kernel = parse.kernels.netbsd; });
+  openbsd = filterDoubles (matchAttrs { kernel = parse.kernels.openbsd; });
+  unix = filterDoubles parse.isUnix;
+
+  mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux"];
+}
diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix
new file mode 100644
index 000000000000..f6315b8ad2a9
--- /dev/null
+++ b/lib/systems/parse.nix
@@ -0,0 +1,173 @@
+# Define the list of system with their properties.  Only systems tested for
+# Nixpkgs are listed below
+
+with import ../lists.nix;
+with import ../types.nix;
+with import ../attrsets.nix;
+
+let
+  lib = import ../default.nix;
+  setTypesAssert = type: pred:
+    mapAttrs (name: value:
+      #assert pred value;
+      setType type ({ inherit name; } // value));
+  setTypes = type: setTypesAssert type (_: true);
+
+in
+
+rec {
+
+  isSignificantByte = isType "significant-byte";
+  significantBytes = setTypes "significant-byte" {
+    bigEndian = {};
+    littleEndian = {};
+  };
+
+
+  isCpuType = isType "cpu-type";
+  cpuTypes = with significantBytes; setTypesAssert "cpu-type"
+    (x: elem x.bits [8 16 32 64 128]
+        && (if 8 < x.bits
+            then isSignificantByte x.significantByte
+            else !(x ? significantByte)))
+  {
+    arm      = { bits = 32; significantByte = littleEndian; family = "arm"; };
+    armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; };
+    armv6l   = { bits = 32; significantByte = littleEndian; family = "arm"; };
+    armv7a   = { bits = 32; significantByte = littleEndian; family = "arm"; };
+    armv7l   = { bits = 32; significantByte = littleEndian; family = "arm"; };
+    aarch64  = { bits = 64; significantByte = littleEndian; family = "arm"; };
+    i686     = { bits = 32; significantByte = littleEndian; family = "x86"; };
+    x86_64   = { bits = 64; significantByte = littleEndian; family = "x86"; };
+    mips64el = { bits = 32; significantByte = littleEndian; family = "mips"; };
+    powerpc  = { bits = 32; significantByte = bigEndian;    family = "powerpc"; };
+  };
+
+  isVendor = isType "vendor";
+  vendors = setTypes "vendor" {
+    apple = {};
+    pc = {};
+    unknown = {};
+  };
+
+  isExecFormat = isType "exec-format";
+  execFormats = setTypes "exec-format" {
+    aout = {}; # a.out
+    elf = {};
+    macho = {};
+    pe = {};
+    unknown = {};
+  };
+
+  isKernelFamily = isType "kernel-family";
+  kernelFamilies = setTypes "kernel-family" {
+    bsd = {};
+    unix = {};
+    windows-nt = {};
+    dos = {};
+  };
+
+  isKernel = x: isType "kernel" x;
+  kernels = with execFormats; with kernelFamilies; setTypesAssert "kernel"
+    (x: isExecFormat x.execFormat && all isKernelFamily (attrValues x.families))
+  {
+    cygwin  = { execFormat = pe;      families = { inherit /*unix*/ windows-nt; }; };
+    darwin  = { execFormat = macho;   families = { inherit unix; }; };
+    freebsd = { execFormat = elf;     families = { inherit unix bsd; }; };
+    linux   = { execFormat = elf;     families = { inherit unix; }; };
+    netbsd  = { execFormat = elf;     families = { inherit unix bsd; }; };
+    none    = { execFormat = unknown; families = { inherit unix; }; };
+    openbsd = { execFormat = elf;     families = { inherit unix bsd; }; };
+    solaris = { execFormat = elf;     families = { inherit unix; }; };
+    win32   = { execFormat = pe;      families = { inherit dos; }; };
+  };
+
+
+  isAbi = isType "abi";
+  abis = setTypes "abi" {
+    gnu = {};
+    msvc = {};
+    eabi = {};
+    androideabi = {};
+    unknown = {};
+  };
+
+  isSystem = isType "system";
+  mkSystem = { cpu, vendor, kernel, abi }:
+    assert isCpuType cpu && isVendor vendor && isKernel kernel && isAbi abi;
+    setType "system" {
+      inherit cpu vendor kernel abi;
+    };
+
+  is64Bit = matchAttrs { cpu = { bits = 64; }; };
+  is32Bit = matchAttrs { cpu = { bits = 32; }; };
+  isi686 = matchAttrs { cpu = cpuTypes.i686; };
+  isx86_64 = matchAttrs { cpu = cpuTypes.x86_64; };
+
+  isDarwin = matchAttrs { kernel = kernels.darwin; };
+  isLinux = matchAttrs { kernel = kernels.linux; };
+  isUnix = matchAttrs { kernel = { families = { inherit (kernelFamilies) unix; }; }; };
+  isWindows = s: matchAttrs { kernel = { families = { inherit (kernelFamilies) windows-nt; }; }; } s
+              || matchAttrs { kernel = { families = { inherit (kernelFamilies) dos; }; }; } s;
+
+
+  mkSkeletonFromList = l: {
+    "2" =    { cpu = elemAt l 0;                      kernel = elemAt l 1;                   };
+    "4" =    { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; abi = elemAt l 3; };
+    "3" = # Awkwards hacks, beware!
+      if elemAt l 1 == "apple"
+        then { cpu = elemAt l 0; vendor = "apple";    kernel = elemAt l 2;                   }
+      else if (elemAt l 1 == "linux") || (elemAt l 2 == "gnu")
+        then { cpu = elemAt l 0;                      kernel = elemAt l 1; abi = elemAt l 2; }
+      else throw "Target specification with 3 components is ambiguous";
+  }.${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:
+      attrByPath [name] (throw "Unknown CPU type: ${name}")
+        cpuTypes;
+    getVendor = name:
+      attrByPath [name] (throw "Unknown vendor: ${name}")
+        vendors;
+    getKernel = name:
+      attrByPath [name] (throw "Unknown kernel: ${name}")
+        kernels;
+    getAbi = name:
+      attrByPath [name] (throw "Unknown ABI: ${name}")
+        abis;
+
+    system = rec {
+      cpu = getCpu args.cpu;
+      vendor =
+        /**/ if args ? vendor    then getVendor args.vendor
+        else if isDarwin  system then vendors.apple
+        else if isWindows system then vendors.pc
+        else                     vendors.unknown;
+      kernel = getKernel args.kernel;
+      abi =
+        /**/ if args ? abi       then getAbi args.abi
+        else if isLinux   system then abis.gnu
+        else if isWindows system then abis.gnu
+        else                     abis.unknown;
+    };
+
+  in mkSystem system;
+
+  mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s));
+
+  doubleFromSystem = { cpu, vendor, kernel, abi, ... }: "${cpu.name}-${kernel.name}";
+
+  tripleFromSystem = { cpu, vendor, kernel, abi, ... } @ sys: assert isSystem sys; let
+    optAbi = lib.optionalString (abi != abis.unknown) "-${abi.name}";
+  in "${cpu.name}-${vendor.name}-${kernel.name}${optAbi}";
+
+}
diff --git a/lib/systems/platforms.nix b/lib/systems/platforms.nix
new file mode 100644
index 000000000000..4322c8e2ff68
--- /dev/null
+++ b/lib/systems/platforms.nix
@@ -0,0 +1,486 @@
+rec {
+  pcBase = {
+    name = "pc";
+    uboot = null;
+    kernelHeadersBaseConfig = "defconfig";
+    kernelBaseConfig = "defconfig";
+    # Build whatever possible as a module, if not stated in the extra config.
+    kernelAutoModules = true;
+    kernelTarget = "bzImage";
+  };
+
+  pc64 = pcBase // { kernelArch = "x86_64"; };
+
+  pc32 = pcBase // { kernelArch = "i386"; };
+
+  pc32_simplekernel = pc32 // {
+    kernelAutoModules = false;
+  };
+
+  pc64_simplekernel = pc64 // {
+    kernelAutoModules = false;
+  };
+
+  sheevaplug = {
+    name = "sheevaplug";
+    kernelMajor = "2.6";
+    kernelHeadersBaseConfig = "multi_v5_defconfig";
+    kernelBaseConfig = "multi_v5_defconfig";
+    kernelArch = "arm";
+    kernelAutoModules = false;
+    kernelExtraConfig = ''
+      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
+    '';
+    kernelMakeFlags = [ "LOADADDR=0x0200000" ];
+    kernelTarget = "uImage";
+    uboot = "sheevaplug";
+    # Only for uboot = uboot :
+    ubootConfig = "sheevaplug_config";
+    kernelDTB = true; # Beyond 3.10
+    gcc = {
+      arch = "armv5te";
+      float = "soft";
+    };
+  };
+
+  raspberrypi = {
+    name = "raspberrypi";
+    kernelMajor = "2.6";
+    kernelHeadersBaseConfig = "bcm2835_defconfig";
+    kernelBaseConfig = "bcmrpi_defconfig";
+    kernelDTB = true;
+    kernelArch = "arm";
+    kernelAutoModules = false;
+    kernelExtraConfig = ''
+      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 y
+      XFS_FS m
+      JFS_FS y
+      EXT4_FS 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
+
+      ZRAM 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
+
+      # nixos mounts some cgroup
+      CGROUPS y
+
+      # Latencytop
+      LATENCYTOP y
+    '';
+    kernelTarget = "zImage";
+    uboot = null;
+    gcc = {
+      arch = "armv6";
+      fpu = "vfp";
+      float = "hard";
+    };
+  };
+
+  raspberrypi2 = armv7l-hf-multiplatform // {
+    name = "raspberrypi2";
+    kernelBaseConfig = "bcm2709_defconfig";
+    kernelDTB = true;
+    kernelAutoModules = false;
+    kernelExtraConfig = ''
+      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 y
+      XFS_FS m
+      JFS_FS y
+      EXT4_FS 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
+
+      ZRAM 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
+
+      # nixos mounts some cgroup
+      CGROUPS y
+
+      # Latencytop
+      LATENCYTOP y
+
+      # Disable the common config Xen, it doesn't build on ARM
+      XEN? n
+    '';
+    kernelTarget = "zImage";
+    uboot = null;
+  };
+
+  guruplug = 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.
+
+    kernelBaseConfig = "guruplug_defconfig";
+    #kernelHeadersBaseConfig = "guruplug_defconfig";
+  };
+
+  fuloong2f_n32 = {
+    name = "fuloong2f_n32";
+    kernelMajor = "2.6";
+    kernelHeadersBaseConfig = "fuloong2e_defconfig";
+    kernelBaseConfig = "lemote2f_defconfig";
+    kernelArch = "mips";
+    kernelAutoModules = false;
+    kernelExtraConfig = ''
+      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
+    '';
+    kernelTarget = "vmlinux";
+    uboot = null;
+    gcc.arch = "loongson2f";
+  };
+
+  beaglebone = armv7l-hf-multiplatform // {
+    name = "beaglebone";
+    kernelBaseConfig = "omap2plus_defconfig";
+    kernelAutoModules = false;
+    kernelExtraConfig = ""; # TBD kernel config
+    kernelTarget = "zImage";
+    uboot = null;
+  };
+
+  armv7l-hf-multiplatform = {
+    name = "armv7l-hf-multiplatform";
+    kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
+    kernelHeadersBaseConfig = "multi_v7_defconfig";
+    kernelBaseConfig = "multi_v7_defconfig";
+    kernelArch = "arm";
+    kernelDTB = true;
+    kernelAutoModules = true;
+    kernelPreferBuiltin = true;
+    uboot = null;
+    kernelTarget = "zImage";
+    kernelExtraConfig = ''
+      # Fix broken sunxi-sid nvmem driver.
+      TI_CPTS y
+
+      # Hangs ODROID-XU4
+      ARM_BIG_LITTLE_CPUIDLE n
+    '';
+    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";
+      float = "hard";
+
+      # For Raspberry Pi the 2 the best would be:
+      #   cpu = "cortex-a7";
+      #   fpu = "neon-vfpv4";
+    };
+  };
+
+  aarch64-multiplatform = {
+    name = "aarch64-multiplatform";
+    kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
+    kernelHeadersBaseConfig = "defconfig";
+    kernelBaseConfig = "defconfig";
+    kernelArch = "arm64";
+    kernelDTB = true;
+    kernelAutoModules = true;
+    kernelPreferBuiltin = true;
+    kernelExtraConfig = ''
+      # Raspberry Pi 3 stuff. Not needed for kernels >= 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
+    '';
+    uboot = null;
+    kernelTarget = "Image";
+    gcc = {
+      arch = "armv8-a";
+    };
+  };
+
+  selectBySystem = system: {
+      "i686-linux" = pc32;
+      "x86_64-linux" = pc64;
+      "armv5tel-linux" = sheevaplug;
+      "armv6l-linux" = raspberrypi;
+      "armv7l-linux" = armv7l-hf-multiplatform;
+      "aarch64-linux" = aarch64-multiplatform;
+      "mips64el-linux" = fuloong2f_n32;
+    }.${system} or pcBase;
+}
diff --git a/lib/tests/release.nix b/lib/tests/release.nix
index f9f57424f7d0..dfa4ca2676d1 100644
--- a/lib/tests/release.nix
+++ b/lib/tests/release.nix
@@ -1,31 +1,40 @@
-{ nixpkgs }:
+{ nixpkgs ? { outPath = (import ../.).cleanSource ../..; revCount = 1234; shortRev = "abcdef"; }
+, # The platforms for which we build Nixpkgs.
+  supportedSystems ? [ builtins.currentSystem ]
+, # Strip most of attributes when evaluating to spare memory usage
+  scrubJobs ? true
+}:
 
-with import ../.. { };
+with import ../../pkgs/top-level/release-lib.nix { inherit supportedSystems scrubJobs; };
 with lib;
 
-stdenv.mkDerivation {
-  name = "nixpkgs-lib-tests";
-  buildInputs = [ nix ];
-  NIX_PATH="nixpkgs=${nixpkgs}";
+{
+  systems = import ./systems.nix { inherit lib assertTrue; };
 
-  buildCommand = ''
-    datadir="${nix}/share"
-    export TEST_ROOT=$(pwd)/test-tmp
-    export NIX_BUILD_HOOK=
-    export NIX_CONF_DIR=$TEST_ROOT/etc
-    export NIX_DB_DIR=$TEST_ROOT/db
-    export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
-    export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
-    export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
-    export NIX_STATE_DIR=$TEST_ROOT/var/nix
-    export NIX_STORE_DIR=$TEST_ROOT/store
-    export PAGER=cat
-    cacheDir=$TEST_ROOT/binary-cache
-    nix-store --init
+  moduleSystem = pkgs.stdenv.mkDerivation {
+    name = "nixpkgs-lib-tests";
+    buildInputs = [ pkgs.nix ];
+    NIX_PATH="nixpkgs=${nixpkgs}";
 
-    cd ${nixpkgs}/lib/tests
-    ./modules.sh
+    buildCommand = ''
+      datadir="${pkgs.nix}/share"
+      export TEST_ROOT=$(pwd)/test-tmp
+      export NIX_BUILD_HOOK=
+      export NIX_CONF_DIR=$TEST_ROOT/etc
+      export NIX_DB_DIR=$TEST_ROOT/db
+      export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
+      export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
+      export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
+      export NIX_STATE_DIR=$TEST_ROOT/var/nix
+      export NIX_STORE_DIR=$TEST_ROOT/store
+      export PAGER=cat
+      cacheDir=$TEST_ROOT/binary-cache
+      nix-store --init
 
-    touch $out
-  '';
+      cd ${nixpkgs}/lib/tests
+      ./modules.sh
+
+      touch $out
+    '';
+  };
 }
diff --git a/lib/tests/systems.nix b/lib/tests/systems.nix
new file mode 100644
index 000000000000..5eacc0defafb
--- /dev/null
+++ b/lib/tests/systems.nix
@@ -0,0 +1,31 @@
+# We assert that the new algorithmic way of generating these lists matches the
+# way they were hard-coded before.
+#
+# One might think "if we exhaustively test, what's the point of procedurally
+# calculating the lists anyway?". The answer is one can mindlessly update these
+# tests as new platforms become supported, and then just give the diff a quick
+# sanity check before committing :).
+{ lib, assertTrue }:
+
+with lib.systems.doubles;
+
+let mseteq = x: y: lib.sort lib.lessThan x == lib.sort lib.lessThan y; in
+
+{
+  all = assertTrue (mseteq all (linux ++ darwin ++ cygwin ++ freebsd ++ openbsd ++ netbsd ++ illumos));
+
+  arm = assertTrue (mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv7l-linux" ]);
+  i686 = assertTrue (mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" ]);
+  mips = assertTrue (mseteq mips [ "mips64el-linux" ]);
+  x86_64 = assertTrue (mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" ]);
+
+  cygwin = assertTrue (mseteq cygwin [ "i686-cygwin" "x86_64-cygwin" ]);
+  darwin = assertTrue (mseteq darwin [ "x86_64-darwin" ]);
+  freebsd = assertTrue (mseteq freebsd [ "i686-freebsd" "x86_64-freebsd" ]);
+  gnu = assertTrue (mseteq gnu (linux /* ++ hurd ++ kfreebsd ++ ... */));
+  illumos = assertTrue (mseteq illumos [ "x86_64-solaris" ]);
+  linux = assertTrue (mseteq linux [ "i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux" "mips64el-linux" ]);
+  netbsd = assertTrue (mseteq netbsd [ "i686-netbsd" "x86_64-netbsd" ]);
+  openbsd = assertTrue (mseteq openbsd [ "i686-openbsd" "x86_64-openbsd" ]);
+  unix = assertTrue (mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos));
+}