Home

Small reminder for Linux user very keen of embedded system.

We will detail the design of a cross-toolchain "From Scratch".

The purpose of this webpage is to understand the design method of a cross-toolchain of a pedagogical perspective.

 

1°) Obtaining a cross-toolchain for ARM architecture

There are several ways to obtain a cross-toolchain. First, the most tedious requiring one to one to compile the sources is commonly called "From Scratch". Another method, more comfortable, is the one requiring the implementation of a tool to generate a string. There crosstool ( http://www.kegel.com/crosstool/ ) which is obsolete but is still able to produce beautiful though somewhat veillotte chains. Crosstool is replaced by crosstool-ng (ng: New Generation) ( http://crosstool-ng.org ). It is maintained and managed by a French. Its setting is kind of like the nucleus (ncurses menu to the sauce). There are chains of cross-made compilations and downloadable on the website of the German company DENX Software Engineering ( http://www.denx.de/en/News/WebHome ). Finally, there are also tools for creating complete embedded Linux distribution (kernel + file system + toolchain cross) as Buildroot, OpenEmbedded, PTXdist. Disadvantage, in many cases, these chains are specific to cross-compilation tool for creating distribution.

A cross toolchain consists of different elements as follows:
- The file header of a Linux kernel,
- A set of software development tools: binutils (binary utilities),
- A Compiler: GCC,
- A C library: glibc
- For more recent versions of GCC: a set of libraries for scientific computing: MPFR and GMP.

All these elements are vital to achieving a toolchain. Their various combinations can generate a cross-toolchain with the help of a few patches or not at all be compatible with each other. It should be to experiment with different versions of each element before reaching a channel without too much difficulty. The library used in the following examples is glibc. It is mainly used in the Linux world. This library contains the main C library system. Glibc provides a set of routines (opening / - closing file; memory allocation etc ...) necessary for the proper functioning of the system based on GNU Linux kernel. It acts as an interface between the kernel and operating system calls with these systems it provides. However, there are other C library that are much lighter and more suitable for embedded systems, for example, the library uClibc, dietlibc library or library newlib.

2) What you need to know or own

Base for a cross toolchain fully functional, it should obviously have:
- Preferably a fast machine (reduced build time),
- A Linux operating system,
- A GCC compiler,
Whichever method of designing the cross-toolchain, it should also have prior program "autoconf" installed in the host machine. This program is responsible for producing a file (called make) that automates the compilation of all sources of a package. To generate such a file, the "configure" script has the mission to inspect the system to ensure that sources can find all dependencies set on the system to properly compile the sources. It should also clarify some terms passed as parameters to the configure script:
- build : refers to the machine where the source code is compiled,
- host : is the machine where the compiler is running,
- target : is the machine for which code is generated.
In all cases the name of the chain will be final type arm-none-linux-gnueabi . The four values ​​mean:
- arm : information on the processor name. It can be mips, i686, x86_64 etc. ...
- none : provides information on additional information. Sometimes this field does not exist. In the case of its presence, the field type is unknown or none,
- linux : information about the operating system,
- gnueabi : information on the type of libc. There are other gnuabi, gnulibc, uclibc.

3) The common steps of creating a chain

1. Obviously obtaining sources is essential. Downloading them from an official website can be done either by hand (systematic use of the wget command for each package), or automatically by script (this is the case with crosstool-ng and crosstool). You can download the sources from CVS (Concurrent Versions System). The latter is a version control system client-server that allows multiple people to work simultaneously on a single set of files. This method allows for the latest update sources. In our case, since we will work with a little packet of old and whose changes are included in the next higher versions, CVS is not used.

2. The first package to be compiled because the compiler is GCC binutils depends on the tools of it to create executables. Indeed, this is binutils which assembles the object files generated by GCC in an executable image,

3. We need the functions header of the Linux kernel specifically for the ARM architecture. They contain essential functions such as system calls to interact with the kernel. These headers are used to produce the C library (glibc) for ARM,

4. Formal credit We will compile a GCC compiler depleted basic functions. Often called "bootstrap GCC", the compiler is still able to produce a library for ARM using Glibc functions of the kernel headers from the previous step,

5.t We use our "bootstrap GCC" to produce the file header of Glibc,

6, We get a C library function for ARM.

6. We have all the tools to start designing our next GCC compiler for ARM,

4. We compile the GMP and MPFR math libraries for ARM,

9. Finally, we compile the final GCC with previous libraries.

 

4) The alchemy of different versions of components of a cross toolchain

For the generation of a chain "from scratch", you have to hand all the previous steps. Versions of the various components work well with only a few patches:

- The Linux kernel 2.6.28.3 in its version, downloadable from the address http://www.kernel.org/pub/linux/kernel/v2.6/ ,

The other ingredients are downloadable from the address: http://ftp.gnu.org/gnu/ ,

- Binutils in its version 2.20,

- GCC version 4.3.3,

- Glibc in version 2.9,

- Glibc-ports in its version 2.9,

- GMP version 4.3.2,

- MPFR version in 3.0.1:

5) Get a cross-toolchain "From Scratch"

a) Introduction

This procedure is inspired by the book "Pro Linux Embedded Systems" by Gene Sally by Apress. There is also here and there web sites more or less serious that get a toolchain smoothly and without patch. I confess to being very cautious about getting a chain smoothly and without a shadow of one patch. Here is detailed, with patch, all the compiler options and each step is discussed.
The compilation of the chain was performed in a PC which is running a 64 bit Ubuntu 4.11. The elements of the host system interfere little in the construction of the chain, but it should be clarified version of the various components installed:

- Binutils in its version 2.21,

- GCC version 4.5.2,

- Glibc in version 2.13,

- Glibc-ports in the version 2.13,

- GMP version 4.3.2,

- In its MPFR version 3.0.0.

For reasons of convenience, we will use two terminals to generate our cross toolchain. These terminals can be called T1 and T2. Both terminals have similar environment variables. However, the terminal T2 advantage of environment variables to facilitate the compilation. In each terminal, enter the following common environment variables:

export SRCDIR=/root/chaine/sources
This directory home all sources downloaded.

export BUILDDIR=/root/chaine/build
It is in this directory that will compile all source packages.

export TARGETMACH=arm-none-linux-gnueabi
This variable specifies the type of target architecture.

export BUILDMACH=x86_64-pc-linux-gnu
This variable specifies the type of architecture in which the package is compiled.

export INSTALLDIR=/opt/arm
This variable provides information about the folder hosting the cross-toolchain.

export SYSROOTDIR=/opt/arm/sysroot
This variable provides information on the directory hosting the libraries and header files the kernel of the target system.

T2 to add more environment variables as follows:

export CROSS=arm-none-linux-gnueabi
Indicates that we use the variable fields CROSS with arm-none-linux-gnueabi.

export CC=${CROSS}-gcc
Indicates that we use the GCC compiler for the ARM architecture.

export LD=${CROSS}-ld
Indicates that we use the dynamic library of the ARM architecture.

export AS=${CROSS}-as
Indicates that we use the assembler of the ARM architecture.

b) Compilation of Binutils

The first package to be compiled is Binutils. Its compilation is not a problem and is fast. From the terminal T1, let's type the following lines:


mkdir $BUILDDIR/binutils
cd $BUILDDIR/binutils
../../sources/binutils-2.20/configure \
--disable-werror \
--build=$BUILDMACH \
--prefix=$INSTALLDIR \
--with-sysroot=$SYSROOTDIR \
--target=$TARGETMACH
make
make install

-> A few explanations:

Parameters

  Fonction

--disable-werror Disabling "warning": avoid blocking the compilation
--build=$BUILDMACH Architecture of the host PC which is the compilation
--prefix=$INSTALLDIR Home directory of the executable
--with-sysroot=$SYSROOTDIR Home directory of booksellers
--target=$TARGETMACH Target architecture

 

c) kernel header files


Compiling the kernel header files generates an error due to a function name reused by different codes when compiling. Open the file linux-2.6.28.3/script/unifdef.c by an editor like vim. Change the function name by removing the letter "e" of the name of the function getline() in getlin() . You can complete the transaction by directly applying the patch unifdef.c.patch . It simply copy this patch into the directory linux-2.6.28.3/script/ , to go to that directory and apply it by typing: patch < unifdef.c.patch
Now, the compilation and installation is done without hassle.

From the terminal T1, let's type the following lines:


cd $SRCDIR/linux-2.6.28.3
make mrproper
make ARCH=arm kb9202_defconfig
make ARCH=arm headers_check
make ARCH=arm INSTALL_HDR_PATH=$INSTALLDIR/sysroot/usr headers_install

-> A few explanations:

Option ARCH=arm accurate, of course, the type of target architecture. We will use this string for the card (a little older, I admit) KwikByte KB9202C which is, unfortunately, more for sale on the manufacturer's website http://www.kwikbyte.com

That is why we specify its use by the entrance kb9202_defconfig . This file includes all the options for the Linux kernel map. To map a generic ARM: Option integrator_defconfig brings together all the common options of the kernel for all ARM. In the kernel directory linux-2.6.28.3/arch/configs/ , we can see all cards natively taken into account by the kernel.

d) Bootstrap GCC

Before proceeding with the compilation and installation of primer GCC (bootstrap GCC), ensure that the GMP and MPFR math libraries are installed in your Linux system.
The GMP library (download at: http://gmplib.org ), contains arithmetic functions to multi-particulars. It is used mainly in research in cryptography and algebraic. GMP is defined as a Debian / Ubuntu as the package to download / install via the Synaptic package manager. The packages are:
- libgmp3c2 (C library),
- libgmp3-dev (C libraries and C + +),
- lib32gmp3-dev (C libraries and C + + in 32-bit)
- libgmpxx4ldbl (C + + library).

The MPFR library (download at: http://www.mpfr.org ), contains mathematical functions that can perform calculations multi clarification floating point with rounded accurate. It is maintained by Laurent Fousse ( laurent@komite.net ) professor at Grenoble.
The library is downloadable and installable under Debian / Ubuntu, in the form of package via Synaptic:
- libmpfr4 (Main Library)
- libmpfr-dev (header functions needed for compiling)
- lib32mpfr4 (32-bit version)
- lib32mpfr-dev (header functions required to compile in 32-bit version).

From the terminal T1, let's type the following lines:


mkdir $BUILDDIR/amorce-gcc
cd $BUILDDIR/amorce-gcc
../../sources/gcc-4.3.3/configure \
--build=$BUILDMACH \
--host=$BUILDMACH \
--target=$TARGETMACH \
--prefix=$INSTALLDIR \
--without-headers \
--enable-bootstrap \
--enable-languages=c \
--disable-threads \
--enable-__cxa_atexit \
--disable-libmudflap \
--with-gnu-ld \
--with-gnu-as \
--disable-libssp \
--disable-libgomp \
--disable-nls \
--disable-shared

make all-gcc install-gcc

make all-target-libgcc install-target-libgcc

ln -s /opt/arm/lib/gcc/arm-none-linux-gnueabi/4.3.3/libgcc.a \
/opt/arm/lib/gcc/arm-none-linux-gnueabi/4.3.3/libgcc_sh.a

-> A few explanations:

Most settings entered on the command line disable a number of options not required for the design of a standard library.

Parameters Fonction
--without-headers not compile with the headers in comment
--enable-bootstrap mode activation "bootstrap"
--enable-languages=c we compile for the C language and it is also possible to compile the C + +
--disable-threads Disabling include files multithreaded because they have not yet been created for the target architecture. GCC will be able to find information on multi-threaded after the headers are created Glibc library
--enable-__cxa_atexit option describing the implementation of the function atexit ()
--disable-libmudflap library used for complex débuger errors in a userspace program. Not necessary here.
--with-gnu-ld Compiling with native linker
--with-gnu-as Compiling with native assembler
--disable-libssp deactivation of the bookstore that specializes in memory or stack overflow
--disable-libgomp Disabling the OpenMP API specialized in parallel computing
--disable-nls Disabling all local languages ​​except English (POSIX)
--disable-shared native compiler (GCC bootstrap) will not support dynamic libraries time to design the final GCC compiler.


Command
Explanation
make all-gcc install-gcc created the basic compiler and installs it in the directory specified by the variable $ INSTALLDIR
make all-target-libgcc install-target-libgcc Construction of a core library used by GCC to produce code. This library must be built before the final because it depends entirely on it.
ln -s /opt/arm/lib/gcc/arm-none-linux-gnueabi/4.3.3/libgcc.a /opt/arm/lib/gcc/arm-none-linux-gnueabi/4.3.3/libgcc_sh.a By this symbolic link, we force the design of the library of static toolchain.

e) Creation of header files from glibc

These header files are used for defining the functions created by the compiler installed on the target system (our famous Bootstrap GCC).
Before proceeding with the compilation and installation of header files glibc, it should be patched two files. The first patch changes the version number supported by Glibc and is configure.patch (applicable in the root of glibc-2.9).
The second solves a problem with sed backslash and is gen-sorted.awk.patch . (Applicable in the directory glibc-2.9/scripts/ ).

Since the terminal T2, let's type the following lines:

mkdir $BUILDDIR/libc-header
cd $BUILDDIR/libc-header
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" » config.cache
export PATH=$INSTALLDIR/bin:$PATH
../../sources/glibc-2.9/configure \
--build=$BUILDMACH \
--host=$TARGETMACH \
--prefix=$SYSROOTDIR/usr \
--with-headers=$SYSROOTDIR/usr/include \
--config-cache \
--enable-add-ons=glibc-ports-2.9,nptl \
--enable-kernel=2.6.0
make -k install-headers cross_compiling=yes install_root=$SYSROOTDIR
ln -s /opt/arm/lib/gcc/arm-none-linux-gnueabi/4.3.3/libgcc.a \
/opt/arm/lib/gcc/arm-none-linux-gnueabi/4.3.3/libgcc_eh.a


Parameters Fonction
--prefix=$SYSROOTDIR/usr
Home directory of the executable.
--with-headers=$SYSROOTDIR/usr/include
Use of the headers of the core of step c).
--config-cache
Force the executable configure to read the instructions file config.cache
--enable-add-ons=glibc-ports-2.9,nptl
Using the additional library glibc-ports for ARM (our case). Also valid for MIPS and PowerPC.
--enable-kernel=2.6.0 Design of the library to the Linux kernel 2.6.0 kind.

Command Explanation
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" » config.cache
The file config.cache contains these two lines that prevent the execution of code compiled for ARM toolchain with cross installed on the host which is the x86.
make -k install-headers cross_compiling=yes install_root=$SYSROOTDIR The header files are cross-compiled and installed into the $SYSROOTDIR
ln -s /opt/arm/lib/gcc/arm-none-linux-gnueabi/4.3.3/libgcc.a \
/opt/arm/lib/gcc/arm-none-linux-gnueabi/4.3.3/libgcc_eh.a
Same here: by this symbolic link, we force the design of the library of static toolchain.


e) Establishment of Glibc

Well, here we are, we have all the elements in the directory $INSTALLDIR to be able to design our Glibc for ARM. You will notice that the controls are very similar compared to the previous step.
Note: The compilation takes a long time and most of the parameters have already been explained.

Since the terminal T2, let's type the following lines:

mkdir $BUILDDIR/glibc
cd $BUILDDIR/glibc
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" » config.cache
../../sources/glibc-2.9/configure \
--build=$BUILDMACH \
--host=$TARGETMACH \
--prefix=/usr \
--with-headers=$SYSROOTDIR/usr/include \
--config-cache \
--enable-add-ons=glibc-ports-2.9,nptl \
--enable-kernel=2.6.0
make -k install-headers cross_compiling=yes install_root=$SYSROOTDIR
make
make install_root=$SYSROOTDIR install


f) Creation of the GCC compiler for ARM

The GCC compiler generated after this step, is able to compile code static. You can stop after this step if you develop applications using extensions static libraries.

From the terminal T1, let's type the following lines:

mkdir $BUILDDIR/gcc
cd $BUILDDIR/gcc
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" » config.cache
export CC=gcc
../../sources/gcc-4.3.3/configure \
--build=$BUILDMACH \
--target=$TARGETMACH \
--prefix=$INSTALLDIR \
--with-sysroot=$SYSROOTDIR \
--enable-languages=c \
--with-gnu-as \
--with-gnu-ld \
--disable-multilib \
--with-float=soft \
--disable-sjlj-exceptions \
--disable-nls \
--enable-threads=posix \
--enable-long-longx
make all-gcc
make install-gcc


Parameters Fonction
export CC=gcc The environment variable forces the compiler for ARM GCC compiler of the host.
--disable-multilib
Different variants for different library arhitecture different is not designed.
--with-float=soft Support for floating point numbers emulated by the software because the ARM have no FPU (Floating Point Unit)
--disable-sjlj-exceptions
Exceptions specific to C + +, they should be seen off our string only supports C.
--enable-threads=posix
Threads are POSIX format
--enable-long-longx C, support for long integers

g) Cross-compiling bibilothèques GMP and MPFR

Add functionality to our final GCC by implementing special libraries for multiprecision GMP and MPFR. Prior to cross-compile GMP (GMP is compiled first because MPFR depends on it), it is necessary to install the package m4 is a macro processing language (maintained by Santiago Vila at sanvila@debian.org) . GMP and MPFR libraries to compile statically with the previous CCG. They will move into the directory /opt/arm/lib

Since the terminal T2, let's type the following lines:

mkdir $BUILDDIR/gmp
cd $BUILDDIR/gmp
export CFLAGS=-static
../../sources/gmp-4.3.2/configure \
--build=$BUILDMACH \
--host=$TARGETMACH \
--prefix=$INSTALLDIR \
--disable-shared
make
make install


Since the terminal T2, let's type the following lines:

mkdir $BUILDDIR/mpfr
cd $BUILDDIR/mpfr
../../sources/mpfr-3.0.1/configure \
--build=$BUILDMACH \
--host=$TARGETMACH \
--prefix=$INSTALLDIR \
--with-gmp=$INSTALLDIR
make
make install


h) Creating final GCC compiler

We have all the elements to finalize the design of the GCC compiler. The toolchain is obitent in the cross compiling with the compiler of the host (where the line export CC=gcc ). This is a rather long operation.
The arguments passed are the same as f) with some exceptions: support for libraries and compiler previous final supporting dynamic compilation.

From the terminal T1, let's type the following lines:

mkdir $BUILDDIR/gcc-final
cd $BUILDDIR/gcc-final
export CC=gcc
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" » config.cache
../../sources/gcc-4.3.3/configure \
--build=$BUILDMACH \
--target=$TARGETMACH \
--prefix=$INSTALLDIR \
--with-sysroot=$SYSROOTDIR \
--enable-languages=c \
--with-gnu-ld \
--with-gnu-as \
--disable-multilib \
--with-float=soft \
--disable-sjlj-exceptions \
--disable-nls \
--enable-threads=posix \
--disable-libmudflap \
--disable-libssp \
--enable-long=longx \
--with-shared \
--with-gmp=$INSTALLDIR \
--with-mpfr=$INSTALLDIR
make
make install


The final library of GCC is in the directory: /opt/arm/arm-none-linux-gnueabi/lib . The cross toolchain is in the directory /opt/arm/bin . In the terminal T1, we can add the executables of cross-toolchain in the environment variable PATH by typing: export PATH=$INSTALLDIR/bin:$PATH
By typing the first letters of executable arm and pressing the tab key, we now have direct access to executables.

6) Test of the cross-toolchain "From Scratch"

Do a test build with our newly installed chain. We will compile the program celebrates Helloworld that just prints a terminal in the message "Hello World".
In compiling the program by:

arm-none-linux-gnueabi-gcc -o helloworld helloworld.c

We can check the file type compiled using the command line:
file helloworld

gives:

helloworld: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, not stripped

Well, this little test tells us that the executable is generated for the ARM architecture. You diposez now a beautiful cross-toolchain for ARM made for yourself!


Page updated on 06/04/2012