Building the GNU ARM Toolchain

Note: This post serves mainly as a reminder to myself. I did not figure out everything myself and got the original instructions from here (many thanks to Adam Kunen). The steps here aren’t exactly the same, but they’re mostly similar. His posts also contain some explanations for the various configure options as well as a short explanation on the triplet (ie. “arm-none-eabi”).

The goal: To build the GCC toolchain for ARM suitable for bare-metal work, complete with gdb and libc (newlib). At the end of the day I used this to compile the LwIP sample projects (both “standalone” and FreeRTOS versions) for an STM32F4 evaluation board.

These are the versions of the various components I used:

There should be no issues using newer versions of these components.

In this tutorial I’m going to install the tool-chain at ~/arm-none-eabi/ with with the sources in ~/arm-none-eabi-src. Do change this path if you prefer a different location. (On my own machine, I placed it in /opt/arm-none-eabi)

Update (6/9/2013): Some of the configure commands include “–with-cpu=cortex-m4”. This is because I was building for a ARM Cortex-M4 MCU. You should replace this with your target architecture. I had problems with an earlier build when I didn’t add this option in. It turns out that Cortex-M processors are picky about word alignment, and if you don’t configure this in before you build newlib and gcc, the libraries may not respect the word alignments and you may end up with hard faults.

Ok, first we create the directory skeleton:

mkdir arm-none-eabi arm-none-eabi-src
cd arm-none-eabi
mkdir src build

Now, download the the packages and extract them:

cd ~/arm-none-eabi-src/src


tar -xf gcc-4.7.1.tar.bz2
tar -xf binutils-2.22.tar.bz2
tar -xf gdb-7.4.tar.bz2
tar -xf newlib-1.20.0.tar.gz

Build binutils first:

cd ~/arm-none-eabi-src/build
mkdir binutils-2.22
cd binutils-2.22
../../binutils-2.22/configure --target=arm-none-eabi \
  --prefix=~/arm-none-eabi --with-cpu=cortex-m4 \
  --with-no-thumb-interwork --with-mode=thumb
make all install
export PATH="$PATH:~/arm-none-eabi/bin"

At this point you could also put the path “~/arm-none-eabi/bin” into your .bashrc file if you want.

After this, we will do the first part in building gcc.

Note: gcc relies on three bignum libraries: mpfr, mpc, and gmp. You should download the source code for those three libraries, rename them to mpft, mpc, and gmp respectively, and move them inside the gcc source tree. Do not compile these libraries separately.

The steps to build the first stage are:

cd ~/arm-none-eabi-src/build
mkdir gcc-4.7.1
cd gcc-4.7.1
../../src/gcc-4.7.1/configure --target=arm-none-eabi \
  --prefix=~/arm-none-eabi ---with-cpu=cortex-m4 \
  --with-mode=thumb --disable-multilib \
  --with-no-thumb-interwork \
  --enable-languages="c,c++" --with-newlib \
  --with-headers=../../src/newlib-1.20.0/newlib/libc/include \
make all-gcc install-gcc

Here I deviate from Kunen’s tutorial a little. I could not get gcc 4.7.1 to compile without the “–with-system-zlib” flag. (The make process fails somewhere when it tries to do link tests. If anyone can explain why or knows why using the system zlib is disadvantageous, do leave a comment and let me know.)

Okay, now let’s build our newlib libc with our freshly compiled gcc cross compiler:

cd ~/arm-none-eabi-src/build
mkdir newlib-1.20.0
cd newlib-1.20.0
../../src/newlib-1.20.0/configure --target=arm-none-eabi \
  --prefix=~/arm-none-eabi --disable-multilib \
make all install

Here there’s another configuration option which I added which Kunen doesn’t: –disable-newlib-supplied-syscalls. The reason is I want to supply the system call stubs myself so I can have a potentially fully functional stdin, stdout, etc. Also, if you’re using an RTOS, here is where you could make standard libc malloc work with your RTOS’ memory management. Even if you aren’t using an RTOS, supplying appropriate stubs will still give you a fully functional libc.

The catch is you’ll always need supply the system call stubs if you use printf, and friends, or malloc and friends. You can read more about it here and here.

Now, we can complete the gcc build:

cd ~/arm-none-eabi-src/build/gcc-4.7.1
make all install

And the final piece, gdb:

cd ~/arm-none-eabi-src/build
mkdir gdb-7.4
cd gdb-7.4
../../src/gdb-7.4/configure --target=arm-none-eabi \
make all install

Alright! Now put

export PATH="$PATH:~/arm-none-eabi/bin"

in your .bashrc or /etc/environment (if you haven’t already) and you have a fully functional ARM tool-chain suitable for bare-metal work.

8 thoughts on “Building the GNU ARM Toolchain

  1. Zhuo Yuzhen

    Execuse me. When i try to Build binutils, it says

    zhuoyuzhen@ubuntu:~/arm-none-eabi-src/build/binutils-2.22$ make all install
    make: *** No rule to make target `all’. Stop.
    zhuoyuzhen@ubuntu:~/arm-none-eabi-src/build/binutils-2.22$ export PATH=”$PATH:~/arm-none-eabi/bin”^C

    can you help me?

  2. Olivier

    Nice article, thank you. Just a quick note: you assume that some libraries are already installed (namely GMP, MPFR and MPC). On Linux systems, they can be installed using the standard package manager. On FreeBSD systems, you need the additional options “–with-mpc=/usr/local –with-mpfr=/usr/local –with-gmp=/usr/local” due to the layout of the system – beside using gmake instead of make. Just in case another FreeBSD fan hits this page 😉

  3. Gary

    remove the –enable-multilib option and you will not have to specify the –with-system-zlib option. Since multilib is enabled by default, this will not change the actual build process other than to solve the problem you saw. Something about the parsing of the –enable-multilib breaks things so simply not putting on the command line resolves it.


  4. servidores linux

    I savor, cause I discovered just what I used to be having a look for. You’ve ended my four day lengthy hunt! God Bless you man. Have a nice day. Bye


Leave a Reply

Your email address will not be published.