about summary refs log tree commit diff
path: root/nixpkgs/doc/cross-compilation.xml
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/doc/cross-compilation.xml')
-rw-r--r--nixpkgs/doc/cross-compilation.xml394
1 files changed, 55 insertions, 339 deletions
diff --git a/nixpkgs/doc/cross-compilation.xml b/nixpkgs/doc/cross-compilation.xml
index b7844da195d7..93fe9095ce2f 100644
--- a/nixpkgs/doc/cross-compilation.xml
+++ b/nixpkgs/doc/cross-compilation.xml
@@ -6,25 +6,11 @@
   <title>Introduction</title>
 
   <para>
-   "Cross-compilation" means compiling a program on one machine for another
-   type of machine. For example, a typical use of cross-compilation is to
-   compile programs for embedded devices. These devices often don't have the
-   computing power and memory to compile their own programs. One might think
-   that cross-compilation is a fairly niche concern. However, there are
-   significant advantages to rigorously distinguishing between build-time and
-   run-time environments! Significant, because the benefits apply even when one
-   is developing and deploying on the same machine. Nixpkgs is increasingly
-   adopting the opinion that packages should be written with cross-compilation
-   in mind, and nixpkgs should evaluate in a similar way (by minimizing
-   cross-compilation-specific special cases) whether or not one is
-   cross-compiling.
+   "Cross-compilation" means compiling a program on one machine for another type of machine. For example, a typical use of cross-compilation is to compile programs for embedded devices. These devices often don't have the computing power and memory to compile their own programs. One might think that cross-compilation is a fairly niche concern. However, there are significant advantages to rigorously distinguishing between build-time and run-time environments! Significant, because the benefits apply even when one is developing and deploying on the same machine. Nixpkgs is increasingly adopting the opinion that packages should be written with cross-compilation in mind, and nixpkgs should evaluate in a similar way (by minimizing cross-compilation-specific special cases) whether or not one is cross-compiling.
   </para>
 
   <para>
-   This chapter will be organized in three parts. First, it will describe the
-   basics of how to package software in a way that supports cross-compilation.
-   Second, it will describe how to use Nixpkgs when cross-compiling. Third, it
-   will describe the internal infrastructure supporting cross-compilation.
+   This chapter will be organized in three parts. First, it will describe the basics of how to package software in a way that supports cross-compilation. Second, it will describe how to use Nixpkgs when cross-compiling. Third, it will describe the internal infrastructure supporting cross-compilation.
   </para>
  </section>
 <!--============================================================-->
@@ -35,24 +21,12 @@
    <title>Platform parameters</title>
 
    <para>
-    Nixpkgs follows the
-    <link
-     xlink:href="https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html">conventions
-    of GNU autoconf</link>. We distinguish between 3 types of platforms when
-    building a derivation: <wordasword>build</wordasword>,
-    <wordasword>host</wordasword>, and <wordasword>target</wordasword>. In
-    summary, <wordasword>build</wordasword> is the platform on which a package
-    is being built, <wordasword>host</wordasword> is the platform on which it
-    will run. The third attribute, <wordasword>target</wordasword>, is relevant
-    only for certain specific compilers and build tools.
+    Nixpkgs follows the <link
+     xlink:href="https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html">conventions of GNU autoconf</link>. We distinguish between 3 types of platforms when building a derivation: <wordasword>build</wordasword>, <wordasword>host</wordasword>, and <wordasword>target</wordasword>. In summary, <wordasword>build</wordasword> is the platform on which a package is being built, <wordasword>host</wordasword> is the platform on which it will run. The third attribute, <wordasword>target</wordasword>, is relevant only for certain specific compilers and build tools.
    </para>
 
    <para>
-    In Nixpkgs, these three platforms are defined as attribute sets under the
-    names <literal>buildPlatform</literal>, <literal>hostPlatform</literal>,
-    and <literal>targetPlatform</literal>. They are always defined as
-    attributes in the standard environment. That means one can access them
-    like:
+    In Nixpkgs, these three platforms are defined as attribute sets under the names <literal>buildPlatform</literal>, <literal>hostPlatform</literal>, and <literal>targetPlatform</literal>. They are always defined as attributes in the standard environment. That means one can access them like:
 <programlisting>{ stdenv, fooDep, barDep, .. }: ...stdenv.buildPlatform...</programlisting>
     .
    </para>
@@ -64,9 +38,7 @@
      </term>
      <listitem>
       <para>
-       The "build platform" is the platform on which a package is built. Once
-       someone has a built package, or pre-built binary package, the build
-       platform should not matter and can be ignored.
+       The "build platform" is the platform on which a package is built. Once someone has a built package, or pre-built binary package, the build platform should not matter and can be ignored.
       </para>
      </listitem>
     </varlistentry>
@@ -76,9 +48,7 @@
      </term>
      <listitem>
       <para>
-       The "host platform" is the platform on which a package will be run. This
-       is the simplest platform to understand, but also the one with the worst
-       name.
+       The "host platform" is the platform on which a package will be run. This is the simplest platform to understand, but also the one with the worst name.
       </para>
      </listitem>
     </varlistentry>
@@ -88,44 +58,23 @@
      </term>
      <listitem>
       <para>
-       The "target platform" attribute is, unlike the other two attributes, not
-       actually fundamental to the process of building software. Instead, it is
-       only relevant for compatibility with building certain specific compilers
-       and build tools. It can be safely ignored for all other packages.
+       The "target platform" attribute is, unlike the other two attributes, not actually fundamental to the process of building software. Instead, it is only relevant for compatibility with building certain specific compilers and build tools. It can be safely ignored for all other packages.
       </para>
       <para>
-       The build process of certain compilers is written in such a way that the
-       compiler resulting from a single build can itself only produce binaries
-       for a single platform. The task of specifying this single "target
-       platform" is thus pushed to build time of the compiler. The root cause
-       of this is that the compiler (which will be run on the host) and the
-       standard library/runtime (which will be run on the target) are built by
-       a single build process.
+       The build process of certain compilers is written in such a way that the compiler resulting from a single build can itself only produce binaries for a single platform. The task of specifying this single "target platform" is thus pushed to build time of the compiler. The root cause of this is that the compiler (which will be run on the host) and the standard library/runtime (which will be run on the target) are built by a single build process.
       </para>
       <para>
-       There is no fundamental need to think about a single target ahead of
-       time like this. If the tool supports modular or pluggable backends, both
-       the need to specify the target at build time and the constraint of
-       having only a single target disappear. An example of such a tool is
-       LLVM.
+       There is no fundamental need to think about a single target ahead of time like this. If the tool supports modular or pluggable backends, both the need to specify the target at build time and the constraint of having only a single target disappear. An example of such a tool is LLVM.
       </para>
       <para>
-       Although the existence of a "target platfom" is arguably a historical
-       mistake, it is a common one: examples of tools that suffer from it are
-       GCC, Binutils, GHC and Autoconf. Nixpkgs tries to avoid sharing in the
-       mistake where possible. Still, because the concept of a target platform
-       is so ingrained, it is best to support it as is.
+       Although the existence of a "target platfom" is arguably a historical mistake, it is a common one: examples of tools that suffer from it are GCC, Binutils, GHC and Autoconf. Nixpkgs tries to avoid sharing in the mistake where possible. Still, because the concept of a target platform is so ingrained, it is best to support it as is.
       </para>
      </listitem>
     </varlistentry>
    </variablelist>
 
    <para>
-    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:
+    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>
@@ -135,13 +84,7 @@
      </term>
      <listitem>
       <para>
-       This is a two-component shorthand for the platform. Examples of this
-       would be "x86_64-darwin" and "i686-linux"; see
-       <literal>lib.systems.doubles</literal> for more. The first component
-       corresponds to the CPU architecture of the platform and the second to
-       the operating system of the platform (<literal>[cpu]-[os]</literal>).
-       This format has built-in support in Nix, such as the
-       <varname>builtins.currentSystem</varname> impure string.
+       This is a two-component shorthand for the platform. Examples of this would be "x86_64-darwin" and "i686-linux"; see <literal>lib.systems.doubles</literal> for more. The first component corresponds to the CPU architecture of the platform and the second to the operating system of the platform (<literal>[cpu]-[os]</literal>). This format has built-in support in Nix, such as the <varname>builtins.currentSystem</varname> impure string.
       </para>
      </listitem>
     </varlistentry>
@@ -151,15 +94,7 @@
      </term>
      <listitem>
       <para>
-       This is a 3- or 4- component shorthand for the platform. Examples of
-       this would be <literal>x86_64-unknown-linux-gnu</literal> and
-       <literal>aarch64-apple-darwin14</literal>. This is a standard format
-       called the "LLVM target triple", as they are pioneered by LLVM. In the
-       4-part form, this corresponds to
-       <literal>[cpu]-[vendor]-[os]-[abi]</literal>. This format is strictly
-       more informative than the "Nix host double", as the previous format
-       could analogously be termed. This needs a better name than
-       <varname>config</varname>!
+       This is a 3- or 4- component shorthand for the platform. Examples of this would be <literal>x86_64-unknown-linux-gnu</literal> and <literal>aarch64-apple-darwin14</literal>. This is a standard format called the "LLVM target triple", as they are pioneered by LLVM. In the 4-part form, this corresponds to <literal>[cpu]-[vendor]-[os]-[abi]</literal>. This format is strictly more informative than the "Nix host double", as the previous format could analogously be termed. This needs a better name than <varname>config</varname>!
       </para>
      </listitem>
     </varlistentry>
@@ -169,10 +104,7 @@
      </term>
      <listitem>
       <para>
-       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>. See
-       <literal>lib.systems.parse</literal> for the exact representation.
+       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>. See <literal>lib.systems.parse</literal> for the exact representation.
       </para>
      </listitem>
     </varlistentry>
@@ -182,10 +114,7 @@
      </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>.
+       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>
@@ -195,10 +124,7 @@
      </term>
      <listitem>
       <para>
-       These predicates are defined in <literal>lib.systems.inspect</literal>,
-       and slapped onto 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.
+       These predicates are defined in <literal>lib.systems.inspect</literal>, and slapped onto 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>
@@ -208,11 +134,7 @@
      </term>
      <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 that is working. Please help us triage these flags and
-       give them better homes!
+       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 that is working. Please help us triage these flags and give them better homes!
       </para>
      </listitem>
     </varlistentry>
@@ -224,62 +146,33 @@
 
    <note>
     <para>
-     This is a rather philosophical description that isn't very
-     Nixpkgs-specific. For an overview of all the relevant attributes given to
-     <varname>mkDerivation</varname>, see
-     <xref
-     linkend="ssec-stdenv-dependencies"/>. For a description of how
-     everything is implemented, see
-     <xref linkend="ssec-cross-dependency-implementation" />.
+     This is a rather philosophical description that isn't very Nixpkgs-specific. For an overview of all the relevant attributes given to <varname>mkDerivation</varname>, see <xref
+     linkend="ssec-stdenv-dependencies"/>. For a description of how everything is implemented, see <xref linkend="ssec-cross-dependency-implementation" />.
     </para>
    </note>
 
    <para>
-    In this section we explore the relationship between both runtime and
-    build-time dependencies and the 3 Autoconf platforms.
+    In this section we explore the relationship between both runtime and build-time dependencies and the 3 Autoconf platforms.
    </para>
 
    <para>
-    A run time dependency between two packages requires that their host
-    platforms match. This is directly implied by the meaning of "host platform"
-    and "runtime dependency": The package dependency exists while both packages
-    are running on a single host platform.
+    A run time dependency between two packages requires that their host platforms match. This is directly implied by the meaning of "host platform" and "runtime dependency": The package dependency exists while both packages are running on a single host platform.
    </para>
 
    <para>
-    A build time dependency, however, has a shift in platforms between the
-    depending package and the depended-on package. "build time dependency"
-    means that to build the depending package we need to be able to run the
-    depended-on's package. The depending package's build platform is therefore
-    equal to the depended-on package's host platform.
+    A build time dependency, however, has a shift in platforms between the depending package and the depended-on package. "build time dependency" means that to build the depending package we need to be able to run the depended-on's package. The depending package's build platform is therefore equal to the depended-on package's host platform.
    </para>
 
    <para>
-    If both the dependency and depending packages aren't compilers or other
-    machine-code-producing tools, we're done. And indeed
-    <varname>buildInputs</varname> and <varname>nativeBuildInputs</varname>
-    have covered these simpler build-time and run-time (respectively) changes
-    for many years. But if the dependency does produce machine code, we might
-    need to worry about its target platform too. In principle, that target
-    platform might be any of the depending package's build, host, or target
-    platforms, but we prohibit dependencies from a "later" platform to an
-    earlier platform to limit confusion because we've never seen a legitimate
-    use for them.
+    If both the dependency and depending packages aren't compilers or other machine-code-producing tools, we're done. And indeed <varname>buildInputs</varname> and <varname>nativeBuildInputs</varname> have covered these simpler build-time and run-time (respectively) changes for many years. But if the dependency does produce machine code, we might need to worry about its target platform too. In principle, that target platform might be any of the depending package's build, host, or target platforms, but we prohibit dependencies from a "later" platform to an earlier platform to limit confusion because we've never seen a legitimate use for them.
    </para>
 
    <para>
-    Finally, if the depending package is a compiler or other
-    machine-code-producing tool, it might need dependencies that run at "emit
-    time". This is for compilers that (regrettably) insist on being built
-    together with their source langauges' standard libraries. Assuming build !=
-    host != target, a run-time dependency of the standard library cannot be run
-    at the compiler's build time or run time, but only at the run time of code
-    emitted by the compiler.
+    Finally, if the depending package is a compiler or other machine-code-producing tool, it might need dependencies that run at "emit time". This is for compilers that (regrettably) insist on being built together with their source langauges' standard libraries. Assuming build != host != target, a run-time dependency of the standard library cannot be run at the compiler's build time or run time, but only at the run time of code emitted by the compiler.
    </para>
 
    <para>
-    Putting this all together, that means we have dependencies in the form
-    "host → target", in at most the following six combinations:
+    Putting this all together, that means we have dependencies in the form "host → target", in at most the following six combinations:
     <table>
      <caption>Possible dependency types</caption>
      <thead>
@@ -318,16 +211,7 @@
    </para>
 
    <para>
-    Some examples will make this table clearer. Suppose there's some package
-    that is being built with a <literal>(build, host, target)</literal>
-    platform triple of <literal>(foo, bar, baz)</literal>. If it has a
-    build-time library dependency, that would be a "host → build" dependency
-    with a triple of <literal>(foo, foo, *)</literal> (the target platform is
-    irrelevant). If it needs a compiler to be built, that would be a "build →
-    host" dependency with a triple of <literal>(foo, foo, *)</literal> (the
-    target platform is irrelevant). That compiler, would be built with another
-    compiler, also "build → host" dependency, with a triple of <literal>(foo,
-    foo, foo)</literal>.
+    Some examples will make this table clearer. Suppose there's some package that is being built with a <literal>(build, host, target)</literal> platform triple of <literal>(foo, bar, baz)</literal>. If it has a build-time library dependency, that would be a "host → build" dependency with a triple of <literal>(foo, foo, *)</literal> (the target platform is irrelevant). If it needs a compiler to be built, that would be a "build → host" dependency with a triple of <literal>(foo, foo, *)</literal> (the target platform is irrelevant). That compiler, would be built with another compiler, also "build → host" dependency, with a triple of <literal>(foo, foo, foo)</literal>.
    </para>
   </section>
 
@@ -335,20 +219,14 @@
    <title>Cross packaging cookbook</title>
 
    <para>
-    Some frequently encountered problems when packaging for cross-compilation
-    should be answered here. Ideally, the information above is exhaustive, so
-    this section cannot provide any new information, but it is ludicrous and
-    cruel to expect everyone to spend effort working through the interaction of
-    many features just to figure out the same answer to the same common
-    problem. Feel free to add to this list!
+    Some frequently encountered problems when packaging for cross-compilation should be answered here. Ideally, the information above is exhaustive, so this section cannot provide any new information, but it is ludicrous and cruel to expect everyone to spend effort working through the interaction of many features just to figure out the same answer to the same common problem. Feel free to add to this list!
    </para>
 
    <qandaset>
     <qandaentry xml:id="cross-qa-build-c-program-in-build-environment">
      <question>
       <para>
-       What if my package's build system needs to build a C program to be run
-       under the build environment?
+       What if my package's build system needs to build a C program to be run under the build environment?
       </para>
      </question>
      <answer>
@@ -366,11 +244,7 @@
      </question>
      <answer>
       <para>
-       Many packages assume that an unprefixed <command>ar</command> is
-       available, but Nix doesn't provide one. It only provides a prefixed one,
-       just as it only does for all the other binutils programs. It may be
-       necessary to patch the package to fix the build system to use a prefixed
-       `ar`.
+       Many packages assume that an unprefixed <command>ar</command> is available, but Nix doesn't provide one. It only provides a prefixed one, just as it only does for all the other binutils programs. It may be necessary to patch the package to fix the build system to use a prefixed `ar`.
       </para>
      </answer>
     </qandaentry>
@@ -395,82 +269,32 @@
   <title>Cross-building packages</title>
 
   <para>
-   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:
+   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:
 <programlisting>
-nix-build &lt;nixpkgs&gt; --arg crossSystem '(import &lt;nixpkgs/lib&gt;).systems.examples.fooBarBaz' -A whatever</programlisting>
+nix-build '&lt;nixpkgs&gt;' --arg crossSystem '(import &lt;nixpkgs/lib&gt;).systems.examples.fooBarBaz' -A whatever</programlisting>
   </para>
 
   <note>
    <para>
-    Eventually we would like to make these platform examples an unnecessary
-    convenience so that
+    Eventually we would like to make these platform examples an unnecessary convenience so that
 <programlisting>
-nix-build &lt;nixpkgs&gt; --arg crossSystem '{ config = "&lt;arch&gt;-&lt;os&gt;-&lt;vendor&gt;-&lt;abi&gt;"; }' -A whatever</programlisting>
-    works in the vast majority of cases. The problem today is dependencies on
-    other sorts of configuration which aren't given proper defaults. We rely on
-    the examples to crudely to set those configuration parameters in some
-    vaguely sane manner on the users behalf. Issue
-    <link xlink:href="https://github.com/NixOS/nixpkgs/issues/34274">#34274</link>
-    tracks this inconvenience along with its root cause in crufty configuration
-    options.
+nix-build '&lt;nixpkgs&gt;' --arg crossSystem '{ config = "&lt;arch&gt;-&lt;os&gt;-&lt;vendor&gt;-&lt;abi&gt;"; }' -A whatever</programlisting>
+    works in the vast majority of cases. The problem today is dependencies on other sorts of configuration which aren't given proper defaults. We rely on the examples to crudely to set those configuration parameters in some vaguely sane manner on the users behalf. Issue <link xlink:href="https://github.com/NixOS/nixpkgs/issues/34274">#34274</link> tracks this inconvenience along with its root cause in crufty configuration options.
    </para>
   </note>
 
   <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.
+   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.
+    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: While
-   the granularity of having 3 platforms is necessary to properly *build*
-   packages, it is overkill for specifying the user's *intent* when making a
-   build plan or package set. A simple "build vs deploy" dichotomy is adequate:
-   the sliding window principle described in the previous section shows how to
-   interpolate between the these two "end points" to get the 3 platform triple
-   for each bootstrapping stage. That means for any package a given package
-   set, even those not bound on the top level but only reachable via
-   dependencies or <varname>buildPackages</varname>, the three platforms will
-   be defined as one of <varname>localSystem</varname> or
-   <varname>crossSystem</varname>, with the former replacing the latter as one
-   traverses build-time dependencies. A last simple difference is that
-   <varname>crossSystem</varname> should be null when one doesn't want to
-   cross-compile, while the <varname>*Platform</varname>s are always non-null.
-   <varname>localSystem</varname> is always non-null.
+   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: While the granularity of having 3 platforms is necessary to properly *build* packages, it is overkill for specifying the user's *intent* when making a build plan or package set. A simple "build vs deploy" dichotomy is adequate: the sliding window principle described in the previous section shows how to interpolate between the these two "end points" to get the 3 platform triple for each bootstrapping stage. That means for any package a given package set, even those not bound on the top level but only reachable via dependencies or <varname>buildPackages</varname>, the three platforms will be defined as one of <varname>localSystem</varname> or <varname>crossSystem</varname>, with the former replacing the latter as one traverses build-time dependencies. A last simple difference is that <varname>crossSystem</varname> should be null when one doesn't want to cross-compile, while the <varname>*Platform</varname>s are always non-null. <varname>localSystem</varname> is always non-null.
   </para>
  </section>
 <!--============================================================-->
@@ -481,62 +305,20 @@ nix-build &lt;nixpkgs&gt; --arg crossSystem '{ config = "&lt;arch&gt;-&lt;os&gt;
    <title>Implementation of dependencies</title>
 
    <para>
-    The categorizes of dependencies developed in
-    <xref
-    linkend="ssec-cross-dependency-categorization"/> are specified as
-    lists of derivations given to <varname>mkDerivation</varname>, as
-    documented in <xref linkend="ssec-stdenv-dependencies"/>. In short,
-    each list of dependencies for "host → target" of "foo → bar" is called
-    <varname>depsFooBar</varname>, with exceptions for backwards
-    compatibility that <varname>depsBuildHost</varname> is instead called
-    <varname>nativeBuildInputs</varname> and <varname>depsHostTarget</varname>
-    is instead called <varname>buildInputs</varname>. Nixpkgs is now structured
-    so that each <varname>depsFooBar</varname> is automatically taken from
-    <varname>pkgsFooBar</varname>. (These <varname>pkgsFooBar</varname>s are
-    quite new, so there is no special case for
-    <varname>nativeBuildInputs</varname> and <varname>buildInputs</varname>.)
-    For example, <varname>pkgsBuildHost.gcc</varname> should be used at
-    build-time, while <varname>pkgsHostTarget.gcc</varname> should be used at
-    run-time.
+    The categorizes of dependencies developed in <xref
+    linkend="ssec-cross-dependency-categorization"/> are specified as lists of derivations given to <varname>mkDerivation</varname>, as documented in <xref linkend="ssec-stdenv-dependencies"/>. In short, each list of dependencies for "host → target" of "foo → bar" is called <varname>depsFooBar</varname>, with exceptions for backwards compatibility that <varname>depsBuildHost</varname> is instead called <varname>nativeBuildInputs</varname> and <varname>depsHostTarget</varname> is instead called <varname>buildInputs</varname>. Nixpkgs is now structured so that each <varname>depsFooBar</varname> is automatically taken from <varname>pkgsFooBar</varname>. (These <varname>pkgsFooBar</varname>s are quite new, so there is no special case for <varname>nativeBuildInputs</varname> and <varname>buildInputs</varname>.) For example, <varname>pkgsBuildHost.gcc</varname> should be used at build-time, while <varname>pkgsHostTarget.gcc</varname> should be used at run-time.
    </para>
 
    <para>
-    Now, for most of Nixpkgs's history, there were no
-    <varname>pkgsFooBar</varname> attributes, and most packages have not been
-    refactored to use it explicitly. Prior to those, there were just
-    <varname>buildPackages</varname>, <varname>pkgs</varname>, and
-    <varname>targetPackages</varname>. Those are now redefined as aliases to
-    <varname>pkgsBuildHost</varname>, <varname>pkgsHostTarget</varname>, and
-    <varname>pkgsTargetTarget</varname>. It is acceptable, even
-    recommended, to use them for libraries to show that the host platform is
-    irrelevant.
+    Now, for most of Nixpkgs's history, there were no <varname>pkgsFooBar</varname> attributes, and most packages have not been refactored to use it explicitly. Prior to those, there were just <varname>buildPackages</varname>, <varname>pkgs</varname>, and <varname>targetPackages</varname>. Those are now redefined as aliases to <varname>pkgsBuildHost</varname>, <varname>pkgsHostTarget</varname>, and <varname>pkgsTargetTarget</varname>. It is acceptable, even recommended, to use them for libraries to show that the host platform is irrelevant.
    </para>
 
    <para>
-    But before that, there was just <varname>pkgs</varname>, even though both
-    <varname>buildInputs</varname> and <varname>nativeBuildInputs</varname>
-    existed. [Cross barely worked, and those were implemented with some hacks
-    on <varname>mkDerivation</varname> to override dependencies.] What this
-    means is the vast majority of packages do not use any explicit package set
-    to populate their dependencies, just using whatever
-    <varname>callPackage</varname> gives them even if they do correctly sort
-    their dependencies into the multiple lists described above. And indeed,
-    asking that users both sort their dependencies, <emphasis>and</emphasis>
-    take them from the right attribute set, is both too onerous and redundant,
-    so the recommended approach (for now) is to continue just categorizing by
-    list and not using an explicit package set.
+    But before that, there was just <varname>pkgs</varname>, even though both <varname>buildInputs</varname> and <varname>nativeBuildInputs</varname> existed. [Cross barely worked, and those were implemented with some hacks on <varname>mkDerivation</varname> to override dependencies.] What this means is the vast majority of packages do not use any explicit package set to populate their dependencies, just using whatever <varname>callPackage</varname> gives them even if they do correctly sort their dependencies into the multiple lists described above. And indeed, asking that users both sort their dependencies, <emphasis>and</emphasis> take them from the right attribute set, is both too onerous and redundant, so the recommended approach (for now) is to continue just categorizing by list and not using an explicit package set.
    </para>
 
    <para>
-    To make this work, we "splice" together the six
-    <varname>pkgsFooBar</varname> package sets and have
-    <varname>callPackage</varname> actually take its arguments from that. This
-    is currently implemented in <filename>pkgs/top-level/splice.nix</filename>.
-    <varname>mkDerivation</varname> then, for each dependency attribute, pulls
-    the right derivation out from the splice. This splicing can be skipped when
-    not cross-compiling as the package sets are the same, but still is a bit
-    slow for cross-compiling. We'd like to do something better, but haven't
-    come up with anything yet.
+    To make this work, we "splice" together the six <varname>pkgsFooBar</varname> package sets and have <varname>callPackage</varname> actually take its arguments from that. This is currently implemented in <filename>pkgs/top-level/splice.nix</filename>. <varname>mkDerivation</varname> then, for each dependency attribute, pulls the right derivation out from the splice. This splicing can be skipped when not cross-compiling as the package sets are the same, but still is a bit slow for cross-compiling. We'd like to do something better, but haven't come up with anything yet.
    </para>
   </section>
 
@@ -544,21 +326,11 @@ nix-build &lt;nixpkgs&gt; --arg crossSystem '{ config = "&lt;arch&gt;-&lt;os&gt;
    <title>Bootstrapping</title>
 
    <para>
-    Each of the package sets described above come from a single bootstrapping
-    stage. While <filename>pkgs/top-level/default.nix</filename>, coordinates
-    the composition of stages at a high level,
-    <filename>pkgs/top-level/stage.nix</filename> "ties the knot" (creates the
-    fixed point) of each stage. The package sets are defined per-stage however,
-    so they can be thought of as edges between stages (the nodes) in a graph.
-    Compositions like <literal>pkgsBuildTarget.targetPackages</literal> can be
-    thought of as paths to this graph.
+    Each of the package sets described above come from a single bootstrapping stage. While <filename>pkgs/top-level/default.nix</filename>, coordinates the composition of stages at a high level, <filename>pkgs/top-level/stage.nix</filename> "ties the knot" (creates the fixed point) of each stage. The package sets are defined per-stage however, so they can be thought of as edges between stages (the nodes) in a graph. Compositions like <literal>pkgsBuildTarget.targetPackages</literal> can be thought of as paths to this graph.
    </para>
 
    <para>
-    While there are many package sets, and thus many edges, the stages can also
-    be arranged in a linear chain. In other words, many of the edges are
-    redundant as far as connectivity is concerned. This hinges on the type of
-    bootstrapping we do. Currently for cross it is:
+    While there are many package sets, and thus many edges, the stages can also be arranged in a linear chain. In other words, many of the edges are redundant as far as connectivity is concerned. This hinges on the type of bootstrapping we do. Currently for cross it is:
     <orderedlist>
      <listitem>
       <para>
@@ -576,101 +348,45 @@ nix-build &lt;nixpkgs&gt; --arg crossSystem '{ config = "&lt;arch&gt;-&lt;os&gt;
       </para>
      </listitem>
     </orderedlist>
-    In each stage, <varname>pkgsBuildHost</varname> refers the the previous
-    stage, <varname>pkgsBuildBuild</varname> refers to the one before that, and
-    <varname>pkgsHostTarget</varname> refers to the current one, and
-    <varname>pkgsTargetTarget</varname> refers to the next one. When there is
-    no previous or next stage, they instead refer to the current stage. Note
-    how all the invariants regarding the mapping between dependency and depending
-    packages' build host and target platforms are preserved.
-    <varname>pkgsBuildTarget</varname> and <varname>pkgsHostHost</varname> are
-    more complex in that the stage fitting the requirements isn't always a
-    fixed chain of "prevs" and "nexts" away (modulo the "saturating"
-    self-references at the ends). We just special case each instead. All the primary
-    edges are implemented is in <filename>pkgs/stdenv/booter.nix</filename>,
-    and secondarily aliases in <filename>pkgs/top-level/stage.nix</filename>.
+    In each stage, <varname>pkgsBuildHost</varname> refers the the previous stage, <varname>pkgsBuildBuild</varname> refers to the one before that, and <varname>pkgsHostTarget</varname> refers to the current one, and <varname>pkgsTargetTarget</varname> refers to the next one. When there is no previous or next stage, they instead refer to the current stage. Note how all the invariants regarding the mapping between dependency and depending packages' build host and target platforms are preserved. <varname>pkgsBuildTarget</varname> and <varname>pkgsHostHost</varname> are more complex in that the stage fitting the requirements isn't always a fixed chain of "prevs" and "nexts" away (modulo the "saturating" self-references at the ends). We just special case each instead. All the primary edges are implemented is in <filename>pkgs/stdenv/booter.nix</filename>, and secondarily aliases in <filename>pkgs/top-level/stage.nix</filename>.
    </para>
 
    <note>
     <para>
-     Note the native stages are bootstrapped in legacy ways that predate the
-     current cross implementation. This is why the the bootstrapping stages
-     leading up to the final stages are ignored inthe previous paragraph.
+     Note the native stages are bootstrapped in legacy ways that predate the current cross implementation. This is why the the bootstrapping stages leading up to the final stages are ignored inthe previous paragraph.
     </para>
    </note>
 
    <para>
-    If one looks at the 3 platform triples, one can see that they overlap such
-    that one could put them together into a chain like:
+    If one looks at the 3 platform triples, one can see that they overlap such that one could put them together into a chain like:
 <programlisting>
 (native, native, native, foreign, foreign)
 </programlisting>
-    If one imagines the saturating self references at the end being replaced
-    with infinite stages, and then overlays those platform triples, one ends up
-    with the infinite tuple:
+    If one imagines the saturating self references at the end being replaced with infinite stages, and then overlays those platform triples, one ends up with the infinite tuple:
 <programlisting>
 (native..., native, native, native, foreign, foreign, foreign...)
 </programlisting>
-    On can then imagine any sequence of platforms such that there are bootstrap
-    stages with their 3 platforms determined by "sliding a window" that is the
-    3 tuple through the sequence. This was the original model for
-    bootstrapping. Without a target platform (assume a better world where all
-    compilers are multi-target and all standard libraries are built in their
-    own derivation), this is sufficient. Conversely if one wishes to cross
-    compile "faster", with a "Canadian Cross" bootstraping stage where
-    <literal>build != host != target</literal>, more bootstrapping stages are
-    needed since no sliding window providess the pesky
-    <varname>pkgsBuildTarget</varname> package set since it skips the Canadian
-    cross stage's "host".
+    On can then imagine any sequence of platforms such that there are bootstrap stages with their 3 platforms determined by "sliding a window" that is the 3 tuple through the sequence. This was the original model for bootstrapping. Without a target platform (assume a better world where all compilers are multi-target and all standard libraries are built in their own derivation), this is sufficient. Conversely if one wishes to cross compile "faster", with a "Canadian Cross" bootstraping stage where <literal>build != host != target</literal>, more bootstrapping stages are needed since no sliding window providess the pesky <varname>pkgsBuildTarget</varname> package set since it skips the Canadian cross stage's "host".
    </para>
 
    <note>
     <para>
-     It is much better to refer to <varname>buildPackages</varname> than
-     <varname>targetPackages</varname>, or more broadly package sets that do
-     not mention "target". There are three reasons for this.
+     It is much better to refer to <varname>buildPackages</varname> than <varname>targetPackages</varname>, or more broadly package sets that do not mention "target". There are three reasons for this.
     </para>
     <para>
-     First, it is because bootstrapping stages do not have a unique
-     <varname>targetPackages</varname>. For example a <literal>(x86-linux,
-     x86-linux, arm-linux)</literal> and <literal>(x86-linux, x86-linux,
-     x86-windows)</literal> package set both have a <literal>(x86-linux,
-     x86-linux, x86-linux)</literal> package set. Because there is no canonical
-     <varname>targetPackages</varname> for such a native (<literal>build ==
-     host == target</literal>) package set, we set their
-     <varname>targetPackages</varname>
+     First, it is because bootstrapping stages do not have a unique <varname>targetPackages</varname>. For example a <literal>(x86-linux, x86-linux, arm-linux)</literal> and <literal>(x86-linux, x86-linux, x86-windows)</literal> package set both have a <literal>(x86-linux, x86-linux, x86-linux)</literal> package set. Because there is no canonical <varname>targetPackages</varname> for such a native (<literal>build == host == target</literal>) package set, we set their <varname>targetPackages</varname>
     </para>
     <para>
-     Second, it is because this is a frequent source of hard-to-follow
-     "infinite recursions" / cycles. When only package sets that don't mention
-     target are used, the package set forms a directed acyclic graph. This
-     means that all cycles that exist are confined to one stage. This means
-     they are a lot smaller, and easier to follow in the code or a backtrace. It
-     also means they are present in native and cross builds alike, and so more
-     likely to be caught by CI and other users.
+     Second, it is because this is a frequent source of hard-to-follow "infinite recursions" / cycles. When only package sets that don't mention target are used, the package set forms a directed acyclic graph. This means that all cycles that exist are confined to one stage. This means they are a lot smaller, and easier to follow in the code or a backtrace. It also means they are present in native and cross builds alike, and so more likely to be caught by CI and other users.
     </para>
     <para>
-     Thirdly, it is because everything target-mentioning only exists to
-     accommodate compilers with lousy build systems that insist on the compiler
-     itself and standard library being built together. Of course that is bad
-     because bigger derivations means longer rebuilds. It is also problematic because
-     it tends to make the standard libraries less like other libraries than
-     they could be, complicating code and build systems alike. Because of the
-     other problems, and because of these innate disadvantages, compilers ought
-     to be packaged another way where possible.
+     Thirdly, it is because everything target-mentioning only exists to accommodate compilers with lousy build systems that insist on the compiler itself and standard library being built together. Of course that is bad because bigger derivations means longer rebuilds. It is also problematic because it tends to make the standard libraries less like other libraries than they could be, complicating code and build systems alike. Because of the other problems, and because of these innate disadvantages, compilers ought to be packaged another way where possible.
     </para>
    </note>
 
    <note>
     <para>
-     If one explores Nixpkgs, they will see derivations with names like
-     <literal>gccCross</literal>. Such <literal>*Cross</literal> derivations is
-     a holdover from before we properly distinguished between the host and
-     target platforms—the derivation with "Cross" in the name covered the
-     <literal>build = host != target</literal> case, while the other covered
-     the <literal>host = target</literal>, with build platform the same or not
-     based on whether one was using its <literal>.nativeDrv</literal> or
-     <literal>.crossDrv</literal>. This ugliness will disappear soon.
+     If one explores Nixpkgs, they will see derivations with names like <literal>gccCross</literal>. Such <literal>*Cross</literal> derivations is a holdover from before we properly distinguished between the host and target platforms—the derivation with "Cross" in the name covered the <literal>build = host != target</literal> case, while the other covered the <literal>host = target</literal>, with build platform the same or not based on whether one was using its <literal>.nativeDrv</literal> or <literal>.crossDrv</literal>. This ugliness will disappear soon.
     </para>
    </note>
   </section>