Cross Compiling Tool Chains
Toolchain: A Toolchain is a compiler and set of development tools that enables the developers to produce a kernel, system software and application software for a specific targeted hardware.
There are two types Toolchain.
There are two types Toolchain.
- Native Toolchain
- Cross Compile Toolchain
Native Toolchain
The native toolchain runs on your workstation and generates code for your workstation, for example x86 desktop machines. The usual development tools available on a GNU/Linux workstation are native toolchains. Cross Compile Toolchain
The cross compiling toolchain will run on your workstation but it will generate source code for your target board (according to your target processor architecture.). For embedded system development we cannot use the native toolchain, because the target is little different in terms of architecture, storage and memory.
- The target is too restricted in terms of storage and memory.
- The target is very slow compared to your work station.
- We don’t want to install all development tools on your target board because restricted memory and other peripherals.
The three machines must be distinguished when discussing toolchain creation.
- The build machine where the toolchain is built.
- The host machine where the toolchain will be executed.
- The target machines where the binaries are created by the toolchains are executed.
Figure1: Toolchains
Components inside the Toolchain:
Figure2: Components of Cross Compilation toolchain
Binutils
Binutils is a set of tools to generate and manipulate binaries for a given architecture. This provides the GNU assembler, a linker/loader and many other utilities used for manipulating executable, constructing and optimizing libraries and other compilation related tasks.
- “as” the assembler generates binary code from assembler source code.
- “ld” linker/loader which is used to link or load required code at runtime.
- The analyzing tools which are used for analyzing the code are “objdump”, “size”, “readelf” and etc.
- “ar”, “ranlib” to generate .a archive files used for libraries.
- “strip” is used for reduce the code size by removing useless parts in binaries.
Kernel headers
The C library and compiled programs needs to interact with the kernel, therefore compiling C library kernel headers and many other applications also require them. For example to get available systems calls and their numbers, data structures, etc. Available in include/ directory, , .
- System call numbers in
#define __NR_exit
1
#define __NR_fork
2
#define __NR_read
3
- Data structure in
- Constant definitions in
GCC Compiler
The GNU GCC Compiler is probably most significant open source compiler available. It can compile C/C++, Ada, FORTRAN, Java, etc and generate code for a large number of CPU architectures. Like ARM, AVR PowerPC, x86, MIPS architectures, etc.
C library
The C library is very important component between applications and the kernel. A C library defines and supports system calls that make request to the kernel and provides higher level functions which create and terminate processes, create a file, open a file, close a file, allocate and de-allocate memory and so on. There are several C libraries are available. The choice of C library must be made at the time of cross compiling toolchain generation.
The different types of C libraries are:
- glibc
- uClibc
- eglibc
- dietlibc
- newlib
glibc:
It is standard C library that is used with GNU C compiler. The glibc library provides a rich and robust set of C language functions. It is large in size, not a problem for desktop systems where as in embedded systems the memory and storage will be constraints. It is quite big for small embedded systems.
uClibc:
A small standard C library used to produce static and shared library executables. Light weight for small embedded systems. Many features can be enabled and disabled through a menuconfig interface. It focuses on size rather than performance. Small compile time. Most of the applications compile with uClibc. It is used in large number of consumer electronic devices and embedded products.
eglibc:
Embedded glibc is a variant of the GNU C library or glibc is designed for use on embedded devices and provide binary compatibility with applications that are compiled with glibc. eglibc objective is reduced footprint, better support for cross compilation and cross testing.
dietlibc:
dietlibc is a small standard C library used to produce static executables that don’t use shared libraries.
newlib:
newlib is a small standard C library used in many free and commercial toolchains for embedded development and it is used by popular Cygwin project.
klibc:
klibc is designed for use in initramfs or initrd at boot time.
When building toolchains, ABI (Application binary interface) is used to generate binaries needs to be defines. An ABI determines such details are calling conventions such as how function arguments are passed and how the return value is passed, how the system calls are made and organization of structures. All binaries in a system must be compiled with same ABI and the kernel must understand this ABI. On ARM two ABIs are there.
- OABI- OABI is the first application binary interface for ARM architecture. It assumes machine has a FPU unit to accelerate floating point instructions so OABI toolchains generates codes to execute on FPU.
- EABI – embedded application binary interface specifies standard conventions for file formats, registers usage, stack frame organization, file formats and the parameter passing of an embedded software program.
Floating point support
Some processors have floating point unit and some other do not. For processors having a floating point, the toolchain will generate hard float code in order to use the floating point instructions directly. For processors without a floating point unit there are two solutions, first one is generate hard float code and relay on the kernel to emulate the floating point instructions. This process is very slow. Second one is generate soft float code, instead of generating floating point instructions calls to a user space library are generated.
Obtaining a Toolchain
There are two ways to build a Toolchain.
- Build your own Toolchain:
Building your own toolchain is a difficult task and it will take so much time. That is it can days or weeks. We need so many components while building toolchain are like kernel headers, C library sources and lots of decision to make such as ABI floating point mechanism, component versions etc.
- Get a pre-compiled Toolchain
Already pre-compiled toolchains are available based on your requirement you can finalize the toolchain you need. The requirements are CPU, C library, endianess, ABI, component version hard float/softfloat, etc. There are many choices are available for pre-compiled toolchains are
a. Linaro toolchains
b. Sourcery Codebench toolchains
#Tags