Cross Compiling using Multi-Arch

This page details what is required to do multiarch crossbuilding. If you just want to use it then read 'Preparing multiarch chroot'. The building itself is trivial (sbuild does all the work), the intial chroot setup is most of it. You can do cross-builds without setting up a chroot, but it is not recommended because it puts a lot of guff in your system and mulitarch problems are much more likely on a more fully-populated system.

Preparing multiarch chroot

There is now a helper script to do the work dsescribed below (in xbuilder 0.8) so if you just want to make a cross-build chroot and use it this is the way to do it. This currently assumes Ubuntu, and would need some minor adjustements for Debian (changing the /etc/apt/sources in the chroot because of the different archive layout).

Install xbuilder 0.8 from the Linaro cross-tools PPA

apt-add-repository ppa:linaro-foundations/cross-build-tools
apt-get update
apt-get install xbuilder

Setup the chroot

xbuild-chroot-setup precise /srv/chroots/precise-cross

You can optionally specify a mirror with --mirror, and to set up qemu in the chroot using --with-qemu

xbuild-chroot-setup precise /srv/chroots/precise-cross --with-qemu --mirror=http://localhost:3142/ubuntu

That's it. Easy peasy.

Do builds in the chroot created with:

sbuild --host=<arch> -d <suite> -c <suite>-<build-arch>-sbuild <package>


sbuild --host=armhf -d precise -c precise-amd64-sbuild <package>

(If you don't have lots of chroots already then you can skip the -c and sbuild will probably pick the right one)

Note that the chroots are set up with sbuild-createchroot so if you've already used that for this particular suite then you'll end up with two named the same and schroot will sulk. Just rename one in /etc/schroot/chroot.d/<suite>-amd64-sbuild-xxxxx (The name is the bit in square brackets on the top lione of the config).

Manually preparing multiarch chroot

Below full details are given of what is actually required. Here is the short version of what to type if you just want to set up a suitable environment and do manual builds. See CrossBuildd for setting up an automated system.

add-apt-repository deb precise main
apt-get update
apt-get install sbuild schroot qemu-user-static

For testing, you will want a precise or later (ubuntu) or wheezy or later (debian) chroot. Raring works best at the moment (May 2013).

sbuild-createchroot --components=main,universe --make-sbuild-tarball=/srv/chroots/precise-cross-buildd.tgz precise /srv/chroots/precise

will create a base chroot and pack it up into /srv/chroots/precise-cross-buildd.tgz

If you've not set up sbuild on this machine before you'll need to:

sbuild-adduser <your-username>

to allow your username to run builds, and

sbuild-update --keygen

is needed to install build-deps in the chroot

Optionally make the chroot an lvm or btrfs snapshot (edit /etc/schroot/schroot.d/ configs to change defaults).

Set up the /etc/apt/sources.list :

As there is no sbuild-add-apt-repository command you have to do it the manual way

Install an editor such as vi or nano for editing the sources.list

sbuild-apt precise apt-get install vim.tiny

Change into the chroot as root, using sbuild-shell which saves your changes:

sudo sbuild-shell precise

Then use vi to make /etc/apt/sources.list look like this (sbuild-add-apt-repository would be handy...) Assuming you are operating on an amd64 machine. (change amd64->i386 if not)

deb [arch=amd64] precise main universe
deb [arch=armhf] precise main universe
deb-src precise main universe

And exit the chroot (ctrl-D or exit)

Run builds by downloading the source, cd-ing into it and doing

sbuild  --host=armhf -d precise 

or just download the source and do

sbuild  --host=armhf -d precise sourcepackage_ver.dsc

add --verbose and --debug for more info and what's going on.

Multiarch cross-building requirements

Here are the details of what goes on behind the scenes so that you can use it or set it up manually, or provide support in other build tools.

  • multiarch-aware dpkg - i.e one that supports the foreign-architecture option

In Ubuntu this is present since natty (v1.16.0) In Debian since v1.16.2

  • multiarch-aware apt (i.e supports -o APT::Architectures)

Available from version 0.8.13 onwards. This is sufficient for use with xdeb, xapt or manual cross-dependency resolution.

To use apt-get build-dep -a effectively you need at least 0.8.16, and preferably 0.9.3

Crossbuilding requirements

Crossbuilding in Debian/Ubuntu assumes the following environment (or will arrange it itself):

  • Cross Toolchain (gcc, g++)
  • cross pkg-config support
  • dpkg-cross to supply autoconf cache variables and cmake config files
  • environment variables set to avoid tests and find local config
  • (initially/optionally) qemu installed so arm build-time binaries run
  • dpkg must be configured for foreign-arch use
  • apt-get build-dep -a<host-arch> should be use to install dependencies

  • dpkg-buildpackage -a<host-arch> should be use to do the build

More detail on these items is given below

Cross toolchain

Cross-toolchain packages vary with target arch, distro and suite. At some point a <triplet>-build-essential package should hide these variations. Until then you need the following:

  • Ubuntu: g++-<triplet>, libc6-dev-<host_arch>-cross

  • Debian: Packages from g++-<triplet>, linux-libc-dev-<host_arch>-cross

Cross pkg-config support

  • In Ubuntu precise: install pkg-config-<triplet>

  • Everywhere else: check /usr/share/pkg-config-crosswrapper exists and create symlink called /usr/bin/<triplet>-pkg-config to it.

dpkg-cross support


apt-get install dpkg-cross

A few default system-wide cache variables (like 'sizeof's) are in the package. Others should be added in /etc/dpkg-cross/cross-config.d/<packagename> and shipped as part of the package.

Environment variables

These variables should be set before doing the build:


We don't want tests to be run as they either won't work or will take forever, or both.


This is necessary for dpkg-cross's autoconf cache vars to be found. (Possibly dpkg-buildpackage -a should do this for you, but it doesn't currently)

Adding qemu support

This is an interim measure - a properly cross-ready package shouldn't be trying to run host_arch binaries. However there are things that are known to need this and using qemu where available is convenient.

The outside system needs the binfmt support. The chroot needs the static qemu binary. schroot should provide functionality to do this for you, but it's not yet available in a released package yet. So:

apt-get install qemu-user-static
cp /usr/bin/qemu-<host_arch>-static <chroot>/usr/bin/

Configuring dpkg

The multiarch implementation has changed over time so precise is a special case.

The standard syntax is:

dpkg --add-architecture <host_arch>

On Ubuntu precise only, the syntax is:

dpkg --add-foreign-architecture <host_arch>

Installing cross-build deps

This is the least well-tested and most problematic area.

We don't want recommends or suggests, and we don't want builds stalled by debconf questions:

In apt.conf.d/10local:

APT::Install-Recommends "0";
APT::Install-Suggests "0";

It should be as simple as:

DEBIAN_FRONTEND=noninteractive apt-get build-dep -a <host_arch> build-dep -yf <package>

This only works at all well with apt later than 0.9.6, or the apt patch mentioned in the section above. Depended-on packages need appropriate multiarch markings in order for apt to do the right thing, which is why newer releases work much better in practice.

Running the build

CONFIG_SITE=/etc/dpkg-cross/cross-config.<host_arch>  DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -a<host_arch> -b -uc -us --preserve-env <package>

Cross Compiling examples

First cross-compile example!

apt-get source hello-debhelper
apt-get install debhelper
cd hello-debhelper-*
dpkg-buildpackage -aarmhf

Now that was easy, as hello-debhelper no build-dependencies on shared libraries. Actually we didn't even use multiarch at all.

Lets take a more complex build-dependency scenario:

apt-get source ccache
cd ccache-*

Since we don't have cross-arch build-dependency satisfying (yet), you need do such satisfying by hand.

We see three missing build-deps: autotools-dev, zlib1g-dev, debhelper.

The IDEA is that we should install "Multi-Arch: foreign" packages as host arch, and Multi-Arch: same" as target arch. The idea breaks down, because most -dev packages are not Multi-Arch: same (yet?).

But to emulate the idea, we:

apt-get install autotools-dev debhelper zlib1g-dev:armhf

If it fails, it is probably because glibc in oneiric is not in sync on armhf/x86.

With older, or non-debian cross-toolchins, the compiler still searches the old cross-compile directories (usr/arm-linux-gnueabi(hf)/ ) instead of multiarch directories. If you have this problem you will need to manage it by hand:

export DEB_LDFLAGS_APPEND="-L/usr/lib/arm-linux-gnueabi -L/lib/arm-linux-gnueabi -L/usr/lib -Wl,-rpath-link=/usr/lib/arm-linux-gnueabi:/lib/arm-linux-gnueabi:/usr/lib"

Don't forget to set the autoconf cache location to avoid runtime tests or incorrect configs

export CONFIG_SITE=/etc/dpkg-cross/cross-config.armel

And finally execute the build in the ccache source directory:

dpkg-buildpackage -aarmel --preserve-env

Great, first crossbuild with multiarch!

Steps to proceed from here

  • Make lib*-dev packages Multi-Arch: same
    • Else build dependency resolver cannot know if host or build version of -dev package and library should be installed
  • Make cross-gcc use multiarch paths
    • As consequence, lib-*-armel-cross packages should be replaces by their lib*-dev:armel counterparts?


Platform/DevPlatform/CrossCompile/UsingMultiArch (last modified 2013-05-17 15:58:41)