documentation: cross-compilation - partial rewrite
This commit is contained in:
parent
8d4e37710f
commit
b20916bd98
@ -11,7 +11,7 @@
|
||||
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, but there are advantages to being rigorous about distinguishing build-time vs run-time environments even when one is developing and deploying on the same machine.
|
||||
Nixpkgs is increasingly adopting this opinion in 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.
|
||||
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>
|
||||
@ -30,11 +30,11 @@
|
||||
<section>
|
||||
<title>Platform parameters</title>
|
||||
<para>
|
||||
The three GNU Autoconf platforms, <wordasword>build</wordasword>, <wordasword>host</wordasword>, and <wordasword>target</wordasword>, are historically the result of much confusion.
|
||||
<link xlink:href="https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html" /> clears this up somewhat but there is more to be said.
|
||||
An important advice to get out the way is, unless you are packaging a compiler or other build tool, just worry about the build and host platforms.
|
||||
Dealing with just two platforms usually better matches people's preconceptions, and in this case is completely correct.
|
||||
Nixpkgs follows the the <link xlink:href="https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html">common historical convention of GNU autoconf</link> of distinguishing between 3 types of platform: <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 is to 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>.
|
||||
All three are always defined as attributes in the standard environment, and at the top level. That means one can get at them just like a dependency in a function that is imported with <literal>callPackage</literal>:
|
||||
@ -52,7 +52,7 @@
|
||||
<varlistentry>
|
||||
<term><varname>hostPlatform</varname></term>
|
||||
<listitem><para>
|
||||
The "host platform" is the platform on which a package is run.
|
||||
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>
|
||||
@ -60,22 +60,24 @@
|
||||
<term><varname>targetPlatform</varname></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The "target platform" is black sheep.
|
||||
The other two intrinsically apply to all compiled software—or any build process with a notion of "build-time" followed by "run-time".
|
||||
The target platform only applies to programming tools, and even then only is a good for for some of them.
|
||||
Briefly, GCC, Binutils, GHC, and certain other tools are written in such a way such that a single build can only compile code for a single platform.
|
||||
Thus, when building them, one must think ahead about which platforms they wish to use the tool to produce machine code for, and build binaries for each.
|
||||
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 compatability with building certain specific compilers and build tools.
|
||||
It can be safely ignored for all other packages.
|
||||
</para>
|
||||
<para>
|
||||
There is no fundamental need to think about the target ahead of time like this.
|
||||
LLVM, for example, was designed from the beginning with cross-compilation in mind, and so a normal LLVM binary will support every architecture that LLVM supports.
|
||||
If the tool supports modular or pluggable backends, one might imagine specifying a <emphasis>set</emphasis> of target platforms / backends one wishes to support, rather than a single one.
|
||||
The build process of certain compilers is written in such a way such that the compiler resulting from a single build can itself only produce binaries for a single platform.
|
||||
The task specifying this single "target platform" is thus pushed to build time of the compiler.
|
||||
The root cause of this mistake is often that the compiler (which will be run on the host) and the the standard library/runtime (which will be run on the target) are built by a single build process.
|
||||
</para>
|
||||
<para>
|
||||
The biggest reason for mess, if there is one, is that many compilers have the bad habit a build process that builds the compiler and standard library/runtime together.
|
||||
Then the specifying target platform is essential, because it determines the host platform of the standard library/runtime.
|
||||
Nixpkgs tries to avoid this where possible too, but still, because the concept of a target platform is so ingrained now in Autoconf and other tools, it is best to support it as is.
|
||||
Tools like LLVM that don't need up-front target platforms can safely ignore it like normal packages, and it will do no harm.
|
||||
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 existance 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>
|
||||
@ -155,14 +157,22 @@
|
||||
<section>
|
||||
<title>Specifying Dependencies</title>
|
||||
<para>
|
||||
As mentioned in the introduction to this chapter, one can think about a build time vs run time distinction whether cross-compiling or not.
|
||||
In the case of cross-compilation, this corresponds with whether a derivation running on the native or foreign platform is produced.
|
||||
An interesting thing to think about is how this corresponds with the three Autoconf platforms.
|
||||
In the run-time case, the depending and depended-on package simply have matching build, host, and target platforms.
|
||||
But in the build-time case, one can imagine "sliding" the platforms one over.
|
||||
The depended-on package's host and target platforms (respectively) become the depending package's build and host platforms.
|
||||
This is the most important guiding principle behind cross-compilation with Nixpkgs, and will be called the <wordasword>sliding window principle</wordasword>.
|
||||
In this section we explore the relationship between both runtime and buildtime dependencies and the 3 Autoconf platforms.
|
||||
</para>
|
||||
<para>
|
||||
A runtime dependency between 2 packages implies that between them both the host and target platforms match.
|
||||
This is directly implied by the meaning of "host platform" and "runtime dependency":
|
||||
The package dependency exists while both packages are runnign on a single host platform.
|
||||
</para>
|
||||
<para>
|
||||
A build time dependency, however, implies a shift in platforms between the depending package and the depended-on package.
|
||||
The meaning of a build time dependency is 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.
|
||||
Analogously, the depending package's host platform is equal to the depended-on package's target platform.
|
||||
</para>
|
||||
<para>
|
||||
In this manner, given the 3 platforms for one package, we can determine the three platforms for all its transitive dependencies.
|
||||
This is the most important guiding principle behind cross-compilation with Nixpkgs, and will be called the <wordasword>sliding window principle</wordasword>.
|
||||
</para>
|
||||
<para>
|
||||
Some examples will probably make this clearer.
|
||||
|
Loading…
Reference in New Issue
Block a user