Building an ARM cross-toolchain with binutils, gcc, newlib, and gdb from source

Update: Please don't use this script, a fixed and updated version is now maintained in the summon-arm-toolchain git repo. Direct download: summon-arm-toolchain.

I've been planning to write about building custom ARM toolchains for a while (I used stuff from gnuarm.com in the past, but I switched to the lastest and greatest upstream versions at some point). Among other things, recent upstream versions now have ARM Cortex support.

First you will need a few base utilities and libs (this list may not be complete):

  $ apt-get install flex bison libgmp3-dev libmpfr-dev libncurses5-dev libmpc-dev autoconf texinfo build-essential

Then you can use my tiny build-arm-toolchain script, which will download, build, and install the whole toolchain:

  $ cat build-arm-toolchain
  #!/bin/sh
  # Written by Uwe Hermann <uwe@hermann-uwe.de>, released as public domain.
  [...]

Update: Please don't use this script, a fixed and updated version is now maintained in the summon-arm-toolchain git repo. Direct download: summon-arm-toolchain.

The final toolchain is located in /tmp/arm-cortex-toolchain per default, and is ca. 170 MB in size. I explicitly created the build script in such a way that it minimizes the amount of disk space used during the build (ca. 1.2 GB or so, compared to more than 3 GB in the "naive" approach).

Using the "-j 2" option for make (see script) you can speed up the build quite a bit on multi-core machines (ca. 30 minutes vs. 60 minutes on an AMD X2 dual-core box). Also, you can change the script to build for other target variants if you want to (arm-elf or arm-none-eabi, for example).

Checkout the blog entry How to build arm gnu gcc toolchain for Mac OS X by Piotr Esden-Tempski for similar instructions for Mac OS X users.

Oh, and while I'm at it — does anybody have any idea why there are no pre-built toolchains for embedded (microcontroller) ARM targets in Debian? There are some toolchains for other microcontroller architectures (avr, m68hc1x, h8300, z80) but not too much other stuff. Is there some specific reason for the missing ARM toolchains (other than "nobody cared enough yet")?

I have heard about Emdebian, but from a quick look that seems to be more intended for toolchains with Linux/libc, not for microcontroller firmware (i.e. no MMU, no Linux, no libc etc.), but maybe I'm wrong?

Update: Please don't use this script, a fixed and updated version is now maintained in the summon-arm-toolchain git repo. Direct download: summon-arm-toolchain.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Any idea why my gcc build

Any idea why my gcc build fails with ${PREFIX}/arm-linux/bin/as: unrecognized option '-Qy' ? Does this happen to anyone else?

Do as --help. See if it has

Do as --help. See if it has the -Q option.

THANKS!

That makes perfect sense. I've been working on that all day and tried everything. Little did I know that's what that meant.

Everything works like a charm now. Thanks again!

Check your $PATH

I had the same problem, it turns out, I had "::" in my PATH (for example echo $PATH /usr/local/bin::/usr/bin:/bin). Which is the same as having a "." in your PATH. This breaks GCC compilation at some point, because it tries to run "as" in a directory where it just compiled the assembler for the embedded system. So just check that your PATH is clean, for example by running "export PATH=/usr/local/bin:/usr/bin:/bin" before running Uwe's script.

Use gcc, not cc

I recently had this problem, and it's worth noting that although my path was fine mingw32 uses the 'gcc' command and has no 'cc' equivalent. So if your Makefile explicitly specifies 'cc' as the compiler, then it will run the Linux version rather than the version installed with the cross-compiler. Just change 'cc' to 'gcc' to fix it, if that's your problem.

MinGW

I'm working on including proper MinGW/Windows support in the latest summon-arm-toolchain version from git. The script itself doesn't explicitly call cc or gcc, but you can probably force it via "export CC=gcc" or the like. This will not be necessary anymore soonish, I hope.

PREFIX\include

hi uwe,

i've tried your workflow slightly edited with MinGW/MSYS. all works fine but i get no header files into $PREFIX\include. can you tell me why?
is there a option i've missed or have they copied manually?

best regards

includes

I think that's ok, my $PREFIX/include/ is also empty, all the files are in $PREFIX/arm-elf/include/, $PREFIX/lib/gcc/arm-elf/4.3.3/install-tools/include, and $PREFIX/lib/gcc/arm-elf/4.3.3/include.

Where is the as ?

I generated the toolchain using your method. My target is the LM3S8962 cortex-m3.
When I try to compile a simple example, I get this output:

arm-elf-gcc -c "-DPART_LM3S8962" -mthumb -mcpu=cortex-m3 -MD -std=c99 -o "Debug/hello.o" -I../../StellarisWare "hello.c"
as: unrecognized option '-mcpu=cortex-m3'
make: *** [Debug/hello.o] Error 1

The compiler tries to use native assembler, that cannot understand Arm code.
Your script doesn't generate assembler and linker: in the final installation dir, arm-elf-as and arm-elf-ld are missing, and arm-elf-gcc tries to run as. Is it correct ?

Removing trailing spaces

Hi David,

this is maybe a problem of copy-and-paste. Removing trailing spaces just after the backslash in line 21 (../$(BINUTILS)/configure ... \ ) should fix your problem!

Kudos to Uwe Hermann for providing this nice script!

Regards,
Stefan

It's not a trailing space problem

Hi Stefan,
Thanks for the suggestion, but I downloaded the script using the link, and it has no any line break
Any other idea ?

Can't confirm that here, I

Can't confirm that here, I have arm-elf-as and arm-elf-ld in my bin/ directory. Are you sure you did the export PATH="$PATH:$PREFIX/bin" part as in the script (before running the build of the toolchain) as well as adding the respective bin/ dir to your PATH (e.g. in ~/.bashrc) after the build, so that the tools can be found?

Problem solved

I found the problem:
http://www.mail-archive.com/bug-binutils@gnu.org/msg06475.html
binutils failed compilation of gas, ld was missing because it's compiled after gas.
I'm sorry I didn't check enough my compilation report.

gas not compiling

Hi,
First, thanks for a great script. It has helped a lot.

I am getting the same error compiling using Ubuntu 9.04
I have ensured that libncurses5-dev is installed and that --disable-werror is included for the $GDB build.
I followed the http://www.mail-archive.com/bug-binutils@gnu.org/msg06475.html
which indicates that it was applied to the sources for binutils.

But I still get the error. I am getting the right sources?
Should I specify --disable-werror for all under Ubuntu?

Here is where it fails:

gcc -DHAVE_CONFIG_H -I. -I../../binutils-2.19.1/gas -I. -I. -I../../binutils-2.19.1/gas -I../bfd -I../../binutils-2.19.1/gas/config -I../../binutils-2.19.1/gas/../include -I../../binutils-2.19.1/gas/.. -I../../binutils-2.19.1/gas/../bfd -DLOCALEDIR="\"/tmp/arm-cortex-toolchain/share/locale\"" -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c ../../binutils-2.19.1/gas/config/tc-arm.c
cc1: warnings being treated as errors
../../binutils-2.19.1/gas/config/tc-arm.c: In function ‘s_arm_unwind_save_mmxwr’:
../../binutils-2.19.1/gas/config/tc-arm.c:3459: error: format not a string literal and no format arguments
../../binutils-2.19.1/gas/config/tc-arm.c:3473: error: format not a string literal and no format arguments
../../binutils-2.19.1/gas/config/tc-arm.c: In function ‘s_arm_unwind_save_mmxwcg’:
../../binutils-2.19.1/gas/config/tc-arm.c:3591: error: format not a string literal and no format arguments
../../binutils-2.19.1/gas/config/tc-arm.c:3606: error: format not a string literal and no format arguments
../../binutils-2.19.1/gas/config/tc-arm.c: In function ‘s_arm_unwind_movsp’:
../../binutils-2.19.1/gas/config/tc-arm.c:3712: error: format not a string literal and no format arguments
make[3]: *** [tc-arm.o] Error 1
make[3]: Leaving directory `/home/john/workspace/te/build/gas'

Path exported

Hi Hermann,
I'm using Kubuntu 8.10, I added it to PATH in etc/environment.
Anyway, I'm using your full script, so it's executed by the script at the start.
In your script I changed only the "PREFIX=" line at start, to point at my cortex compiler dir.
The ls of the PREFIX/bin at end of work reported:

arm-elf-addr2line arm-elf-cpp arm-elf-gccbug arm-elf-objdump arm-elf-size
arm-elf-ar arm-elf-g++ arm-elf-gcov arm-elf-ranlib arm-elf-strings
arm-elf-c++ arm-elf-gcc arm-elf-nm arm-elf-readelf arm-elf-strip
arm-elf-c++filt arm-elf-gcc-4.3.3 arm-elf-objcopy arm-elf-run

P.S.: For the same problem, the script fails in compiling arm-elf-gdb.

For the parallel stuff I

For the parallel stuff I use:
PARALLEL=-j`getconf _NPROCESSORS_ONLN`

getconf _NPROCESSORS_ONLN

Nice, thanks!

This looks better to me if

This looks better to me if you have multiple cores and multiple processors and still feel the need for more speed while recompiling... you know you do ;)...

if grep -q "processor" /proc/cpuinfo || grep -q "siblings" /proc/cpuinfo
then
PARALLEL="j "$(($( grep "processor" /proc/cpuinfo | sort -u | wc -l ) * $( grep "siblings" /proc/cpuinfo | tail -1 | cut -d: -f2 )))
else
PARALLEL=""
fi

cpuinfo

Nice, thanks.

Btw, the latest version of this script is available in the summon-arm-toolchain git repo.

Though I guess this stuff is highly Linux-specific (/proc/cpuinfo), won't work on *BSD or Mac OS X or Windows, whereas "-j 2" probably does.

Hi

Hi,

I tried your toolchain to compile a cortex device, beagleboard kernel, i am getting this error:

LD arch/arm/boot/compressed/vmlinux
arm-elf-ld: ERROR: arch/arm/boot/compressed/misc.o uses VFP instructions, whereas arch/arm/boot/compressed/vmlinux does not
arm-elf-ld: failed to merge target specific data of file arch/arm/boot/compressed/misc.o
make[2]: *** [arch/arm/boot/compressed/vmlinux] Error 1
make[1]: *** [arch/arm/boot/compressed/vmlinux] Error 2
make: *** [zImage] Error 2

Best Regards

beagleboard

Not sure this is the correct toolchain for that use-case, you probably need arm-linux-* or similar. Please check beagleboard-specific resources for more info, I don't know too much about that.

I have this problem too,

I have this problem too, both with arm-elf and arm-linux toolchains ( though I'm not explicitely trying to build for Beagle).
I'm quite sure it's not related to arm-elf.