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”.