Text Size

  • Increase
  • Normal
  • Decrease

Current Size: 100%


ARMLinux toolchain

All ARM development needs a working toolchain - either a native one or a cross one. Most people use cross-compilers on x86 machines for performance and convenience reasons. There are plenty of these available and most people don't need to compile their own - they can just install an existing one.

Here I (Wookey) document my own work and others' work of which I am aware on the ARM GNU toolchain front. I welcome input from anyone who can help with corrections, improvements or fixes.

Aleph One Toolchains

Here are the toolchains I've built, along with config, build and version information, and the test status of them.

gcc-arm-linux-3.2.3 - this version produces kernels that work but fails to compile bootldr assembler, giving the following errors:

make: Circular version_2.19.73 <- version_2.19.73 dependency dropped.
-DSPLASH_LINUX -x assembler-with-cpp -c -I.
-I/usr/src/arm/linux-brh/include -I/usr/arm-linux/include
boot-sa1100.s:926:2: warning: #warning DEBUGGING_RESUME_HANG
boot-sa1100.s: Assembler messages:
boot-sa1100.s:134: Error: internal_relocation (type: OFFSET_IMM) not fixed up
boot-sa1100.s:137: Error: internal_relocation (type: OFFSET_IMM) not fixed up
boot-sa1100.s:140: Error: internal_relocation (type: OFFSET_IMM) not fixed up

All the offending lines mention C Labels thus:

ldr     r1,_C_LABEL(SerBase)

The same code compiles quite happily with Phil Blundell's gcc-3.2.3 toolchain from handhelds.org. Can someone enlighten me as to what I should look at to try and try this difference down?

gcc-arm-linux-3.2.3-cvs20030221 - this version works fine with bootldr and C and C++ user-space stuff but generates kernels that hang somewhere near init. reason not yet determined.

Both the above are configured with the following options:

          -v \
--enable-languages=c,c++ \
--prefix=/usr \
--infodir=/usr/share/info \
--mandir=/usr/share/man \
--with-gxx-include-dir=/usr/arm-linux/include/g++ \
--with-gnu-as \
--with-gnu-ld \
--enable-shared \
--enable-threads=posix \
--with-system-zlib \
--enable-long-long \
--enable-nls \
--without-included-gettext \
--enable-checking \
--build=i386-linux \
--host=i386-linux \
#turn off --enable-checking for releases



Both the above are configured with the following options:

    --prefix=/usr \
--build=i386-linux \
--host=i386-linux \


  • HOWTO on building the GNU toolchain as an ARM cross-compiler.
  • Debian cross-compiler draft policy
  • Other toolchains:
    • Erik Mouw's @ linux.arm.org.uk
    • Phil Blundell's @ handhelds.org
    • ....

The story so far

Below here I describe the work I've done on this subject in some detail, as general background, hints for others and documentation when I'm asking for advice.

Personally I've been happily using the emdebian Toolchain prepared by Frank Smith for the last few years. However as a 2.95.3 version it's getting rather long in the tooth, and doesn't support Xscale, which recently became an issue for me. As I'm also supposed to run emdebian.org myself these days I thought that a Debian-compatible updated toolchain would be a good idea. Debian is moving to GCC 3 during the first half of 2003 so it all made sense.

There have been significant changes between gcc 2.95 and 3, primiarily in the C++ ABI. Early GCC 3 versions were very broken on ARM, especially for C++ stuff, but things were beginning to shape up in early 2003.

Knowing that various versions of the toolchain have various problems on ARM, and that other people had got stuff working at least for their own purposes, I collected as much wisdom as I could find on the subject in Feb 2003. This was primarily gleaned from the linux-arm mailing list.

The summary was:

Russell King said: These versions of GCC have problems (usually noticable when building kernels)
  • * GCC 2.95.1, 2.95.2: ignores register clobber list in asm().
  • * GCC 3.0, 3.1: general bad code generation..
  • * GCC 3.2.0: incorrect function argument offset calculation..
  • * GCC 3.2.1: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c

gcc 2.95.4 is the last rock-solid for ARM

Erik Andersen said:
I use binutils 2.12.1 with gcc-3.2 and it works for me. There
have been some gcc related kernel problems that rmk has noticed
but for my arm systems this combination works well.

Kentropy said:
gcc-2.95.3 + binutils-2.10.1 = do not support linux-2.4.18-rmk7-pxa3 (Lubbock)
gcc-2.95.3 + binutils-2.11.2 = OK for linux-2.4.18-rmk7-pxa3 (Lubbock)
gcc-2.95.3 + binutils-2.12.91 = get error "internal error earmelf_linux.c 160"

Nicolas Pitre said:
I trust binutils-2.12.1.tar.bz2. Other versions should work as well, but I trust that one at the moment.

Luc De Cock:
I use the cross-3.2 toolchain with kernel 2.4.18-rmk4-pxa2. It contains gcc
3.2, but I don't now the version of the included binutils.
The included shared libs are compatible with those of the familiar
Cross-2.95.3 gave me problems (internal error, ...)

Build scripts

Next I collected the build scripts various people had used to make working systems. The idea was to work out what the 'best' set of options was for something that was as generic as possible but still worked. I collected scripts from Erik Mouw, Erik Anderson, Jonathan Marks, and Dominic Duval.

These people had had success with the following versions of things:

Dominic:  gcc 3.2.1, glibc 2.3.1, binutils, gdb 5.3
Jonathan: gcc 3.2, glibc 2.2.5, binutils 2.12.1
ErikA: gcc 3.2.2 uClibc 0.9.18, binutils
ErikM: gcc 3.2 glibc 2.2.5, binutils 2.13

At the time gcc 3.2.3 was recently out and promised, as a stable release, not to break anything new. It looked reasonably promising as a version that might work generally and work with Xscale. Which binutils version to use seemed to be something there was little agreemnt on , beyond '2.12.1 was good vintage'

All of the above scripts build directly from the base tarballs which mean they use the 2-stage build mechanism of first building a basic compiler without glibc, then building with threads and glibc.

But on Debian it is possible to greatly simply the build process to the normal single-stage build because a glibc for the target architecture already exists and can be downloaded. An infrastructure to take advantage of this fact and make cross-compiler packages from the standard sources has been set up by Hakan Ardo - it's called 'toolchain-source'. Now it turns out there are problems with this approach but we'll get to that later. I decided to try it out as it looked like a good way of making a Debian-compatible cross-compiler with very little pain. I would use this mechanism with the optimal configure options from the various build scripts mentioned above.

Building from toolchain-source

More info coming here soon...

Here are some useful Q&A's from the list which may help answer some of your questions.

I read that the toolchain ( specifically gcc, glibc ) depends on kernel
header files and therefore the tools need to be rebuilt when changing
kernel versions.
My question is : when must tools be rebuilt?

Answer: (from rmk)
Probably never.

The reason glibc needs the kernel header files is that they need some
rudimentary description of the API (like system call numbers, etc).
(The kernel API to user space is fairly fixed, especially in stable
kernel versions. Also, we try to keep the API compatible between the
major releases of stable kernel versions)

The only time that there would be an absolute
requirement to upgrade glibc is when a system call that glibc uses in
the kernel is removed. However, those types of actions typically take
around 3 to 4 years from the initial announcement to happen. (eg,
announced in 2.2, removed in 2.5)

Relations between versions:
seem to believe that there are strong relations between glibc, gcc and
the kernel. This is a falacy. You can compile the kernel with gcc 2.95.3,
glibc with gcc 3.2 and your applications with gcc 2.95.4. Everything
should still work.

However, you can trip over some incompatibilities - eg, when upgrading
from a non-versioned glibc. However, all recent builds should be using
versioned glibc.

There are some dependencies between glibc and gcc which you should bear in mind.

The C++ ABI does change between 2.95.x, 2.96 and 3.0 compilers. Note,
however, that the C++ library is distributed alongside gcc, so the two
should remain in step with each other.

> Does using a cross-compiler affect the inter-dependencies? The
> cross-compiler will include a version of glibc, so would upgrading the
> glibc on the target require upgrading the glibc in the cross-toolchain?

That depends. If both the old and new glibc is using versioned symbols
on the target, then you can upgrade glibc on the target to a newer
version without rebuilding any of the binaries that use it. That's the
point of a versioned symbols in libraries.

You can continue to build your applications against the old glibc, and
everything should be fine.

However, if you build programs against a newer glibc than the one on
the target, you will run into problems; those build programs will be
looking for later-versioned symbols in glibc which may not be there.
However, rather than randomly crashing without any errors, ld-linux.so.2
will tell you there's something wrong almost immediately.

As far as cross-compiler vs compiler, the two should be identical -
they're just built in slightly different ways, which should not affect
the ARM ABI/API. If it does, you've found a compiler bug.

> What about the set of header files when the cross-gcc s built vs the
> header files present in the kernel being built?
When a compiler is building for a non-native target, it must not use any
of the system installed header files to build any of the target files.
If it does, the build is buggy and should be fixed.

This is one reason why the kernel now starts to use -nostdinc and friends;
there was a misconception that the kernel build allows things like
to be included. The use of these compiler flags ensures that
such problems are immediately picked up and rectified when they occur.

Our prices include postage in the UK only.
T: +44 (0)1223 811679 E: info@aleph1.co.uk