Cross compiling kernel for Raspberry Pi on Fedora 17 – Part 2

There are multiple ways to install a cross compiler on Fedora 17. The simplest way was described in Part 1. The problem is that the available cross-build binary utilities for ARM (sudo yum info gcc-arm-linux-gnu) does not support cross-building of user space programs. A slightly more complicated option is to use build frameworks like OpenEmbedded or crosstool-ng.

Install crosstool-ng
By the time of writing this post the latest stable version of crosstool-ng is 1.16.0. Installation of a stable version is quite straightforward and it is very clearly described in “Download and usage section” of For your reference I copy it here with slight modifications.

su - #change to root
#Install dependencies
yum install bison flex gperf libtool texinfo gcc gcc-c++ gmp-devel
#Download and install crosstool-ng
cd /opt
bunzip2 crosstool-ng-1.16.0.tar.bz2
tar xf crosstool-ng-1.16.0.tar
cd crosstool-ng-1.16.0
#The --prefix parameter shall be set to the installation directory 
./configure --prefix=/opt/crosstool-ng-1.16.0
make install
#For auto-completion, do not forget to install 'ct-ng.comp' into your bash completion directory
cp ct-ng.comp /etc/bash_completion.d/    

The bash_completion will automatically pick up the auto completion parameters after restart. You can read more about autocopletion feature of bash here and here.

Edit the .bash_profile of root user and also your user and add the /opt/crosstool-ng-1.16.0/bin to PATH in order make the crostool-ng comands available from shell.


Configure the toolchain
The crosstool-ng has been installed and ready to build a toolchain for the Raspberry Pi (or other environment)

su -
mkdir /opt/crosstool-ng-1.16.0-config 
cd /opt/crosstool-ng-1.16.0-config
ct-ng menuconfig

The last command will pop up a kernel-like menuconfig configuration interface where the following changes needs to be made.

  • Paths and misc options
    • Enable “Try features marked as EXPERIMENTAL”
    • Set the “Prefix directory” from “${HOME}/x-tools/${CT_TARGET}” to “/opt/crosstool-ng-1.16.0-tools/${CT_TARGET}”, please note that the /opt/crosstool-ng-1.16.0-config directory will contain the configuration, downloaded tools, temporary build files and the /opt/crosstool-ng-1.16.0-tools will contain your actual toolchain.
  • Toolchain options
    • Tuple’s version string is set to “unknown” by default, if would like to change it please see the “Note” in the bottom of this post
  • Target options
    • Be sure that the “Target Architecture” is set to “arm”
    • Be sure that “Little Endian” and “32bit” are selected
    • Be sure that “Floating point” is set to “hardware (FPU)”
    • Be sure that “Use EABI” is selected
  • Operating system
    • Set “Target OS” to Linux
  • C compiler
    • Enable “Show Linaro versions”
    • The “gcc version” should automatically change to latest linaro version, if not then set it manually. Currently the latest is “linaro-4.7-2012.07”
    • Enable “C++” in order to have C++ compiler
    • Disable “Link libstdc++ statically into gcc binary” otherwise you will get the the following error “[ERROR] Static linking impossible on the host system ‘x86_64-build_unknown-linux-gnu'”
    • Disable “GRAPHITE loop optimisations” otherwise you will get the the following error “Installing PPL for host [ERROR] configure: error: Cannot find GMP version 4.1.3 or higher.”

Exit from the menuconfig save the changes and build it still as root

ct-ng build

The build takes a while, but after it is done the toolchain should appear in the /opt/crosstool-ng-1.16.0-tools directory.

Switch from root to your regular user and append the /opt/crostool-ng-1.16.0-tools/arm-unknown-linux-gnueabi/bin to PATH variable in .bash_profile to make the cross compiler binaries available in shell


Now you have a full featured cross-compile environment and you can build user space programs or you can compile kernel as described in Part 1. Of course in the CROSS_COMPILE parameter you need to specify the /opt/crosstool-ng-1.16.0-tools/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi- instead of /usr/bin/arm-linux-gnu-. For example:

make ARCH=arm CROSS_COMPILE=/opt/crosstool-ng-1.16.0-tools/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi- oldconfig

After you have executed every kernel compilation step described in the Part 1 you should see

pi@raspberrypi ~ $ uname -a
Linux raspberrypi 3.2.27-crosstool-ng #1 PREEMPT Tue Oct 2 20:28:03 CEST 2012 armv6l GNU/Linux

To test the cross-building capability of user space programs just creat a little hello world as hello.c

#include <stdio.h>

int main () {
  printf("Hello Cross Compiled Pi\n");
  return 0;

Compile it and check the result of compilation with file command

~ $ arm-unknown-linux-gnueabi-gcc -o arm-hello hello.c
~ $ file arm-hello
arm-hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.5.0, not stripped

After transfering it to Raspberry pi with scp

pi@raspberrypi ~ $ ./arm-hello
Hello Cross Compiled Pi

Note: The “arm-unknown-linux-gnueabi” name is crated based on form “arch-vendor-kernel-system”. You can set the vendor to whatever you think fits better. For that you can navigate to “Toolchain options” -> “Tuple’s vendor string” and change it from “unknown” to e.g. “rpi” and build the whole tool-chain as described above, after this modification your tools will be named like “arm-rpi-linux-gnueabi”.


Cross compiling kernel for Raspberry Pi on Fedora 17 – Part 1

The Raspberry Pi is very limited in CPU and memory and doing computation heavy tasks like compiling the entire kernel on it would take a lot of time. In order to make this process faster a cross compiler is required.
There are multiple ways to install a cross compiler on your Fedora 17 powered development workstation, one of the simplest is just to install the gcc-arm-linux-gnu from the repository using the yum package manager.

yum -y install gcc-arm-linux-gnu
arm-linux-gnu-gcc --version
arm-linux-gnu-gcc (GCC) 4.7.1 20120606 (Red Hat 4.7.1-0.1.20120606)

Get kernel source code
Kernel sources can be obtained from Raspberry PI git repository. If you like experimenting then you can download (or clone with appropriate git commands) the master version of kernel which contains the latest codebase. If you are a bit less adventurous then you can download an older version of kernel from branch section that are considered more stable.

mkdir ~/raspberrypi   
cd ~/raspberrypi
wget -O raspberrypi-linux-3.2.27.tar.gz
tar xzf raspberrypi-linux-3.2.27.tar.gz
mv raspberrypi-linux-965b922 kernel-3.2.27

Configure the kernel
Setting up a proper kernel configuration file from scratch is a very challenging task, therefore it is worth to download current config file (.config) from your current Raspberry Pi and us it as a base for kernel compilation. In order to do this execute the following command on the Raspberry Pi:

zcat /proc/config.gz  > /tmp/.config

Copy the .config file to your development workstation with scp.

scp pi@rpi:/tmp/.config ~/raspberrypi/kernel-3.2.27

If you prefer to use a default config instead of the above described one then you can pick one from the available configs in the kernel source tree. The Raspberry Pi configs are prefixed with “bcmrpi_”.

cd ~/raspberrypi/kernel-3.2.27
cp arch/arm/configs/bcmrpi_defconfig .config

It is usually a good idea to execute oldconfig before the menuconfig since the oldconfig will prompt only the newly introduced kernel configuration options and if you execute the menuconfig then maybe some important newly introduced kernel options will remain unnoticed.

make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnu- oldconfig
  HOSTCC  scripts/basic/fixdep
  #For the sake of clarity rest of the lines are removed...
* CPU Frequency scaling
CPU Frequency scaling (CPU_FREQ) [N/y/?] (NEW) 

To have the nice menu based kernel configuse the menuconfig:

make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnu- menuconfig

In the “General Setup” menu of the Kernel Configuration (menuconfig) you can set up a custom version string that will be appended to kernel version. Change the “Local version – append to kernel relase” to “-tutorial”. In older kernels where this menu item does not exist the following command will have the same effect

sed -i 's/EXTRAVERSION =.*/EXTRAVERSION = Tutorial/' Makefile

Compile kernel
To start compiling and create a the architecture specific kernel image:

make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnu-
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnu- modules

Transfer kernel to Raspberry Pi
The transfer is described on RPi_Kernel_Compilation site. Make sure that the sshfs is installed on the Raspberry (you can use also NFS if you wish) and the firewall on your workstation allows the connection to it. For the sake of clarity I copy the code here

sudo bash #Execute everything as root on Raspberry Pi
apt-get install sshfs
cd /mnt
mkdir raspberrypi
sshfs user@host:/home/user/raspberrypi raspberrypi
cd raspberrypi/kernel-3.2.27
make modules_install
cp arch/arm/boot/Image /boot/kernel.img

After reboot you will see that the newly complied (3.2.27-tutorial) kernel is running

pi@raspberrypi ~ $ uname -a
Linux raspberrypi 3.2.27-tutorial #1 PREEMPT Mon Sep 24 22:01:27 CEST 2012 armv6l GNU/Linux

There is a problem with gcc-arm-linux-gnu utilities. If you check the description of the package (sudo yum info gcc-arm-linux-gnu) you will see that it does not support cross-building of user space programs. If you would like to have a cross compiler that can be used for compiling user space code then build frameworks like OpenEmbedded or crosstool-ng might be the right tools for you. In the Part 2 I will show how to set up a full featured cross-compile environment on Fedora 17.