Building Raspberry Pi programs on a traditional PC

Large Programs

You can compile larger programs that you would typically install with the command triplet ./configure; make; make install on an external system by adding the option --host=arm-linux-gnueabihf or arm-bcm2708-linux-gnueabi or arm-bcm2708hardfp-linux-gnueabi to ./configure. The translation process will then look for the suitable cross-compiler and tools, as long as they are in the path. You can then execute the time-intensive Make on the better-performing computer. The complete result for a successful build is copied onto a Rasp Pi, and the program is then finally installed via make install.

Larger applications usually need various dependencies in the form of libraries or other programs. For the compilation, these dependencies also need to be present on the host system. You can either cross-compile the necessary dependencies or install the packages on the Raspberry Pi, including the development versions, which are designated by the prefix dev-, and then copy the installation to the host computer.

Alternatively, you can take the memory card out of the Raspberry Pi and mount the complete Rasp Pi system on the PC. Then, you can communicate with the build process in ./configure via a series of options about where to find the various compiler and header files. These options are typically called --with-<package name>=[...].

Larger software packages frequently offer a shell script called <Package name>-config (e.g. wx-config for wxWidgets, sdl-config for SDL, …) to simplify this process. This can also typically be activated with ./configure options, such as --with-wx-config when compiling wxMaxima. The command wx-config --libs --cflags provides the necessary compiler--flags, where the libraries and header files are located. When cross-compiling, you do not use the 'native' wx-config tool (/usr/bin/wx-config, which would point to the native libraries), but the one in the crosscompiling environment, which points to the libraries for the Arm architecture.

With programs that only use a simple makefile for a build, it is possible to modify the compiler and other tools. Frequently, there are definitions for variables, such as CC (C Compiler) and CXX (C++ Compiler), that you will only need to adapt for the corresponding Raspberry cross-compiler. With build systems based on CMake, toolchain files indicate which compiler the build process should use and which target system the build is intended for. A simple example is presented in Listing 8. The invocation is made from the build directory according to Listing 9. You should reference the file Toolchain-raspi.cmake, which has been adapted for the Raspberry Pi as a toolchain file.

Listing 8

Building with CMake

set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
# where is the target environment
set(CMAKE_FIND_ROOT_PATH "/opt/tools/arm-bcm2708/
# search for programs in the build host directories
# search for libraries and headers in the target directories

Listing 9

Invoking CMake

$ cmake -DCMAKE_TOOLCHAIN_FILE=<path>/
  Toolchain-raspi.cmake <path>/<to>/the/<sourcecode>x

Google Go

The Go programming language, which was originally developed by Google [4], contains built-in functionality for cross-compiling. Go describes the functionality in the installation instructions by stating, "In effect, you are always cross-compiling." In general, the build system is consistent with the target system. This functionality is advantageous for Rasp Pi developers. Most of the Linux distributions have Go in their package sources. However, you will need to manually install Go for cross-compiling (Listing 10).

Listing 10

Installing Go for Cross-Compiling

cd $HOME
# for bootstrapping Go 1.5 we need Go 1.4
  so install that first:
# install Go 1.4 into $HOME/go1.4/
# (it is searched there when building Go 1.5)
tar xzf go1.4.3.linux-386.tar.gz --transform 's/go/go1.4/'
# extract Go 1.5.1 into $HOME/go/
tar xzf go1.5.1.src.tar.gz
cd go/src/
# build Go 1.5.1 with native and Arm CPU support
GOOS=linux GOARCH=arm ./make.bash
cd $HOME

After you complete the installation, the Go compiler will be in the ~/go directory. You should set the environment variable $GOROOT and expand the path with the directory so that it works properly. In this way, the self-compiled Go compiler takes precedence over any other version of the Go compiler on the system that might be lacking cross-compiling capabilities (Listing 11). If Go finds the environment variables GOOS=linux and GOARCH=arm, the compiler will spit out a Rasp Pi-compatible binary image. Listing 12 demonstrates the process using the example of the simple "Hello World" demo helloworld.go (Listing 13) [9].

Listing 11

Setting GOROOT

$ export GOROOT=$HOME/go
$ export PATH=$GOROOT/bin:$PATH

Listing 12

Getting the Binary Image

$ go run helloworld.go                            # run program without compilation
hello world
$ go build helloworld.go                          # compile program native
$ file helloworld                                 # Result: a binary for x86-64
helloworld: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
$ GOOS=linux GOARCH=arm go build helloworld.go    # crosscompile for the RasPi
$ file helloworld                                 # Result: a binary for the RasPi
helloworld: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped

Listing 13

Hello in Go

package main
import "fmt"
func main() {
  fmt.Println("hello world")

Buy this article as PDF

Express-Checkout as PDF

Pages: 6

Price $2.95
(incl. VAT)

Buy Raspberry Pi Geek

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content