Spread the love

How to cross compile for ARMWhat is Cross compilation ?

According to Wikipedia, cross compilation is a process of compiling and creating executable code for a platform other than the one on which the compiler is running.

Cross compilation is a mechanism of compiling a source code which will be used on different architecture rather than the architecture on which it compile.

Practical example :- A compiler that runs on a Windows-10 PC but generates code that runs on Android smart-phone is a process of cross compilation

Cross compilation in more technical terms

Most commonly it is used with reference to compilation for architectures that are not binary-compatible for instance,

  • Building RISC binaries on a CISC CPU platform,
  • OR 64-bit binaries on a 32-bit system.
  • OR Building firmware intended to run on embedded devices (perhaps using the ARM CPU architecture) on Intel PC-based OSs.

Difference between Native and Cross compiler

  • A native compiler is one that compiles programs for the same architecture or operating system that it is running on. For instance, a compiler running on an x86 processor and creating x86 binaries.
  • A cross-compiler is one that compiles binaries for architectures other than its own, such as compiling ARM binaries on a Intel’s x86 processor.
  • A “cross compiler” executes in one environment and generates code for another. A “native compiler” generates code for its own execution environment.

Why we use cross compilation:

Lets understand this with an example :-

Suppose we have a micro controller(eg raspberry pie) which have 900 MHz frequency and less ram size.

Now we want a binary or library for some application on it. So that we compile a source code for it. Now

as above mention that it has less frequency and ram size so that it take more time for execution. For small code its ok! but for larger code !!! its time taking sounds panic.

So we have always a option for cross compilation.

Now we have CPU for our desktop which have more frequency and ram size than above mentioned.

So it take less time for execution and make binaries and library for the other architecture.

Eg:—-Suppose we have x86 arch on which we compile the source code for arm arch.

So here we use cross compilation.

Now question arises in your mind that how we can do it…Don’t be panic !!!! it is very easy

For this we will use tool chain .Download the tool chain from the google which is easily available

The name of some tool chain are following:-

1.arm-none-linux-gnueabi

2.arm-linux-gnueabihf(HF-hard float)

And many more…………

What is Tool-chain ?

A Tool-chain is the set of compiler + linker + librarian + any other tools you need to produce the executable (+ shared libraries, etc) for the target. A debugger and/or IDE may also count as part of a Tool-chain.

Why we require ARM Tool-chain ?

Tool-chain plays very important role in embedded system development. Tool-chain required to produce final executable and Architecture specific code out of source code.

For example:- If you want to run your C program on your ARM based smart-phone, then you have to cross compile your C program and you need ARM compiler, linker, library, etc. In short you need tool-chain.

Configuring tool-chain

Download Tool-chain first from here

I have got tar file named “gcc-arm-none-eabi-4_9-2015q1-20150306-linux.tar.bz2”

tar -xvf <tar_file_name>

 

After extracting tar file you would get “opt” directory go to that directory and find bin directory where you can get compiler and all that stuff required for cross compilation.

Set PATH variable to bin of tool-chain, so that your OS load binaries from that directory too. Use following line to do that

export PATH=<Absolute_path_from_root_directory_to_bin_directory_of_your_downloaded_tool-chain)>:$PATH

 

To check whether your OS use binaries from your tool-chain folder, write arm and press tab it will show you different binaries of tool-chain. Like follows

Toochain ARM(Click on image to zoom )

Let’s Compile C program for ARM architecture

Write hello world program in C (my file name is test.c here)

#include<stdio.h>
int main()
{
  printf("Hello World !\n");
}

 

Compiling

Before compiling with arm toolchain , first we have to export path to toolchain –

export PATH=$PATH:/home/manav/<toolchain name>/bin

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

When you compile first time, you may encounter this error(if your system is 64-bit)

"arm-none-linux-gnueabi-gcc: No such file or directory"

Solution: You need to install ia32-libs to work with 64-bit architecture, to install that use this command sudo apt-get install ia32-libs.

Now try again, and everything goes good, after compilation you will see the output binary file “test” in same folder.

To check this binary is compiled successfully or not use this

file test

and it will display like this

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

Run the binary –

./test

So now it display a error message that executable formate error…

Now if u are scared that ohhh !!! what is my output …I want to see it on my system before running on the target system….okkk u can do it..

For this u should install a tool “qemu” for setting the environment for arm on your x86 plateform.

On Ubuntu system type

sudo apt-get install qemu

After installing it run your cross compiled binary with qemu as:-

qemu-arm  -L  /home/manav/<toolchain path>/arm-none-linux-gnueabi/  ./test

Note :

(-L /home/manav/<toolchain path>/arm-none-linux-gnueabi/ it is for telling the qemu to set the environment for arm on this library path of toolchain).

Now u got ur output on the terminal.

Output :-

Hello World!

Let’s understanding tool-chain

GCC is a popular, open source tool-chain that can generate code for a wide range of architectures including Intel’s x86, ARM v4/5/6/7, TI’s MSP, Atmel’s AVR, and many others.

Note: when the host and target architectures are different, the tool-chain is also called a cross compiler

A typical GNU (GNU’s Not Unix) assembler tool-chain includes several programs that interact as shown in

  • as is the assembler and it converts human-readable assembly language programs into binary machine language code. It typically takes as input .s assembly files and outputs .o object files.
  • ld is the linker and it is used to combine multiple object files by resolving their external symbol references and relocating their data sections, and outputting a single executable file. It typically takes as input .o object files and .ld linker scripts and outputs .out executable files.
  • objcopy is a translation utility that copies and converts the contents of an object file from one format (e.g. .out) another (e.g. .bin).
  • objdump is a disassembler but it can also display various other information about object files. It is often used to disassemble binary files (e.g. .out) into a canonical assembly language listing (e.g. .lst).
  • ar is a utility for creating, modifying and extracting from archives.
  • nlmconv converts object code into an NLM.
  • nm lists symbols from object files.
  • ranlib generates an index to the contents of an archive.
  • readelf displays information from ELF-format object file.
  • size displays the sections of an object or archive, and their sizes.
  • strip Discards symbols embedded in object files.

If you search for an ARM compiler, you might stumble across the following toolchains: arm-none-linux-gnueabi, arm-none-eabi, arm-eabi, and arm-softfloat-linux-gnu, among others. This might leave you wondering about the method to the naming madness.

Unix cross compiler’s naming convention uses the form like

[arch] – [vendor] – [os] – [abi]

  • The arch refers to the target architecture, which in our case is ARM.
  • The vendor nominally refers to the tool-chain supplier.
  • The os refers to the target operating system, if any, and is used to decide which libraries (e.g. newlib, glibc, crt0, etc.) to link and which syscall conventions to employ.
  • The abi specifies which application binary interface convention is being employed, which ensures that binaries generated by different tools can inter-operate.

Some examples :

arm-none-eabi is the tool-chain we use in this class. This tool-chain targets the ARM architecture, has no vendor, does not target an operating system (i.e. targets a “bare metal” system), and complies with the ARM EABI.

i686-apple-darwin10-gcc-4.2.1 is the version of GCC on my MacBook Pro. This tool-chain targets the Intel i686 architecture, the vendor is Apple, and the target OS is Darwin version 10.

arm-none-linux-gnueabi is the tool-chain that can be installed in Debian-based systems using a package manager like apt (the package is called gcc-arm-linux-gnueabi). This toolchain targets the ARM architecture, has no vendor, creates binaries that run on the Linux operating system, and uses the GNU EABI. In other words, it is used to target ARM-based Linux systems.

arm-eabi  Android ARM compiler

What is ABI ?

Each architecture or architecture/os couple has an ABI. The ABI (Application binary Interface) describes how functions should be called, syscalls numbers, arguments passed, which registers can be used …

The abi describes how the compiler should generate the assembler.

If you use only assembler you don’t need to care about the ABI.

EABI, on the other hand, defines how functions interact. It doesn’t care how the data is represented on disk but rather how it is represented in memory. It answers questions of where the arguments are present, where the return value is stored, which registers are caller saved and which are callee saved, etc.

What is ELF ?

EABI stands for Embedded ABI, which is the definition of the Application Binary Interface for certain targets (e.g. PPC). ELF is the Executable and Linking Format which defines the ELF file format.

ELF is the currently preferred file format on most Unix like environments (e.g. Linux). This is the file format that the compiler will emit object files to, the format the linker will read (the previously generated object files), and the format the linker will emit binaries in. It will also come into play with the loader (and potentially the kernel). It defines how the data is written into a file.

So in some senses, ELF is the on disk representation of the data (though, in reality, it will also be in memory as the image will be mapped into memory for execution) and EABI defines the runtime representation of the (intermediate) data of the application.

What is the difference between arm-linux-gcc, arm-none-linux-gnueabi-gcc and arm-linux-gnueabi toolchains?

Toolchains have a loose name convention like  [arch] – [vendor] – [os] – [abi]

  • arch is for architecture: arm, mips, x86, i686…
  • vendor is tool chain supplier: apple,
  • os is for operating system: linux, none (bare metal)
  • abi is for application binary interface convention: eabi, gnueabi, gnueabihf

For your question, arm-none-linux-gnueabi and arm-linux-gnueabi is same thing. arm-linux-gcc is actually binary for gcc which produces objects for ARM architecture to be run on Linux with default configuration (abi) provided by toolchain.SystemSoureCode