I stumbled upon a great howto on building GCC cross compilers by Jeff Preshing and used his script to build a cross-compiler to compile Raspberry Pi programs on my Linux x86 desktop. In this post I explain how I did it and show how it’s like to compile programs with this cross-compiler.

Gather Information From the Raspberry Pi System

I run uname -a on my Raspberry Pi system to find out the kernel version, which for me is 3.12.23.

Configuring the Build

The cross compiler is built on the Linux system on which we want to compile our Raspberry Pi programs.

Download the build shell script from github and place into a newly created empty directory that we’ll use for downloading and building everything.

Open the script and change some variables according to the information gathered from the Raspberry Pi system.

1
2
3
4
5
6
TARGET=arm-unknown-linux-gnueabi
...
LINUX_ARCH=arm
CONFIGURATION_OPTIONS="--disable-multilib --disable-werror" # --disable-threads --disable-shared
...
LINUX_KERNEL_VERSION=linux-3.12.23

A added --disable-werror to the CONFIGURATION_OPTIONS variable to disable the -Werror flag for binutils compilation. -Werror causes warnings to become errors and binutils was too optimistic to have this enabled for us.

Run and Wait

Install the prerequisites, execute the build_cross_gcc script, and cross your fingers.

1
2
3
$ sudo apt-get install g++ make gawk
$ chmod +x ./build_cross_gcc
$ sudo ./build_cross_gcc

The script is easy to understand and self documented. If it fails you will see which command caused the failure and you will be able to find the command inside the script to understand which build step is problematic.

If the script fails to download some files, check this page and download the appropriate packages manually.

You can comment the first lines of the script to avoid running them again when you call build_cross_gcc for the thousandth time.

Testing the Cross-Compiler

All the tools we need to compile Raspberry Pi programs are in the /opt/cross/bin directory.

1
2
3
4
5
6
7
8
9
10
11
12
13
arm-unknown-linux-gnueabi-addr2line       arm-unknown-linux-gnueabi-gcov
arm-unknown-linux-gnueabi-ar              arm-unknown-linux-gnueabi-gprof
arm-unknown-linux-gnueabi-as              arm-unknown-linux-gnueabi-ld
arm-unknown-linux-gnueabi-c++             arm-unknown-linux-gnueabi-ld.bfd
arm-unknown-linux-gnueabi-c++filt         arm-unknown-linux-gnueabi-nm
arm-unknown-linux-gnueabi-cpp             arm-unknown-linux-gnueabi-objcopy
arm-unknown-linux-gnueabi-elfedit         arm-unknown-linux-gnueabi-objdump
arm-unknown-linux-gnueabi-g++             arm-unknown-linux-gnueabi-ranlib
arm-unknown-linux-gnueabi-gcc             arm-unknown-linux-gnueabi-readelf
arm-unknown-linux-gnueabi-gcc-4.9.2       arm-unknown-linux-gnueabi-size
arm-unknown-linux-gnueabi-gcc-ar          arm-unknown-linux-gnueabi-strings
arm-unknown-linux-gnueabi-gcc-nm          arm-unknown-linux-gnueabi-strip
arm-unknown-linux-gnueabi-gcc-ranlib

Compile the following C program using our new cross-compiler:

hello.c
1
2
3
4
5
6
#include <stdio.h>

int main(int argc, char *argv[]) {
	puts("Hello, World!");
	return 0;
}
1
2
$ export PATH=$PATH:/opt/cross/bin
$ arm-unknown-linux-gnueabi-gcc hello.c -o hello

You can check it’s actually an ARM program:

1
2
3
4
5
6
$ arm-unknown-linux-gnueabi-objdump -a hello
hello:     file format elf32-littlearm
hello
architecture: armv5t, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x000082c4

Send the program to your Raspberry Pi using SSH:

1
$ scp hello pi@192.168.20.13:/home/pi

Now we can check if it runs properly on the Raspberry Pi:

1
2
pi@raspberrypi:~$ ./hello
Hello, World!

This is success! Happy cross-compiling.