Cross compile for Raspberry Pi

Tested Setup

 * Target: Raspberry Pi Model 3 B+, running `aarch64` (Ubuntu MATE 18.04 64 bit)
 * Build host (for GNU Radio only): Ubuntu 18.04 on a PC
 * GNU Radio Version: above 3.8tech-preview, commit
 * Volk version: above v1.4, commit  (set automatically via git submodule)
 * Using Python 3

Initial setup of the Raspberry Pi
Install all GNU Radio build dependencies:

sudo apt update sudo apt install git cmake g++ libboost-all-dev libgmp-dev swig python3-numpy \ python3-mako python3-sphinx python3-lxml doxygen libfftw3-dev libcomedi-dev \ libsdl1.2-dev libgsl-dev libqwt-qt5-dev libqt5opengl5-dev python3-pyqt5 \ liblog4cpp5-dev libzmq3-dev python3-yaml python-mako python-click-plugins

Initial setup of the build host
Install the toolchain for linux ARM aarch64 cross-compilation:

sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu pkg-config-aarch64-linux-gnu

Create a folder to store the sysroot of the Raspberry Pi (RPI):

mkdir -p ~/x-compile/sysroot

Rsync the "/lib" and "/usr" folders from the RPI to the sys root folder that was created on the host:

rsync --progress -rl --delete-after --safe-links rpi-hostname:/{lib,usr} ~/x-compile/sysroot where  is the hostname of your RPI.

Cross-compile GNU Radio
Clone:

mkdir -p ~/src/ cd ~/src/ git clone --recursive https://github.com/gnuradio/gnuradio.git cd gnuradio/

Now, copy the  toolchain from volk:

Cmake build environment
Add some custom configurations to the cmake toolchain file. First configure  by adding:

set(CMAKE_SYSROOT "$ENV{HOME}/x-compile/sysroot")

set(ENV{PKG_CONFIG_DIR} "") set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig:${CMAKE_SYSROOT}/usr/lib/aarch64-linux-gnu/pkgconfig:${CMAKE_SYSROOT}/usr/local/lib/pkgconfig") set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})

Then, add the following:

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

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

Now prepare the build environment with cmake. Note many in-tree modules are disabled below. Choose whatever suits you. More importantly, note that  must be set.

mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX=/home/$USER/usr/local/ \ -DENABLE_DOXYGEN=OFF \ -DENABLE_SPHINX=OFF \ -DENABLE_GR_DTV=OFF \ -DENABLE_GR_FEC=OFF \ -DENABLE_GR_CHANNELS=OFF \ -DENABLE_GR_AUDIO=OFF \ -DENABLE_GR_TRELLIS=OFF \ -DENABLE_GR_VIDEO_SDL=OFF \ -DENABLE_GR_VOCODER=OFF \ -DENABLE_GR_WAVELET=OFF \ -DENABLE_GR_ZEROMQ=off \ -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchains/aarch64-linux-gnu.cmake ..

> IMPORTANT: the prefix set via  will be used both locally (in the host) as well as in the target (RPI). By the end of the build, we install locally in the prefix. Subsequently, we copy the locally installed files to the same path in the target (the RPI).

As configured above, the cmake build will try to use QT5 tools from the sysroot, particularly the QT User Interface Compiler (uic) and the QT Meta-Object Compiler (moc). This would cause problems, since binaries of these tools on sysroot folder are for the RPI, not for the host system. To overcome this, open the following files and manually substitute the path of all occurrences of “uic” and “moc” such that, instead, the locally (host’s) tool is used.

Substitute  with , and   with   in the following files:

* build/gr-qtgui/lib/CMakeFiles/gnuradio-qtgui.dir/build.make * build/gr-qtgui/examples/c++/CMakeFiles/display_qt.dir/build.make

Build and Install
In the build host, run: make -j4 make install

> NOTE: this will install locally (on the host) at the path that was defined via, i.e..

Prepare GR on RPI
First copy the GR build products (executables, libraries, includes etc) from the build host to the target (RPI).

On the RPI, run:

mkdir -p ~/usr/local

Then, from the host, run:

cd ~/usr/local rsync -av -e ssh. rpi-hostname:~/usr/local

Now, back in the RPI, create a script to set environmental variables. These vars will be necessary on RPI every time GR is to be executed, since GR build products have been placed at a non-conventional prefix. Hence, you will need to run this script every time.

Create a file named, for instance in your home bin folder  , and place the following lines on it:


 * 1) !/bin/bash

PREFIX=$HOME/usr/local

export PATH=$PATH:$PREFIX/bin export LD_LOAD_PATH=$LD_LOAD_PATH:$PREFIX/lib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PREFIX/lib export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$PREFIX/lib/pkgconfig export PYTHONPATH=$PYTHONPATH:$PREFIX/lib/python3.6/dist-packages

Now add executable permissions and run it such that env vars are set in the parent bash session:

chmod u+x set_env.sh . set_env.sh

Check if GR is working. For instance, try to open :

cd ~/usr/local/bin python3 gnuradio-companion

Or check version and built components:

gnuradio-config-info -v --enabled-components

If the above commands are succesful, your are good to start using GNU Radio on Raspberry Pi!

Building an OOT Module
In case you have an OOT module that you can afford to build natively from the RPI, all you need to do is first set the env vars to use the above GNU Radio build:

. ~/usr/local/bin/set_env.sh

Then, configure cmake with the correct installation prefix and run the build: cd ~/src/your-oot-dir mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX=~/usr/local/ .. make make install

Using an RTL-SDR on Raspberry Pi
In case you want to use an RTL-SDR, you can build its corresponding library directly (natively) on Raspberry Pi.

First, instal :

sudo apt-get install libusb-1.0-0-dev

Next, build :

cd ~/src/ git clone https://github.com/osmocom/rtl-sdr.git cd rtl-sdr/ mkdir build cd build/ cmake ../ -DINSTALL_UDEV_RULES=ON make make install DESTDIR=~

A minor note is that this build might result in the following error:

>Allocating 15 zero-copy buffers >Bus error

The solution is to remove some lines of code from `src/librtlsdr.c` and then recompile. See this stackoverflow thread.

Finally, blacklist module  such that it does not prevent rtl-sdr from running. To do so, edit  and add:

blacklist dvb_usb_rtl28xxu

Finally, build gr-osmosdr. The main repository does not provide a working version for GR 3.8. However, an almost functional version can be found at igorauad/gr-osmosdr:

Clone the fork and switch to the GR 3.8 branch: cd ~/src/ git clone https://github.com/igorauad/gr-osmosdr.git cd gr-osmosdr/ git fetch origin git checkout gr3.8

Build: mkdir build cd build/ cmake -DCMAKE_INSTALL_PREFIX=/home/$(USER)/usr/local/ .. make make install