Cross Compiling

Overview

When building packages, it might be necessary to use cross compilation depending on the target architecture. Cross compilation is not necessary if the target architecture can directly run on the host CPU (for example building an x86_64 or x86 package on a x86_64 CPU).

Multiple methods for cross compilation are implemented in pmbootstrap. For all methods except cross-native, a foreign arch chroot (with the target architecture) gets used during the build in addition to the native chroot.

Method

Native

Foreign

Speed

Limitations

QEMU only

x

slow

So slow that it is desirable to
use other methods where possible.

crossdirect
(default)

x

x

medium

Cross compiler runs natively,
everything else goes through QEMU.

cross-native

x

fast

Cannot depend on libraries
(works for kernel, u-boot, etc.).

cross-native2

x

x

fast

Works with e.g. meson build system.
Kernel builds not yet supported.

Methods

QEMU only

Enable this method with options="!pmb:crossdirect" in the APKBUILD.

This method is the most reliable, but also the slowest. We only use it if faster methods don’t work. GTK projects using g-ir-scanner (“Generating […].gir with a custom command”) are currently known to fail with other methods.

Crossdirect

This is the default method.

This method works for almost all packages, and gives a good speed improvement over running everything in QEMU. However only the cross compilers run natively. Linkers and all other commands used during the build still need to run through QEMU and so these are still very slow.

The native chroot gets mounted in the foreign arch chroot at /native. The crossdirect package gets installed into the native chroot and creates wrapper scripts pointing to the cross compilers. When building packages for armv7, the build runs in the foreign chroot and PATH will get prepended with /native/usr/lib/crossdirect/armv7. This leads to invoking the cross compiler from the native chroot, running at native speed, whenever calling the compiler from the foreign arch chroot.

Cross-Native

Enable this method with options="pmb:cross-native" in the APKBUILD.

This method is only supported for packages that do not depend on foreign arch libraries, such bare metal software (kernel, u-boot), firmware packages or the postmarketos-artwork package.

The whole build is done in the native chroot. Environment variables are used to tell abuild that it is a different arch package (CARCH) and to the kernel-style Makefiles that the cross compilers should be used.

Cross-Native2

Enable this method with options="pmb:cross-native2" in the APKBUILD. This is supported since pmbootstrap 3.4, previous versions will ignore this option and use the crossdirect method instead.

Packages from makedepends_host= in the APKBUILD are installed in the native chroot, and packages from makedepends_build= in the foreign chroot. Environment variables are used to run abuild in the native chroot and use its cross compilation features rather than running it and the build system through QEMU. This massively speeds up building when it works.

The foreign chroot is mounted into the native chroot at /sysroot. Most build systems will refer to it as “sysroot”, in abuild it is CBUILDROOT.

Packages have been built successfully with cross-native2 and the following build systems:

  • meson

  • go build

Where possible, we should try to migrate all packages that currently use crossdirect to cross-native2 to make them build faster.

Language-specific

Rust

Rust packages can either be built with QEMU only, or with the crossdirect method. Now that we have cross-native2 it makes more sense to try to get rust support working there as it will be faster and more reliable. Rust support in crossdirect is still experimental. pmaports!4234 (cross/crossdirect: improve rust handling) describes some of the problems with this approach.

CARGO_HOME

If a program needs to download git repositories of dependencies with cargo (ideally they are bundled with the source tarball and don’t need to be downloaded), then these git repositories are cached with pmbootstrap. This works as long as the program does not override CARGO_HOME. GNOME podcasts does this for example, so if building gnome-podcasts from the git repository with pmbootstrap build --src, patch out the override of CARGO_HOME so the dependencies do not get downloaded for every build.

Packaging caveats

  • cargo auditable build is unsupported with crossdirect and falls back to compiling in QEMU. Change it to cargo build to build the package with the native compiler.

  • Running tests doesn’t really work (e.g. when building squeekboard, the tests hang and time out).