Differences between revisions 24 and 25
Revision 24 as of 2012-03-18 20:58:34
Size: 9904
Editor: NeilWilliams
Revision 25 as of 2012-03-18 21:02:29
Size: 10199
Editor: NeilWilliams
Deletions are marked like this. Additions are marked like this.
Line 195: Line 195:
xapt usage (squeeze):
xapt -a armel $LIBRARY

xapt usage (wheezy and unstable):
xapt -a armel -m $LIBRARY

The -m is necessary if pulling in packages from testing or unstable because of the MultiArch changes.

If you are still using Lenny, apt-cross is necessary.

Building a Cross Compiler

This document will help you build Debian packages of a cross-compilation toolchain. It is based on a HOWTO by Josh Triplett, with his kind permission.

Note that most sensible cross-toolchain combinations within Debian are built by the Embedded Debian Project, so you may well just be able to apt-get what you need on their Toolchains page: http://www.emdebian.org/tools/crosstools.html . They also maintain scripts which effectively do what this page describes. Take a look at the 'buildcross' package from Debian experimental, which will build a whole range of toolchains.

Commands you need to run as root assume you have already set up sudo on your system.

We will be building a cross-compiler from the gcc-4.1 package. Specific version numbers for packages are listed as VERSION; substitute the version number of the latest package in unstable (or testing).

Notes for Debian unstable

We build gcc-4.4 whose cross package additionally build-depends on gcc-4.4-source which you henceforth must install.

The package linux-kernel-headers is now called linux-libc-dev instead.

The three packages libc6-dev, libc6, linux-libc-dev have additional dependencies, so you need to get the (native for the target arch) gcc-4.4-base, libc-bin, libc-dev-bin and libgcc2 (libgcc1, libgcc4, whatever your target needs) packages additionally. Now, dpkg-cross refuses to convert those without “any useful files”, so you need to pass the -A option in addition to -b and -a $ARCH.

A bit uglily, you get libgcc2-m68k-cross depending on gcc-4.4-base-m68k-cross from dpkg-cross and later, after compiling, libgcc2-m68k-cross depending on gcc-4.4-m68k-linux-gnu-base. Just remove the dpkg-cross-generated one once you got the new ones.

Build a cross-compilation toolchain

Create a working directory

mkdir -p ~/src/cross-toolchain
cd ~/src/cross-toolchain

Some useful variables

These will be used in the commands in this document. Replace "arm" with the architecture for which you are building a cross-compiler.

unset ARCH      # make sure it’s not exported
ARCH=arm        # set to the value we want to use

Get the source for binutils and GCC

apt-get source binutils gcc-4.1

Install Build-Depends

sudo apt-get build-dep binutils gcc-4.1

Note that gcc-4.1 may have build-dependencies that apt-get can't figure out; this is not a problem, just make sure you install all the ones that apt-get understands. Unfortunately, apt-get build-dep may give an error if such a situation arises; in this case, take the list of packages apt-get provided before giving an error, and install them using "sudo apt-get install pkg1 pkg2 pkg3 ...".

Install fakeroot

fakeroot allows you to build packages without being root.

sudo apt-get install fakeroot

Install dpkg-cross

dpkg-cross adds cross-compilation support to some of the basic Debian package tools. dpkg-cross can also convert packages designed for the target architecture into packages usable for cross-compilation to that architecture.

sudo apt-get install dpkg-cross

Build and install binutils

cd binutils-VERSION
export TARGET=$(dpkg-architecture -a$ARCH -qDEB_HOST_GNU_TYPE 2>/dev/null)
# this is for binutils <= 2.20
#fakeroot debian/rules binary-cross >../binutils.build 2>&1 || echo 'Build error'
# this is for binutils >= 2.21
dpkg-buildpackage -b -uc -us -rfakeroot >../binutils.build 2>&1 || echo 'Build error'
unset TARGET
cd ..
sudo dpkg -i binutils-${TARGET}_VERSION_HOSTARCH.deb

Note: the instructions are not totally correct. For example, with ARCH=amd64 you get TARGET=x86_64-linux-gnu and binutils-x86-64-linux-gnu (replace _ with - simply). For i386, you get TARGET=i486-linux-gnu but you’ll probably want i386-linux-gnu instead.

Convert library packages

You will need cross-compilation packages for various libraries; dpkg-cross can convert native packages for the target architecture into packages usable for cross-compilation. Note that the mirror ftp.us.debian.org only has amd64 and i386 packages, so to build a cross-compilation toolchain for another architecture (e.g. arm), you will have to use a mirror other than ftp.us.debian.org.

wget http://ftp.XX.debian.org/debian/pool/main/e/eglibc/libc6-dev_VERSION_$ARCH.deb
wget http://ftp.XX.debian.org/debian/pool/main/e/eglibc/libc6_VERSION_$ARCH.deb
wget http://ftp.XX.debian.org/debian/pool/main/l/linux-kernel-headers/linux-kernel-headers_VERSION_$ARCH.deb
dpkg-cross -a $ARCH -b l*.deb
sudo dpkg -i l*$ARCH-cross*.deb

It may be needed to download and convert libc-bin and libc-dev-bin packages too, otherwise the packages’ dependencies can maybe not be resolved. Use dpkg-cross -a m68k -A -b l*.deb in that case.

If you have an architecture that needs a libgcc[124] package, such as libgcc2-m68k-cross, installed to build gcc itself, it’s useful to install that from a previous build first (otherwise, convert it now, the same way).

June 2011, it's gotten worse. dpkg-cross -M -b -a m68k -X libc-bin -X libc-dev-bin *_m68k.deb converts the two eglibc packages, even though multiarch, and dropping the above-mentioned dependencies, and the linux-libc-dev package.

Build and install GCC

Now that you have all the necessary prerequisites, you can build a cross-compiling GCC.

cd gcc-VERSION
debian/rules control
dpkg-buildpackage -us -uc -rfakeroot -b > ../gcc.build 2>&1 || echo 'Build error'
cd ..
sudo dpkg -i *-VERSION-$ARCH-linux-gnu*.deb *-$ARCH-cross_VERSION*.deb

If you run into this error, or a similar one…

dh_strip -plibgcc2-m68k-cross --dbg-package=libgcc2-dbg-m68k-cross
objcopy: Unable to recognise the format of the input file `debian/libgcc2-m68k-cross/usr/m68k-linux-gnu/lib/libgcc_s.so.2'
dh_strip: objcopy --only-keep-debug debian/libgcc2-m68k-cross/usr/m68k-linux-gnu/lib/libgcc_s.so.2 debian/libgcc2-dbg-m68k-cross/usr/lib/debug//usr/m68k-linux-gnu/lib/libgcc_s.so.2 returned exit code 1
make[1]: *** [stamps/08-binary-stamp-libgcc] Error 2
make[1]: Leaving directory `/home/tg/X/gcc-4.4-4.4.5'
make: *** [binary] Error 2
dpkg-buildpackage: error: fakeroot debian/rules binary gave error exit status 2

… then this will help:

tg@zigo:~/X/gcc-4.4-4.4.5 $ sudo apt-get install binutils-multiarch
[sudo] password for tg:
Reading package lists... Done
Building dependency tree
Reading state information... Done
Starting 2
The following NEW packages will be installed:
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/2127 kB of archives.
After this operation, 7164 kB of additional disk space will be used.
Selecting previously deselected package binutils-multiarch.
(Reading database ... 32493 files and directories currently installed.)
Unpacking binutils-multiarch (from .../binutils-multiarch_2.21.0.20110216-2_amd64.deb) ...
Adding 'diversion of /usr/bin/nm to /usr/bin/nm.single by binutils-multiarch'
Adding 'diversion of /usr/bin/objdump to /usr/bin/objdump.single by binutils-multiarch'
Adding 'diversion of /usr/bin/objcopy to /usr/bin/objcopy.single by binutils-multiarch'
Adding 'diversion of /usr/bin/strings to /usr/bin/strings.single by binutils-multiarch'
Adding 'diversion of /usr/bin/strip to /usr/bin/strip.single by binutils-multiarch'
Adding 'diversion of /usr/bin/size to /usr/bin/size.single by binutils-multiarch'
Adding 'diversion of /usr/bin/ar to /usr/bin/ar.single by binutils-multiarch'
Adding 'diversion of /usr/bin/ranlib to /usr/bin/ranlib.single by binutils-multiarch'
Adding 'diversion of /usr/bin/addr2line to /usr/bin/addr2line.single by binutils-multiarch'
Adding 'diversion of /usr/bin/gprof to /usr/bin/gprof.single by binutils-multiarch'
Adding 'diversion of /usr/bin/readelf to /usr/bin/readelf.single by binutils-multiarch'
Setting up binutils-multiarch ( ...

Test the cross-compile environment

Test compilation

Create a file "hello.c", containing the following code:

#include <stdio.h>

int main()
    printf("Hello cross-compiling world!\n");
    return 0;

Compile it statically with the new cross-compiler.

$ARCH-linux-gnu-gcc -static hello.c -o hello

Check the binary's type with "file".

file hello

You should see something like:

hello: ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), for GNU/Linux 2.2.0, statically linked, not stripped

for the PowerPC architecture.

Install qemu

qemu is an emulator for various architectures. It supports both whole-system emulation as well as single-program emulation with system-call conversion.

sudo apt-get install qemu

Run the test program with qemu

To run the test program with qemu, just prefix it with "qemu-$ARCH" (assuming of course that your architecture is supported by qemu).

qemu-$ARCH ./hello

You should see:

Hello cross-compiling world!

Get all the libraries you need

apt-cross is in Lenny but no longer in Squeeze. pdebuild-cross in Squeeze contains an early version of xapt or you can use the xapt xapt package from experimental until Squeeze is released.

xapt usage (squeeze):

xapt -a armel $LIBRARY

xapt usage (wheezy and unstable):

xapt -a armel -m $LIBRARY

The -m is necessary if pulling in packages from testing or unstable because of the MultiArch changes.

If you are still using Lenny, apt-cross is necessary.

apt-cross reminders:

apt-get install apt-cross dpkg-cross


apt-cross -a $ARCH -u

Fetch your cross favorite library

apt-cross -a $ARCH -i $LIBRARY