Cross Compiling using Multi-Arch
- Preparing multiarch chroot
- Manually preparing multiarch chroot
- Multiarch cross-building requirements
- Crossbuilding requirements
- Cross Compiling examples
- Steps to proceed from here
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 http://ppa.launchpad.net/linaro-foundations/cross-build-tools/ubuntu 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 http://archive.ubuntu.com/ubuntu/
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:
to allow your username to run builds, and
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] http://archive.ubuntu.com/ubuntu precise main universe deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports precise main universe deb-src http://archive.ubuntu.com/ubuntu 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 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 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 emdebian.org: 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.
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.
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/
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:
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-* dpkg-checkbuilddeps
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
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)