| 
		
			All checks were successful
		
		
	 / Link Farm (push) Successful in 16s / Individual Build (cross aarch64-linux) (push) Successful in 13s / Individual Build (cross riscv64-linux) (push) Successful in 16s / Individual Build (cross x86_64-linux) (push) Successful in 15s / Individual Build (emulated aarch64-linux) (push) Successful in 14s / Individual Build (emulated x86_64-linux) (push) Successful in 14s This build takes too long | ||
|---|---|---|
| .forgejo/workflows | ||
| .gitignore | ||
| ci.nix | ||
| cross.nix | ||
| emulated.nix | ||
| main.cpp | ||
| meson.build | ||
| package.nix | ||
| README.md | ||
Cross Compilation
In principle, there are two ways:
- Real cross compilation with a cross compiler (e.g. by using pkgsCross).
- Emulating user-space with qemu-user. Not technically cross compilation, but in the end a binary for a foreign architecture is output.
Basics
Cross Compilation
Getting a cross toolchain is as simple as
import <nixpkgs> { crossSystem = "aarch64-linux" }.
Note that there is an older mechanism that uses
pkgs.pkgsCross.aarch64-multiplatform. Internally it uses a internal function
nixpkgsFun that allows to pass additional arguments to the current nixpkgs
instance (it is in fact just passing crossSystem). The naming of the different
platforms is a bit random, though. Also, it uses a the file
<nixpkgs/lib/system/examples.nix> for predefined platforms. For more details
about the “clean up” of the cross toolchain, see
nixpkgs#34274.
The crossSystem argument originally specified a attrset which was quite
complex. However, nowadays there is the
elaborate function
in between. This function takes a string (nix two tuple like aarch64-linux or
a generic LLVM four tuple of the form <arch>-<os>-<vendor>-<abi>) and
internally constructs the appropriate attrset.
Emulation
Instead of using a cross compiler, one can also emulate the compilation with
qemu-user. This just runs the normal user space environment of the target
system and emulates it.
This is as easy as using import <nixpkgs> { system = "aarch64-linux" }.
The advantage is that there are no cross-compilation specifics (e.g. bugs in the build scripts of the packages). The disadvantage is that it is quite slow.
To set up binfmt with qemu-user for the targets, add the following fragment to the NixOS configuration:
boot.binfmt.emulatedSystems = [ "aarch64-linux" "riscv64-linux" ];
boot.binfmt.preferStaticEmulators = true;