1
0
Fork 0
mirror of https://github.com/NixOS/nix.dev.git synced 2024-10-18 14:32:43 -04:00

Merge pull request #327 from worktheclock/patch-10

Cross compilation RITZA edit
This commit is contained in:
Domen Kožar 2022-09-26 13:38:25 +02:00 committed by GitHub
commit 9dac52e1f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -10,17 +10,14 @@ myst:
# Cross compilation # Cross compilation
When compiling code, we can distinguish between the **build platform**, where the executable When compiling code, we can distinguish between the **build platform**, where the executable is *built*, and the **host platform**, where the compiled executable *runs*. [^id3]
is *built*, and the **host platform**, where the compiled executable *runs*. [^id3]
**Native compilation** is the special case where those two platforms are the same. **Native compilation** is the special case where those two platforms are the same.
**Cross compilation** is the general case where those two platforms are not. **Cross compilation** is the general case where those two platforms are not.
Cross compilation needed when the host platform has limited resources (such as CPU) Cross compilation is needed when the host platform has limited resources (such as CPU) or when it's not easily accessible for development.
or when it's not easily accessible for development.
The `nixpkgs` package collection has world-class support for cross compilation, The `nixpkgs` package collection has world-class support for cross compilation, after many years of hard work by the Nix community.
after many years of hard work by the Nix community.
[^id3]: Terminology for cross compilation platforms differs between build systems. [^id3]: Terminology for cross compilation platforms differs between build systems.
We have chosen to follow We have chosen to follow
@ -28,17 +25,16 @@ after many years of hard work by the Nix community.
## What's a target platform? ## What's a target platform?
There is a third concept for a platform we call **target platform**. There is a third concept for a platform we call a **target platform**.
It matters in cases where you want to build a compiler binary. The target platform is relevant to cases where you want to build a compiler binary.
Then you would build a compiler on the *build platform*, run it to compile code on the In such cases, you would build a compiler on the *build platform*, run it to compile code on the *host platform*, and run the final executable on the *target platform*.
*host platform*, and run the final executable on the *target platform*.
Since that is rarely needed, we will assume that the target is identical to the host. Since this is rarely needed, we will assume that the target is identical to the host.
## Pinning nixpkgs ## Pinning Nixpkgs
To ensure reproducibility of this tutorial as explained in {ref}`the pinning tutorial <pinning-nixpkgs>`: To ensure the reproducibility of this tutorial as explained in {ref}`the pinning tutorial <pinning-nixpkgs>`:
```shell-session ```shell-session
$ NIX_PATH=https://github.com/NixOS/nixpkgs/archive/9420363b95521e65a76eb5153de1eaee4a2e41c6.tar.gz $ NIX_PATH=https://github.com/NixOS/nixpkgs/archive/9420363b95521e65a76eb5153de1eaee4a2e41c6.tar.gz
@ -46,18 +42,16 @@ $ NIX_PATH=https://github.com/NixOS/nixpkgs/archive/9420363b95521e65a76eb5153de1
## Determining the host platform config ## Determining the host platform config
The build platform is determined automatically by Nix The build platform is determined automatically by Nix during the configure phase.
as it can just guess it during the configure phase.
The host platform is best determined by running on the host platform: The host platform is best determined by running this command on the host platform:
```shell-session ```shell-session
$ bash $(nix-build '<nixpkgs>' -A gnu-config)/config.guess $ bash $(nix-build '<nixpkgs>' -A gnu-config)/config.guess
aarch64-unknown-linux-gnu aarch64-unknown-linux-gnu
``` ```
In case that's not possible (when the host platform is not easily accessible In case this is not possible (for example, when the host platform is not easily accessible for development), the platform config has to be constructed manually via the following template:
for development), the platform config has to be constructed manually via the following template:
``` ```
<cpu>-<vendor>-<os>-<abi> <cpu>-<vendor>-<os>-<abi>
@ -66,12 +60,9 @@ for development), the platform config has to be constructed manually via the fol
This string representation is used in `nixpkgs` for historic reasons. This string representation is used in `nixpkgs` for historic reasons.
Note that `<vendor>` is often `unknown` and `<abi>` is optional. Note that `<vendor>` is often `unknown` and `<abi>` is optional.
There's also no unique identifier for a platform, for example `unknown` and There's also no unique identifier for a platform, for example `unknown` and `pc` are interchangeable (which is why the script is called `config.guess`).
`pc` are interchangeable (hence it's called config.guess).
If you can't install Nix, find a way to run `config.guess` (usually comes with If you can't install Nix, find a way to run `config.guess` (usually comes with the autoconf package) from the OS you're able to run on the host platform.
: the autoconf package) from the OS you're able to run on the host platform.
Some other common examples of platform configs: Some other common examples of platform configs:
@ -129,7 +120,8 @@ pkgsCross.mmix pkgsCross.x86_64-unknown-redox
pkgsCross.msp430 pkgsCross.msp430
``` ```
These attribute names for cross compilation packages have been chosen somewhat freely over the course of time. They usually do not match the corresponding platform config string. These attribute names for cross compilation packages have been chosen somewhat freely over the course of time.
They usually do not match the corresponding platform config string.
You can retrieve the platform string from `pkgsCross.<platform>.stdenv.hostPlatform.config`: You can retrieve the platform string from `pkgsCross.<platform>.stdenv.hostPlatform.config`:
@ -153,7 +145,7 @@ The mechanism for setting up cross compilation works as follows:
Taking `pkgs.pkgsCross.<host>.hello` will produce the package `hello` compiled on the build platform to run on the `<host>` platform. Taking `pkgs.pkgsCross.<host>.hello` will produce the package `hello` compiled on the build platform to run on the `<host>` platform.
There are multiple, equivalent ways to access packages targeted to the host platform. There are multiple equivalent ways to access packages targeted to the host platform.
1. Explicitly pick the host platform package from within the build platform environment: 1. Explicitly pick the host platform package from within the build platform environment:
@ -191,10 +183,9 @@ There are multiple, equivalent ways to access packages targeted to the host plat
$ nix-build '<nixpkgs>' -A hello --arg crossSystem '{ config = "aarch64-unknown-linux-gnu"; }' $ nix-build '<nixpkgs>' -A hello --arg crossSystem '{ config = "aarch64-unknown-linux-gnu"; }'
``` ```
## Cross compiling for the first time! ## Cross compiling for the first time
To cross compile a package like [hello](https://www.gnu.org/software/hello/), To cross compile a package like [hello](https://www.gnu.org/software/hello/), pick the platform attribute — `aarch64-multiplatform` in our case — and run:
pick the platform attribute - `aarch64-multiplatform` in our case - and run:
```shell-session ```shell-session
$ nix-build '<nixpkgs>' -A pkgsCross.aarch64-multiplatform.hello $ nix-build '<nixpkgs>' -A pkgsCross.aarch64-multiplatform.hello
@ -202,15 +193,11 @@ $ nix-build '<nixpkgs>' -A pkgsCross.aarch64-multiplatform.hello
/nix/store/pzi2h0d60nb4ydcl3nn7cbxxdnibw3sy-hello-aarch64-unknown-linux-gnu-2.10 /nix/store/pzi2h0d60nb4ydcl3nn7cbxxdnibw3sy-hello-aarch64-unknown-linux-gnu-2.10
``` ```
[Search for a package](https://search.nixos.org/packages) attribute name to find the [Search for a package](https://search.nixos.org/packages) attribute name to find the one you're interested in building.
one that you're interested in building.
## Real-world cross compiling of a Hello World example ## Real-world cross compiling of a Hello World example
To show off the power of cross compilation in Nix, let's build our own Hello World program To show off the power of cross compilation in Nix, let's build our own Hello World program by cross compiling it as static executables to `armv6l-unknown-linux-gnueabihf` and `x86_64-w64-mingw32` (Windows) platforms and run the resulting executable with [an emulator](https://en.wikipedia.org/wiki/Emulator).
by cross compiling it as static executables to `armv6l-unknown-linux-gnueabihf`
and `x86_64-w64-mingw32` (Windows) platforms and run the resulting executable
with [an emulator](https://en.wikipedia.org/wiki/Emulator).
```nix ```nix
{ pkgs ? import <nixpkgs> {} { pkgs ? import <nixpkgs> {}
@ -262,11 +249,9 @@ Hello, world!
## Developer environment with a cross compiler ## Developer environment with a cross compiler
In the {ref}`tutorial for declarative reproducible environments <declarative-reproducible-envs>`, In the {ref}`tutorial for declarative reproducible environments <declarative-reproducible-envs>`, we looked at how Nix helps us provide tooling and system libraries for our project.
we looked at how Nix helps us provide tooling and system libraries for our project.
It's also possible to provide an environment with a compiler configured for **cross-compilation It's also possible to provide an environment with a compiler configured for **cross-compilation to static binaries using musl**.
to static binaries using musl**.
Given we have a `shell.nix`: Given we have a `shell.nix`:
@ -311,18 +296,12 @@ hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically link
## Next steps ## Next steps
- The [official binary cache](https://cache.nixos.org) has very limited number of binaries - The [official binary cache](https://cache.nixos.org) has a limited number of binaries for packages that are cross compiled, so to save time recompiling, configure {ref}`a binary cache and CI (GitHub Actions and Cachix) <github-actions>`.
for packages that are cross compiled, so to save time recompiling, configure
{ref}`a binary cache and CI (GitHub Actions and Cachix) <github-actions>`.
- While many compilers in nixpkgs support cross compilation, - While many compilers in Nixpkgs support cross compilation, not all of them do.
not all of them do.
On top of that, supporting cross compilation is not trivial Additionally, supporting cross compilation is not trivial work and due to many possible combinations of what would need to be tested, some packages might not build.
work and due to many possible combinations of what would
need to be tested, some packages might not build.
[A detailed explanation how of cross compilation is implemented in Nix](https://nixos.org/manual/nixpkgs/stable/#chap-cross) can help with fixing those issues. [A detailed explanation how of cross compilation is implemented in Nix](https://nixos.org/manual/nixpkgs/stable/#chap-cross) can help with fixing those issues.
- The Nix community has a [dedicated Matrix room](https://matrix.to/#/#cross-compiling:nixos.org) - The Nix community has a [dedicated Matrix room](https://matrix.to/#/#cross-compiling:nixos.org) for help with cross compiling.
for help around cross compiling.