Cross-building Ubuntu packages

Cross-building (or cross-compiling) is not a new science. The GNU toolchain has supported it for many years; quite a number of packages are either simple enough that it is not a problem or have gained explicit support for it at some point; and other projects such as OpenEmbedded, Scratchbox, and Gentoo specialise in it. But, traditionally, with some special-purpose exceptions such as Emdebian, Debian and Ubuntu packages have always been built natively, that is, built on the architecture they're being built for. This may have been under full-system emulation on a faster system for performance's sake, but it still essentially counted as native. This is still the case for all our production builds, and will probably remain that way for quite some time to come.

However, multiarch has changed the landscape. Rather than needing to disassemble and reassemble packages to move their libraries around in order to have enough cross-library support to build non-trivial packages, modern library packages are now installed to non-conflicting paths such that in many cases it is now possible to install stock library packages directly for more than one architecture at once. With a few adjustments this has allowed us to cross-build many packages with the equivalent of debuild -aarmhf -B. In many cases (e.g. reasonably simple packages using the GNU autotools and debhelper 9) packages require no modifications at all to cross-build cleanly.

An automatic cross-builder is now in operation for all of raring main to armhf (thanks to Wookey for previous incarnations of this).

Why do we care?

Once the number of packages that cross-build passes some tipping point, it becomes reasonable to use it more widely. People expect that Ubuntu packages will natively build, and are surprised when they fail; at the moment, the expectation is that packages will fail to cross-build, so it is probably not worth the time to try to reproduce a build failure under cross-building even if the build itself would be faster. However, at the time of writing (December 2012) we are at the point where 30% of main can be cross-built. We have a chance to normalise cross-building and make it widely useful, which in turn will make life easier for people who can't do without it (such as people attempting to bootstrap new architectures).

There is a good reason to care about much more than the base system. Developers building for resource-constrained architectures would be well-served by being able to run at least experimental builds on their fast development systems instead. This use case implies having multiarch sufficiently far advanced to cope with all the build-dependencies of packages quite a long way up the software stack, and figuring out the standard patterns required to cross-build using all the relevant build systems. Dealing with this is a large proportion of the work (and definitely of the hard thinking!) required to cross-build the archive. Furthermore, the more packages we fix to support cross-building, the more patterns we can figure out and automate, and the more the remaining manual steps become standard practice in new packages.

Out of scope (at least for now)

  • Production builds, including anything in Launchpad
  • Significant backports to stable releases (some things will work, and we might consider the odd high-value and non-invasive SRU, but in general you get what you're given there)

Local setup

These instructions are aimed at users of saucy or newer. Cross-building is still under rapid enough development that you're best advised to use current versions of everything, and in general the development series should be stable enough for daily use by developers.

You must have sbuild 0.64.0-1 or newer (pbuilder is not supported for this).

You must have ubuntu-dev-tools 0.146 or newer.

To create a chroot suitable for cross-building:

  • mk-sbuild --target=armhf trusty

If this is the first time you have used sbuild on this machine

  • sbuild-update --keygen

To attempt to cross-build a package (you may want to run this in a scratch directory, and use the -n option if you don't want to save the build log):

  • sbuild --build=amd64 --host=armhf -d trusty foo.dsc

The auto-cross-builder runs in a fairly strict mode: in particular, it does not have qemu-user-static installed in either the host filesystem or the build chroots (previous incarnations did, but that is less useful for porting to new architectures), and it does not have binutils-multiarch installed in the build chroots (which would save having to worry about things like using the correct ld, strip, etc., but can mask real problems). To debug auto-cross-builder failures, try to match this configuration as closely as you can.

(Older and more manual instructions)

The Debian wiki has some advice on fixing packages:

Please make sure that any cross-building fixes you upload to Ubuntu that also apply to Debian are forwarded to the Debian BTS. Use these pseudo-headers in your report:

Usertags: cross

Known large-scale problems

  • Perl multiarch support (in progress)

  • gobject-introspection cross support
    • One possible way to do this is to move all the size/alignment checks to configure time (Autoconf has sufficient magic to be able to test these when cross-compiling) and build "gobject-introspection-HOST" packages, akin to "pkg-config-HOST". This would be aided by sbuild/dpkg-checkbuilddeps changes to automatically add host versions of certain build-dependencies.
  • Qt cross/multiarch support

CrossBuilding (last edited 2014-06-11 09:33:38 by seb128)