lib: Consolidate platform configurations (used for crossSystem)

This is good for maintenance and education.

Changed files
+200 -173
doc
lib
pkgs
+44 -8
doc/cross-compilation.xml
···
This field is obsolete and will soon disappear—please do not use it.
</para></note>
<para>
-
The exact scheme these fields is a bit ill-defined due to a long and convoluted evolution, but this is slowly being cleaned up.
+
The exact schema these fields follow is a bit ill-defined due to a long and convoluted evolution, but this is slowly being cleaned up.
+
You can see examples of ones used in practice in <literal>lib.systems.examples</literal>; note how they are not all very consistent.
For now, here are few fields can count on them containing:
</para>
<variablelist>
···
This is a nix representation of a parsed LLVM target triple with white-listed components.
This can be specified directly, or actually parsed from the <varname>config</varname>.
[Technically, only one need be specified and the others can be inferred, though the precision of inference may not be very good.]
-
See <literal>lib.systems.parse</literal> for the exact representation, along with some <literal>is*</literal>predicates.
-
These predicates are superior to the ones in <varname>stdenv</varname> as they aren't tied to the build platform (host, as previously discussed, would be a saner default).
+
See <literal>lib.systems.parse</literal> for the exact representation.
+
</para>
+
</listitem>
+
</varlistentry>
+
<varlistentry>
+
<term><varname>libc</varname></term>
+
<listitem>
+
<para>
+
This is a string identifying the standard C library used.
+
Valid identifiers include "glibc" for GNU libc, "libsystem" for Darwin's Libsystem, and "uclibc" for µClibc.
+
It should probably be refactored to use the module system, like <varname>parse</varname>.
+
</para>
+
</listitem>
+
</varlistentry>
+
<varlistentry>
+
<term><varname>is*</varname></term>
+
<listitem>
+
<para>
+
These predicates are defined in <literal>lib.systems.inspect</literal>, and slapped on every platform.
+
They are superior to the ones in <varname>stdenv</varname> as they force the user to be explicit about which platform they are inspecting.
+
Please use these instead of those.
</para>
</listitem>
</varlistentry>
···
<listitem>
<para>
This is, quite frankly, a dumping ground of ad-hoc settings (it's an attribute set).
-
See <literal>lib.systems.platforms</literal> for examples—there's hopefully one in there that will work verbatim for each platform one is working.
+
See <literal>lib.systems.platforms</literal> for examples—there's hopefully one in there that will work verbatim for each platform that is working.
Please help us triage these flags and give them better homes!
</para>
</listitem>
···
More information needs to moved from the old wiki, especially <link xlink:href="https://nixos.org/wiki/CrossCompiling" />, for this section.
</para></note>
<para>
-
Many sources (manual, wiki, etc) probably mention passing <varname>system</varname>, <varname>platform</varname>, and, optionally, <varname>crossSystem</varname> to nixpkgs:
-
<literal>import &lt;nixpkgs&gt; { system = ..; platform = ..; crossSystem = ..; }</literal>.
-
<varname>system</varname> and <varname>platform</varname> together determine the system on which packages are built, and <varname>crossSystem</varname> specifies the platform on which packages are ultimately intended to run, if it is different.
-
This still works, but with more recent changes, one can alternatively pass <varname>localSystem</varname>, containing <varname>system</varname> and <varname>platform</varname>, for symmetry.
+
Nixpkgs can be instantiated with <varname>localSystem</varname> alone, in which case there is no cross compiling and everything is built by and for that system,
+
or also with <varname>crossSystem</varname>, in which case packages run on the latter, but all building happens on the former.
+
Both parameters take the same schema as the 3 (build, host, and target) platforms defined in the previous section.
+
As mentioned above, <literal>lib.systems.examples</literal> has some platforms which are used as arguments for these parameters in practice.
+
You can use them programmatically, or on the command line like <command>nix-build &lt;nixpkgs&gt; --arg crossSystem '(import &lt;nixpkgs/lib&gt;).systems.examples.fooBarBaz'</command>.
</para>
+
<para>
+
While one is free to pass both parameters in full, there's a lot of logic to fill in missing fields.
+
As discussed in the previous section, only one of <varname>system</varname>, <varname>config</varname>, and <varname>parsed</varname> is needed to infer the other two.
+
Additionally, <varname>libc</varname> will be inferred from <varname>parse</varname>.
+
Finally, <literal>localSystem.system</literal> is also <emphasis>impurely</emphasis> inferred based on the platform evaluation occurs.
+
This means it is often not necessary to pass <varname>localSystem</varname> at all, as in the command-line example in the previous paragraph.
+
</para>
+
<note>
+
<para>
+
Many sources (manual, wiki, etc) probably mention passing <varname>system</varname>, <varname>platform</varname>, along with the optional <varname>crossSystem</varname> to nixpkgs:
+
<literal>import &lt;nixpkgs&gt; { system = ..; platform = ..; crossSystem = ..; }</literal>.
+
Passing those two instead of <varname>localSystem</varname> is still supported for compatibility, but is discouraged.
+
Indeed, much of the inference we do for these parameters is motivated by compatibility as much as convenience.
+
</para>
+
</note>
<para>
One would think that <varname>localSystem</varname> and <varname>crossSystem</varname> overlap horribly with the three <varname>*Platforms</varname> (<varname>buildPlatform</varname>, <varname>hostPlatform,</varname> and <varname>targetPlatform</varname>; see <varname>stage.nix</varname> or the manual).
Actually, those identifiers are purposefully not used here to draw a subtle but important distinction:
+1
lib/systems/default.nix
···
parse = import ./parse.nix;
inspect = import ./inspect.nix;
platforms = import ./platforms.nix;
+
examples = import ./examples.nix;
# Elaborate a `localSystem` or `crossSystem` so that it contains everything
# necessary.
+130
lib/systems/examples.nix
···
+
# 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!
+
+
let platforms = import ./platforms.nix; in
+
+
rec {
+
#
+
# Linux
+
#
+
+
sheevaplug = rec {
+
config = "armv5te-unknown-linux-gnueabi";
+
bigEndian = false;
+
arch = "armv5te";
+
float = "soft";
+
withTLS = true;
+
libc = "glibc";
+
platform = platforms.sheevaplug;
+
openssl.system = "linux-generic32";
+
inherit (platform) gcc;
+
};
+
+
raspberryPi = rec {
+
config = "armv6l-unknown-linux-gnueabihf";
+
bigEndian = false;
+
arch = "armv6l";
+
float = "hard";
+
fpu = "vfp";
+
withTLS = true;
+
libc = "glibc";
+
platform = platforms.raspberrypi;
+
openssl.system = "linux-generic32";
+
inherit (platform) gcc;
+
};
+
+
armv7l-hf-multiplatform = rec {
+
config = "arm-unknown-linux-gnueabihf";
+
bigEndian = false;
+
arch = "armv7-a";
+
float = "hard";
+
fpu = "vfpv3-d16";
+
withTLS = true;
+
libc = "glibc";
+
platform = platforms.armv7l-hf-multiplatform;
+
openssl.system = "linux-generic32";
+
inherit (platform) gcc;
+
};
+
+
aarch64-multiplatform = rec {
+
config = "aarch64-unknown-linux-gnu";
+
bigEndian = false;
+
arch = "aarch64";
+
withTLS = true;
+
libc = "glibc";
+
platform = platforms.aarch64-multiplatform;
+
inherit (platform) gcc;
+
};
+
+
scaleway-c1 = armv7l-hf-multiplatform // rec {
+
platform = platforms.scaleway-c1;
+
inherit (platform) gcc;
+
inherit (gcc) fpu;
+
};
+
+
pogoplug4 = rec {
+
arch = "armv5tel";
+
config = "armv5tel-softfloat-linux-gnueabi";
+
float = "soft";
+
+
platform = platforms.pogoplug4;
+
+
inherit (platform) gcc;
+
libc = "glibc";
+
+
withTLS = true;
+
openssl.system = "linux-generic32";
+
};
+
+
fuloongminipc = rec {
+
config = "mips64el-unknown-linux-gnu";
+
bigEndian = false;
+
arch = "mips";
+
float = "hard";
+
withTLS = true;
+
libc = "glibc";
+
platform = platforms.fuloong2f_n32;
+
openssl.system = "linux-generic32";
+
inherit (platform) gcc;
+
};
+
+
#
+
# Darwin
+
#
+
+
iphone64 = {
+
config = "aarch64-apple-darwin14";
+
arch = "arm64";
+
libc = "libsystem";
+
platform = {};
+
};
+
+
iphone32 = {
+
config = "arm-apple-darwin10";
+
arch = "armv7-a";
+
libc = "libsystem";
+
platform = {};
+
};
+
+
#
+
# Windows
+
#
+
+
# 32 bit mingw-w64
+
mingw32 = {
+
config = "i686-pc-mingw32";
+
arch = "x86"; # Irrelevant
+
libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
+
platform = {};
+
};
+
+
# 64 bit mingw-w64
+
mingwW64 = {
+
# That's the triplet they use in the mingw-w64 docs.
+
config = "x86_64-pc-mingw32";
+
arch = "x86_64"; # Irrelevant
+
libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
+
platform = {};
+
};
+
}
+8 -1
lib/systems/platforms.nix
···
arch = "armv6";
fpu = "vfp";
float = "hard";
+
# TODO(@Ericson2314) what is this and is it a good idea? It was
+
# used in some cross compilation examples but not others.
+
#
+
# abi = "aapcs-linux";
};
};
···
'';
kernelTarget = "vmlinux";
uboot = null;
-
gcc.arch = "loongson2f";
+
gcc = {
+
arch = "loongson2f";
+
abi = "n32";
+
};
};
beaglebone = armv7l-hf-multiplatform // {
+10 -82
pkgs/stdenv/linux/make-bootstrap-tools-cross.nix
···
lib = import ../../../lib;
pkgsFun = import ../../..;
-
sheevaplugCrossSystem = {
-
crossSystem = rec {
-
config = "arm-linux-gnueabi";
-
bigEndian = false;
-
arch = "armv5te";
-
float = "soft";
-
withTLS = true;
-
libc = "glibc";
-
platform = lib.systems.platforms.sheevaplug;
-
openssl.system = "linux-generic32";
-
inherit (platform) gcc;
-
};
-
};
-
-
raspberrypiCrossSystem = {
-
crossSystem = rec {
-
config = "arm-linux-gnueabihf";
-
bigEndian = false;
-
arch = "armv6";
-
float = "hard";
-
fpu = "vfp";
-
withTLS = true;
-
libc = "glibc";
-
platform = lib.systems.platforms.raspberrypi;
-
openssl.system = "linux-generic32";
-
inherit (platform) gcc;
-
};
-
};
-
-
armv7l-hf-multiplatform-crossSystem = {
-
crossSystem = rec {
-
config = "arm-linux-gnueabihf";
-
bigEndian = false;
-
arch = "armv7-a";
-
float = "hard";
-
fpu = "vfpv3-d16";
-
withTLS = true;
-
libc = "glibc";
-
platform = lib.systems.platforms.armv7l-hf-multiplatform;
-
openssl.system = "linux-generic32";
-
inherit (platform) gcc;
-
};
-
};
-
-
aarch64-multiplatform-crossSystem = {
-
crossSystem = rec {
-
config = "aarch64-linux-gnu";
-
bigEndian = false;
-
arch = "aarch64";
-
withTLS = true;
-
libc = "glibc";
-
platform = lib.systems.platforms.aarch64-multiplatform;
-
inherit (platform) gcc;
-
};
-
};
-
-
scaleway-c1-crossSystem.crossSystem = armv7l-hf-multiplatform-crossSystem.crossSystem // rec {
-
platform = lib.systems.platforms.scaleway-c1;
-
inherit (platform) gcc;
-
inherit (gcc) fpu;
-
};
-
-
pogoplug4-crossSystem.crossSystem = {
-
arch = "armv5tel";
-
config = "armv5tel-softfloat-linux-gnueabi";
-
float = "soft";
-
-
platform = lib.systems.platforms.pogoplug4;
-
-
inherit (lib.systems.platforms.pogoplug4) gcc;
-
libc = "glibc";
-
-
withTLS = true;
-
openssl.system = "linux-generic32";
-
};
+
inherit (lib.systems.examples)
+
sheevaplug raspberryPi armv7l-hf-multiplatform
+
aarch64-multiplatform scaleway-c1 pogoplug4;
selectedCrossSystem =
-
if toolsArch == "armv5tel" then sheevaplugCrossSystem else
-
if toolsArch == "scaleway" then scaleway-c1-crossSystem else
-
if toolsArch == "pogoplug4" then pogoplug4-crossSystem else
-
if toolsArch == "armv6l" then raspberrypiCrossSystem else
-
if toolsArch == "armv7l" then armv7l-hf-multiplatform-crossSystem else
-
if toolsArch == "aarch64" then aarch64-multiplatform-crossSystem else null;
+
if toolsArch == "armv5tel" then sheevaplug else
+
if toolsArch == "scaleway" then scaleway-c1 else
+
if toolsArch == "pogoplug4" then pogoplug4 else
+
if toolsArch == "armv6l" then raspberryPi else
+
if toolsArch == "armv7l" then armv7l-hf-multiplatform else
+
if toolsArch == "aarch64" then aarch64-multiplatform else null;
-
pkgs = pkgsFun ({inherit system;} // selectedCrossSystem);
+
pkgs = pkgsFun ({ inherit system; crossSystem = selectedCrossSystem; });
glibc = pkgs.libcCross;
bash = pkgs.bash;
+7 -82
pkgs/top-level/release-cross.nix
···
guile = nativePlatforms;
};
-
darwinToAarch64 = let
-
crossSystem = {
-
config = "aarch64-apple-darwin14";
-
arch = "arm64";
-
libc = "libSystem";
-
};
-
in mapTestOnCross crossSystem darwinCommon;
+
crossIphone64 = mapTestOnCross lib.systems.examples.iphone64 darwinCommon;
-
darwinToArm = let
-
crossSystem = {
-
config = "arm-apple-darwin10";
-
arch = "armv7-a";
-
libc = "libSystem";
-
};
-
in mapTestOnCross crossSystem darwinCommon;
+
crossIphone32 = mapTestOnCross lib.systems.examples.iphone32 darwinCommon;
/* Test some cross builds to the Sheevaplug */
-
crossSheevaplugLinux = let
-
crossSystem = {
-
config = "armv5tel-unknown-linux-gnueabi";
-
bigEndian = false;
-
arch = "arm";
-
float = "soft";
-
withTLS = true;
-
platform = lib.systems.platforms.sheevaplug;
-
libc = "glibc";
-
openssl.system = "linux-generic32";
-
};
-
in mapTestOnCross crossSystem (linuxCommon // {
+
crossSheevaplugLinux = mapTestOnCross lib.systems.examples.sheevaplug (linuxCommon // {
ubootSheevaplug = nativePlatforms;
});
-
/* Test some cross builds on 32 bit mingw-w64 */
-
crossMingw32 = let
-
crossSystem = {
-
config = "i686-pc-mingw32";
-
arch = "x86"; # Irrelevant
-
libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
-
platform = {};
-
};
-
in mapTestOnCross crossSystem windowsCommon;
-
+
crossMingw32 = mapTestOnCross lib.systems.examples.mingw32 windowsCommon;
/* Test some cross builds on 64 bit mingw-w64 */
-
crossMingwW64 = let
-
crossSystem = {
-
# That's the triplet they use in the mingw-w64 docs.
-
config = "x86_64-pc-mingw32";
-
arch = "x86_64"; # Irrelevant
-
libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
-
platform = {};
-
};
-
in mapTestOnCross crossSystem windowsCommon;
-
+
crossMingwW64 = mapTestOnCross lib.systems.examples.mingwW64 windowsCommon;
/* Linux on the fuloong */
-
fuloongminipc = let
-
crossSystem = {
-
config = "mips64el-unknown-linux-gnu";
-
bigEndian = false;
-
arch = "mips";
-
float = "hard";
-
withTLS = true;
-
libc = "glibc";
-
platform = lib.systems.platforms.fuloong2f_n32;
-
openssl.system = "linux-generic32";
-
gcc = {
-
arch = "loongson2f";
-
abi = "n32";
-
};
-
};
-
in mapTestOnCross crossSystem linuxCommon;
-
+
fuloongminipc = mapTestOnCross lib.systems.examples.fuloongminipc linuxCommon;
/* Linux on Raspberrypi */
-
rpi = let
-
crossSystem = {
-
config = "armv6l-unknown-linux-gnueabi";
-
bigEndian = false;
-
arch = "arm";
-
float = "hard";
-
fpu = "vfp";
-
withTLS = true;
-
libc = "glibc";
-
platform = lib.systems.platforms.raspberrypi;
-
openssl.system = "linux-generic32";
-
gcc = {
-
arch = "armv6";
-
fpu = "vfp";
-
float = "softfp";
-
abi = "aapcs-linux";
-
};
-
};
-
in mapTestOnCross crossSystem (linuxCommon // {
+
rpi = mapTestOnCross lib.systems.examples.raspberryPi (linuxCommon // {
vim = nativePlatforms;
unzip = nativePlatforms;
ddrescue = nativePlatforms;