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

I've been planning to write about building custom ARM toolchains for a while (I used stuff from 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:

  $ apt-get install flex bison libgmp3-dev libmpfr-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
  # Written by Uwe Hermann <>, released as public domain.

  TARGET=arm-elf                         # Or: TARGET=arm-none-eabi
  PREFIX=/tmp/arm-cortex-toolchain       # Install location of your final toolchain
  PARALLEL="-j 2"                        # Or: PARALLEL=""


  export PATH="$PATH:$PREFIX/bin"

  mkdir build

  wget -c$BINUTILS.tar.bz2
  tar xfvj $BINUTILS.tar.bz2
  cd build
  ../$BINUTILS/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib \
    --with-gnu-as --with-gnu-ld --disable-nls
  make $PARALLEL
  make install
  cd ..
  rm -rf build/* $BINUTILS $BINUTILS.tar.bz2

  wget -c$GCC/$GCC.tar.bz2
  tar xfvj $GCC.tar.bz2
  cd build
  ../$GCC/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib \
    --enable-languages="c" --with-newlib --without-headers --disable-shared --with-gnu-as --with-gnu-ld
  make $PARALLEL all-gcc
  make install-gcc
  cd ..
  rm -rf build/* $GCC.tar.bz2

  wget -c$NEWLIB.tar.gz
  tar xfvz $NEWLIB.tar.gz
  cd build
  ../$NEWLIB/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib \
    --with-gnu-as --with-gnu-ld --disable-nls
  make $PARALLEL
  make install
  cd ..
  rm -rf build/* $NEWLIB $NEWLIB.tar.gz

  # Yes, you need to build gcc again!
  cd build
  ../$GCC/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib \
    --enable-languages="c,c++" --with-newlib --disable-shared --with-gnu-as --with-gnu-ld
  make $PARALLEL
  make install
  cd ..
  rm -rf build/* $GCC

  wget -c$GDB.tar.bz2
  tar xfvj $GDB.tar.bz2
  cd build
  ../$GDB/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib
  make $PARALLEL
  make install
  cd ..
  rm -rf build $GDB $GDB.tar.bz2

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?

How to use the full size of your (x)term when connecting to some other box serially with minicom

minicom terminal size 1

Just as a reminder for myself, as I'll probably need this more often in the future (and maybe it's helpful for others):

Per default, if you use a big xterm (232x74 in my case) where you start minicom, the $COLUMNS and $LINES environment variables will be 80x24 nevertheless, and those applications which honor them (vim, for example) will be too small and not use the full xterm size of 232x74.

  $ minicom
  $ echo $COLUMNS; echo $LINES

minicom terminal size 2

You can fix that like this:

  $ eval `resize`
  $ echo $COLUMNS; echo $LINES

After you do eval `resize` the variables are updated and vim will use the full xterm size. That's all.