Guidelines for cross-build friendly packages

This page describes good (and bad) practice in packaging (and upstream code) with respect to cross-building Debian-based packages. Little of this is yet mandated by policy, but some is and more will be in the future.

There are often lots of ways of 'fixing' a cross-build problem, but unless you are an expert in the area it will not be clear what the implications of using one method over another are. This page endeavours to document standard guidelines so that packagers can use it as a reference, and Debian and derivatives can develop policy in this area.


This somewhat confusing terminology is GNU's fault.


dpkg-architecture is responsible for translating between triplets, Debian architecture names and multiarch paths. This provides a consistent interface and namespace.

cross-building is defined as BUILD != HOST. more explicitly in debian.rules:

  native build

We cannot run tests to determine aspects of the host machine which will be different on the build machine.

Classic cross-compiling assumes never running any host architecture binaries, and this remains good policy, but we often have QEMU or similar emulation available these days so it makes sense to control this separately where we can. In practice this means running tests, which should be controlled with DEB_BUILD_OPTS=nocheck rather than 'are we cross-compiling or not'. Cross-build tools will set 'nocheck' by default, but it can be enabled when approapriate.

When cross-building the build must select the correct tools who's output varies with architecture. This is usually done with an explicit GNU triplet prefix (arm-linux-gnueabi- ia64-linux-gnu-). This applies to the following tools: gcc, g++, binutils (ld, as, strip, ar, readelf etc), pkg-config

Build environment

Various things need to be set in the environment for cross-builds to work correctly.

Below is a list of what is set by various tools, however the interface to package building is still defined as the debian rules targets and your rules file should not rely on any outside environment setting.

The recommended way to set the architecture variables provided by dpkg-architecture is to include this snippet provided by dpkg-dev:

include /usr/share/dpkg/

This is available from dpkg-dev 1.16.1 onwards, and will not overwrite any previously-supplied values.

Environment set by build tools


all the dpkg-architecture variables:


(it also sets some FAKEROOT stuff that we don't care about here, and sanitises a load of stuff out of your normal environment)


sbuild duses dpkg-buildpackage so sets the same things as that, and:

CONFIG_SITE=/etc/dpkg-cross/cross-config.$DEB_HOST_ARCH  (for autoconf cache settings provided by dpkg-cross)

anything else configured to be set in build environment


xdeb uses dpkg-buildpackage so sets the same things as that, and:

CONFIG_SITE=/etc/dpkg-cross/cross-config.$DEB_HOST_ARCH  (for autoconf cache settings provided by dpkg-cross)


Make sets some things itself too. Some of them not very helpfully, like the implicit $(CC)=cc

Setting correct compiler

Simply hardcoding 'gcc' will not allow cross-building, and is arguably wrong for other reasons (like using llvm/clang instead)

Normally you want to set gcc for native builds and $(DEB_HOST_GNU_TYPE)-gcc for cross-builds. Sadly we can't just set $(DEB_HOST_GNU_TYPE)-gcc always because that doesn't work natively

So normally people do this:


But it should also be possible to override the compiler for the build from the environment so that for example LLVM test builds or strangly-named external toolchains can be used.

Unfortunately make always sets $(CC) (to 'cc') so you can't just test if it is already set, and set it if not.

This state can be detected with $(origin CC) see

This is a good way to set CC in a bash script: : ${CC=gcc}  which means if $CC is not aleady set, set it to 'gcc', otherwise use the existing value. The ':' is the 'null command' and stops the value being executed.

In Make use: CC ?= gcc instead of CC = gcc so that previously-set values show through.

Running/skipping tests

Normally you don't want to run tests when cross-building.


However here are packages where the tests make sense, and they can be done using qemu so the responsibility of packagers is just to honour this variable.

Where build profiles are enabled (DebianBootstrap) having a profile for 'check' is useful to annotate build-dependencies which are only needed for checks/tests.

Autoconf configure tests

autoconf will not do tests that need a program to be run when in 'cross-compiling' mode. To get the results that would be missing we can use the config.cache mechanism to supply pre-seeded answers. These can be architecture-specific answers, or generic 'Debian' answers. In rare cases you may need to change them for your own use-case.

These autoconf cache files are managed by the dpkg-cross package, which contains a set of files in /etc/dpkg-cross/ to pre-seed the answers. cross-config.<arch> contains the architecture-specific stuff (anything depending on size of variables, lengths of pointers, or peculiarities of this arch's glibc implementation). cross-config.cache contains the architecture-independent stuff.

All you need to do in your package to enable this mechanism and use the default settings is to set the environment variable CONFIG_SITE=/etc/dpkg-cross/cross-config.$DEB_HOST_ARCH e.g. /etc/dpkg-cross/cross-config.armel

If you need a special package-specific variable then you should set PACKAGE=<packagename> to match up with a stanza in one of the config files. This is to avoid clashes if two different packages need a variable set in a different way.


* will the nocheck stuff ever be part of the build system, I think it should be, (maybe setting an additional variable if it does so), this way it would be smarter, for example if we use cross-build to orchestrate multilib, or building with qemu--and still run tests.--scientes