Crafty Bytes

Musings of an attentive programmer.

Cross-Compiling for Raspberry Pi Using CMake on Linux

Raspberry Pi is a great device with a (relatively) powerful GPU, but due to its low-end CPU compiling C/C++ applications on the machine takes too long to be feasible for anything but the simplest programs. Luckily, setting up a cross-compiling toolchain that produces binaries compatible with Raspberry Pi is a rather straightforward affair on Linux.

Although the following instructions assume a 64-bit Linux distribution, it should be easy to adapt them to a 32-bit version. If you don’t use CMake, you can skip the CMake Setup section.

Toolchain Setup

First of all, create a new directory where the toolchain and other files required for cross-compilation will be stored:

1
2
mkdir ~/rpi
cd ~/rpi

The Raspberry Pi foundation maintains a repository with tools for cross-compilation. Let’s clone it:

1
git clone https://github.com/raspberrypi/tools.git

The toolchain we’re going to use is located in tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/.

At this stage it would be possible to compile some simple programs, but any useful application will need access to headers and libraries from the target system. They can be copied from an SD card containing Raspbian 1:

1
2
3
4
mkdir -p rootfs/opt
cp /run/media/amgaera/root/lib/ rootfs/ -rv
cp /run/media/amgaera/root/usr/ rootfs/ -rv
cp /run/media/amgaera/root/opt/vc rootfs/opt/ -rv

CMake Setup

CMake is a build system that’s very popular among C/C++ developers and has good support for cross-compilation. The recommended way to configure it to cross-compile for a specific platform is to provide it with a toolchain file. Let’s create such a file for the toolchain we downloaded:

Toolchain-RaspberryPi.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)

# Specify the cross compiler
SET(CMAKE_C_COMPILER $ENV{HOME}/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER $ENV{HOME}/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-g++)

# Where is the target environment
SET(CMAKE_FIND_ROOT_PATH $ENV{HOME}/rpi/rootfs)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}")
SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}")

# Search for programs only in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# Search for libraries and headers only in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

If you want to use VideoCore IV-related libraries, you may also consider adding the following commands to the toolchain file 2:

1
2
3
INCLUDE_DIRECTORIES($ENV{HOME}/rpi/rootfs/opt/vc/include)
INCLUDE_DIRECTORIES($ENV{HOME}/rpi/rootfs/opt/vc/include/interface/vcos/pthreads)
INCLUDE_DIRECTORIES($ENV{HOME}/rpi/rootfs/opt/vc/include/interface/vmcs_host/linux)

Now we’re all set to start cross-compiling CMake-based projects for Raspberry Pi. If you have such a project handy, create a new build directory and start CMake, pointing it to the toolchain file:

1
2
3
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=Debug -D CMAKE_TOOLCHAIN_FILE=$HOME/rpi/Toolchain-RaspberryPi.cmake path/to/your/project

Unless CMake can’t find some libraries in the target environment, you should end up with a Makefile and be able to compile the project using make.

Summary

When developing for such low-power devices as Raspberry Pi, cross-compilation is usually a must. Otherwise builds 3 take so much time that continuous testing of code changes becomes difficult. The good thing is that nowadays it’s quite easy to set up a toolchain to cross-compile for Raspberry Pi, especially if one uses Linux with CMake.


  1. Arch Linux ARM or Pidora should work too

  2. Alternatively, they may be added to the CMakeLists.txt of each project that requires them, but because all of my projects do, I found it easier to include them in the toolchain file

  3. Even incremental

Comments