Visual Servoing Platform  version 3.4.0
Tutorial: Cross-compilation for Raspberry Pi from Ubuntu host

Compiling ViSP directly on your Raspberry Pi will take a lot of time. In this tutorial you will learn how to cross-compile ViSP from source on an Ubuntu 14.04 host for a Raspberry Pi 1, 2 or 3 target.

Adapting this tutorial for other linux hosts (Fedora, Linux Mint, Debian...) should not be too complicated.

The material that is here involved is the following:

  • a host computer running Ubuntu 14.04 where we will cross-compile ViSP that will then be used on your Raspberry Pi
  • a Raspberry Pi board that will the target.
Note
Concerning ViSP installation on Raspberry Pi, we provide also this other Tutorial: Installation from source for Raspberry Pi.

Setting up Raspberry Pi target

There are a lot of documentation and tutorial that explain different ways to setup a Raspberry Pi. A good reference is the official page http://www.raspberrypi.org

We suppose here that you have a Raspberry Pi board that is already running.

Depending on you application or usage, you may want to install some 3rd parties useful to enable some ViSP capabilities. We recommend to install the following on your Raspberry Pi:

  • OpenCV
    $ sudo apt-get install libopencv-dev
    
  • libX11 to be able to open a window to display images
    $ sudo apt-get install libx11-dev
    
  • lapack to benefit from optimized mathematical capabilities
    $ sudo apt-get install liblapack-dev
    
  • libv4l to grab images from usb or analogic cameras
    $ sudo apt-get install libv4l-dev
    
  • QR code detection
    $ sudo apt-get install libzbar-dev
    

Setting up Ubuntu host computer

Install Raspberry official toochain

Note
Everything in this section is to run on your Ubuntu host computer.

Start with making a folder in your home directory called raspberrypi.

$ mkdir -p $HOME/soft/raspberrypi

Go in to this folder and pull down the offical Raspberry tools folder.

$ cd $HOME/soft/raspberrypi
$ git clone git://github.com/raspberrypi/tools.git --depth=1

The toochain that will be used is located in $HOME/soft/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian. Add now toolchain binaries location to your PATH adding

export PATH=$PATH:$HOME/soft/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin

to the end of the file named ~/.bashrc

Now you can either log out and log back in (i.e. restart your terminal session), or run . ~/.bashrc in your terminal to pick up the PATH addition in your current terminal session.

Now, verify that you can access the compiler arm-linux-gnueabihf-g++.

$ arm-linux-gnueabihf-g++ --version

You should get something like this:

arm-linux-gnueabihf-g++ (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11) 4.8.3 20140106 (prerelease)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Install Raspberry Pi sysroot

This step is mandatory to cross-compile ViSP with the 3rd parties that are already installed on the Raspberry target.

In your raspberrypi folder, make a folder called rootfs.

$ mkdir $HOME/soft/raspberrypi/rootfs

Now you need to copy via rsync the entire Raspberry /lib and /usr directories to this newly created folder.

$ rsync -rl --delete-after --safe-links pi@192.168.1.PI:/{lib,usr} $HOME/soft/raspberrypi/rootfs

where 192.168.1.PI is replaced by the IP of your Raspberry Pi.

Get ViSP source code

Cross-compilation capabilities are fully supported since ViSP 3.0.1 release.

There are different ways to get ViSP source code on Raspberry Pi:

  • You can download a daily snapshot. Once downloaded, uncompress the file using
    $ tar xvzf visp-snapshot-yyyy-mm-dd.tar.gz
    
  • Or you get the cutting-edge ViSP from GitHub repository using the following command
    $ git clone https://github.com/lagadic/visp.git
    
  • Or you can download the latest release (should be at least 3.0.1) as a zip or a tarball. Once downloaded, uncompress the file using either
    $ tar xvzf visp-x.y.z.tar.gz
    
    or
    $ unzip visp-x.y.z.zip
    

We suppose now that ViSP source is in a directory denoted <source_dir>, for example $HOME/soft/visp

Cross-compiling ViSP from source

At the end, the resulting installation is available in$HOME/soft/visp-crossbuild

Using ViSP cross-compilation result on Raspberry

The result of the cross-compilation could then be used on the Raspberry. We give a brief summary of the steps:

  • Copy the cross-build installation to Raspberry Pi target
    $ tar cvzf install.tar.gz install
    $ scp -r install.tar.gz pi@192.168.1.PI:
    
  • Usage on Raspberry Pi First move the libraries that were cross-build to a more friend location
    $ ssh pi@192.168.1.PI
    pi@raspberrypi:~ $ tar xvzf install.tar.gz
    pi@raspberrypi:~ $ mv install visp-crossbuild
    
    Then as described in Tutorial: How to create and build a project that uses ViSP and CMake on Unix or Windows create a tutorial-viewer.cpp and the corresponding CMakeLists.txt file in $HOME/started:
    pi@raspberrypi:~ $ cd $HOME/started
    pi@raspberrypi:~ $ ls
    tutorial-viewer.cpp CMakeLists.txt
    
    Create a build folder:
    pi@raspberrypi:~ $ mkdir build
    pi@raspberrypi:~ $ cd build
    
    To configure this project, you may run:
    pi@raspberrypi:~ $ cmake .. -DVISP_DIR=/home/pi/visp-crossbuild/lib/cmake/visp
    
    At this step you may encounter the following issue with a Raspberry Pi 1: CMake 2.8.12 or greater requested. Once fixed, to build just run:
    pi@raspberrypi:~ $ make
    

Tips and tricks

How to use an other toochain

The default toolchain used in arm-raspberrypi.toolchain.cmake file is the one located in $HOME/soft/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin. To set an other toochain, use ARM_RASPBERRY_CROSSCHAIN cmake var:

$ cmake -DARM_RASPBERRY_CROSSCHAIN=$HOME/soft/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin -DCMAKE_TOOLCHAIN_FILE=../visp/platforms/linux/arm-raspberrypi.toolchain.cmake ../visp

Don't forget to update the location of the toolchain in your PATH in ~/.bashrc file:

export PATH=$PATH:$HOME/soft/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

How to use an other rootfs location

The default rootfs used in arm-raspberrypi.toolchain.cmake file is the one located in $HOME/soft/raspberrypi/roots. To set an other location, use ARM_RASPBERRY_ROOTFS cmake var:

$ cmake -DARM_RASPBERRY_ROOTFS=$HOME/soft/raspberrypi/root-fs-pi3 -DCMAKE_TOOLCHAIN_FILE=../visp/platforms/linux/arm-raspberrypi.toolchain.cmake ../visp

Linker cannot find libpthread.so

During the cross-compilation, if you get the following error:

Linking CXX shared library ../../lib/libvisp_core.so
 .../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/../lib/gcc/arm- linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find /lib/arm-linux-gnueabihf/libpthread.so.0
 .../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find /usr/lib/arm-linux-gnueabihf/libpthread_nonshared.a

Do the following:

$ cd $HOME/soft/raspberrypi/rootfs
$ find . -name libpthread.so
./usr/lib/arm-linux-gnueabihf/libpthread.so

Edit this file to set relative path:

$ vi ./usr/lib/arm-linux-gnueabihf/libpthread.so
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( ../../../lib/arm-linux-gnueabihf/libpthread.so.0 ../../../usr/lib/arm-linux-gnueabihf/libpthread_nonshared.a )

Linker cannot find libc.so

During the cross-compilation, if you get the following error:

.../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find /lib/arm-linux-gnueabihf/libc.so.6
.../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find /usr/lib/arm-linux-gnueabihf/libc_nonshared.a
.../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3

Do the following:

$ cd $HOME/soft/raspberrypi/rootfs
$ find . -name libc.so
./usr/lib/arm-linux-gnueabihf/libc.so

Edit this file to set relative path:

$ vi ./usr/lib/arm-linux-gnueabihf/libc.so
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( ../../../lib/arm-linux-gnueabihf/libc.so.6 ../../../usr/lib/arm-linux-gnueabihf/libc_nonshared.a  AS_NEEDED ( ../../../lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 ) )

No rule to make target libpng.so

If during cross-compilation, you get the error:

make[3]: *** No rule to make target `.../raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf/libpng.so', needed by `lib/libvisp_io.so.3.0.1'

It mean that libpng.so is not found. The fix consists in reparing libpng12.so link that was miss updated during rsync:

$ cd $HOME/soft/raspberrypi/rootfs
$ cd usr/lib/arm-linux-gnueabihf
$ ls -als libpng*
172 -rw-r--r-- 1 fspindle fspindle 175234 juin   7 15:18 libpng12.a
  0 lrwxrwxrwx 1 fspindle fspindle     13 juin   7 15:17 libpng12.so -> libpng12.so.0
  0 lrwxrwxrwx 1 fspindle fspindle     10 juin   7 15:17 libpng.a -> libpng12.a
  0 lrwxrwxrwx 1 fspindle fspindle     11 juin   7 15:17 libpng.so -> libpng12.so
$ rm libpng12.so
$ ln -s ../../../lib/arm-linux-gnueabihf/libpng12.so.0 libpng12.so

Undefined reference to __throw_out_of_range_fmt

This error occurs when cross-compiling for Raspberry Pi 3 Model B.

Linking CXX executable testArray2D
/home/fspindle/sThis is unfortunately due to the OpenCV core library (for Jessie) being built with a newer version of gcc/g++ oft/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf/libopencv_ts.so.2.4.9: undefined reference to `std::__throw_out_of_range_fmt(char const*, ...)@GLIBCXX_3.4.20'

This error is due to the fact that OpenCV was built with gcc-4.9 on Raspberry Pi Jessy distro, while the cross-compiler uses gcc-4.8 version.

There exists different work arround depending on your use case:

  • if you are just interested to build ViSP libraries, a simple workarround is to turn off the build of the tests, demos, tutorials and examples:
    $ cd $HOME/soft/visp-crossbuild
    $ cmake -DCMAKE_TOOLCHAIN_FILE=../visp/platforms/linux/arm-raspberrypi.toolchain.cmake ../visp -DBUILD_DEMOS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TESTS=OFF -DBUILD_TUTORIALS=OFF
    
  • if you are not interested in OpenCV usage on the Raspberry, disable OpenCV:
    $ cd $HOME/soft/visp-crossbuild
    $ cmake -DCMAKE_TOOLCHAIN_FILE=../visp/platforms/linux/arm-raspberrypi.toolchain.cmake ../visp -DUSE_OPENCV=OFF
    
  • an other way, that we didn't investigate in depth is to upgrade the toochain to gcc-4.9. Notice that arm-rpi-4.9.3-linux-gnuabihf toolchain in https://github.com/raspberrypi/tools.git doesn't allow cmake to detect all the 3rd parties. During our trial, we succeed to build ViSP, but X11 was not detected. During the configuration cmake only found OpenCV and zbar libraries.

CMake 2.8.12 or greater requested

The following error may occur on Raspberry Pi 1 when you are trying to build a project with the resulting cross-build material:

pi@raspberrypi:~ $ cmake .. -DVISP_DIR=/home/pi/visp-crossbuild/lib/cmake/visp
-- The C compiler identification is GNU 4.6.3
-- The CXX compiler identification is GNU 4.6.3
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
CMake Error at /home/pi/visp-crossbuild/lib/cmake/visp/VISPModule
s.cmake:156 (message):
  This file relies on consumers using CMake 2.8.12 or greater.
Call Stack (most recent call first):
  /home/pi/visp-crossbuild/lib/cmake/visp/VISPConfig.cmake:170 (i
nclude)
  CMakeLists.txt:5 (find_package)

The current cmake version is 2.8.9 while 2.8.12 is requested:

pi@raspberrypi:~ $ cmake --version
cmake version 2.8.9

You definitely need to update cmake version on the Raspberry Pi. To this end download and unpack the lastest CMake release. In our case it was cmake-3.5.2.tar.gz

pi@raspberrypi ~ $ cd soft
pi@raspberrypi ~/soft $ tar xvzf cmake-3.5.2.tar.gz
pi@raspberrypi ~/soft $ cd cmake-3.5.2

Now to build cmake 3.5.2 run the following (it can take some hours on a Raspberry Pi 1):

pi@raspberrypi ~/soft/cmake-3.5.2 $ ./bootstrap --prefix=/usr
pi@raspberrypi ~/soft/cmake-3.5.2 $ sudo make install
pi@raspberrypi ~/soft/cmake-3.5.2 $ cmake --version
cmake version 3.5.2

Now you should be able to configure your project and build

pi@raspberrypi:~ $ cmake .. -DVISP_DIR=/home/pi/visp-crossbuild/lib/cmake/visp
pi@raspberrypi:~ $ make

Next tutorial

You are now ready to see the next Tutorial: How to create and build a project that uses ViSP and CMake on Unix or Windows that will show you how to use ViSP as a 3rd party to build your own project on Raspberry Pi or on any other system. Then if you have a Raspberry Pi camera module, you can also follow the Tutorial: Blob tracking especially subsection Tracking form v4l2 live cameras.