GRAndDeps
{{>toc}}
Setup and Building the Dependencies
Android Build System Prerequisites
We need Android Lollipop (5.0) to support the use of complex numbers. This is Android API 21 and the latest Android NDK, which is r10d.
- NDK: https://developer.android.com/tools/sdk/ndk/index.html
- Android Studio: http://developer.android.com/sdk/installing/index.html?pkg=studio
IMPORTANT: Please use the NDK version r10e. Newer versions (r11c out currently) have removed GCC version 4.8 and only include 4.9. We have some C++ build issues with 4.9 and must use 4.8.
Optionally:
- SDK: Android SDK Tools Only, https://developer.android.com/sdk/index.html#Other
Unpack the NDK into /opt/android-ndk-<version>. Create a symlink to /opt/ndk.
Unpack Android Studio into /opt/android-studio. Run /opt/android-studio/bin/studio.sh. The first thing this will do is download and install the Android SDK. If you downloaded this yourself above, I installed it into /opt/android-sdk-linux and created a symlink to /opt/android. When I ran Android Studio, it asks where you would like to install this. Give it /opt/android-sdk-linux. If you did not install the SDK yourself, this will install everything you need. If you did install it, this will just install updates.
You can then run /opt/android/tools/android to do any tweaking of the SDK. Make sure your Android SDK and NDK supports API 21 (5.0).
Export these variables pointing to where you installed the SDK (/opt/android) and NDK (/opt/ndk):
export ANDROID_SDK=/opt/android export ANDROID_NDK=/opt/ndk export PATH=$PATH:$ANDROID_SDK/tools:$ANDROID_NDK
Dependencies Build Script
The following build script packages up all of the steps to build the following dependencies as well as VOLK, GNU Radio, GRAnd, and gr-osmosdr (see GRAndBuild). It is known to work with Ubuntu 15.10, 64-bit. There are likely a handful of apt-gettable programs necessary for this to complete. You will definitely need the following:
- cmake, git, make, xutils-dev, automake, autoconf, libtool, wget, perl, tar, sed
Download the Build Script.
Building the Toolchain
We will create our own tool chain that uses GCC 4.8. The 4.9 toolchain has some issues still. To make the toolchain, run the command:
/opt/ndk/build/tools/make-standalone-toolchain.sh --stl=gnustl --arch=arm --platform=android-21 --abis=armeabi-v7a --install-dir=/opt/android-toolchain
You can select your own --install-dir; we'll set a variable later for this to make it flexible.
Then, let's update some of the environmental variables:
export ANDROID_STANDALONE_TOOLCHAIN=/opt/android-toolchain export PATH=$ANDROID_STANDALONE_TOOLCHAIN/bin:$PATH
Dependency Setup
The basic dependencies we need to build GNU Radio and its most interesting/useful components are Boost and FFTW.
Make a directory to install all of the dependencies and GNU Radio and make it owned by you. For example:
sudo mkdir /opt/grandroid sudo chown user1:user1 /opt/grandroid export PREFIX=/opt/grandroid
Boost for Android
NOTE: Recently changed; See the "Older Boost (1.55) for Android" section below for the original instructions we were using.
Download Boost >= 1.58 from http://www.boost.org/. This can either be a bzip or gzip tarball. We'll unpack it, fix some configuration issues for Android, and build:
tar xjf boost_1_58_0.tar.bz2 (use 'xzf' flags instead of 'xjf' if you have the tar.gz version) cd boost_1_58_0
Create a file called tools/build/src/user-config.jam and put the following into it:
import os ; local ANDROID_STANDALONE_TOOLCHAIN = [ os.environ ANDROID_STANDALONE_TOOLCHAIN ] ; using gcc : android : $(ANDROID_STANDALONE_TOOLCHAIN)/bin/arm-linux-androideabi-g++ : --sysroot=$(ANDROID_STANDALONE_TOOLCHAIN)/sysroot -march=armv7-a -mfloat-abi=softfp -Os -fno-strict-aliasing -O2 -DNDEBUG -g -lstdc++ -I$(ANDROID_STANDALONE_TOOLCHAIN)/include/c++/4.8/ -I$(ANDROID_STANDALONE_TOOLCHAIN)/include/c++/4.8/arm-linux-androideabi/armv7-a -D__GLIBC__ -D_GLIBCXX__PTHREADS -D__arm__ -D_REENTRANT -DBOOST_SP_USE_PTHREADS -L$(ANDROID_STANDALONE_TOOLCHAIN)/lib/gcc/arm-linux-androideabi/4.8/ $(ANDROID_STANDALONE_TOOLCHAIN)/bin/arm-linux-androideabi-ar $(ANDROID_STANDALONE_TOOLCHAIN)/bin/arm-linux-androideabi-ranlib ;
Then run the build scripts. You can play with the options for which libraries to build and not build. Here, we are building the set of libraries required for GNU Radio but no others.
./bootstrap.sh ./b2 \ --without-python --without-container --without-context \ --without-coroutine --without-graph --without-graph_parallel \ --without-iostreams --without-locale --without-log --without-math \ --without-mpi --without-signals --without-timer --without-wave \ link=static runtime-link=static threading=multi threadapi=pthread \ target-os=linux --stagedir=android --build-dir=android \ stage
{{collapse(Details on the results (click to unfold))
When done correctly, the initial output will show us the configuration, which will looks like this using the above settings:
Performing configuration checks - 32-bit : yes - arm : yes - has_icu builds : no - lockfree boost::atomic_flag : no Component configuration: - atomic : building - chrono : building - container : not building - context : not building - coroutine : not building - date_time : building - exception : building - filesystem : building - graph : not building - graph_parallel : not building - iostreams : not building - locale : not building - log : not building - math : not building - mpi : not building - program_options : building - python : not building - random : building - regex : building - serialization : building - signals : not building - system : building - test : building - thread : building - timer : not building - wave : not building
It is important to make sure that this is saying that it will be building 32-bit for ARM.
When that finishes, we will have a set of static libraries in the android/lib directory. We can verify that these are correctly cross-compiled for our ARM systems with:
readelf -A android/lib/libboost_system.a File: android/lib/libboost_system.a(error_code.o) Attribute Section: aeabi File Attributes Tag_CPU_name: "7-A" Tag_CPU_arch: v7 Tag_CPU_arch_profile: Application Tag_ARM_ISA_use: Yes Tag_THUMB_ISA_use: Thumb-2 Tag_FP_arch: VFPv2 Tag_ABI_PCS_wchar_t: 4 Tag_ABI_FP_denormal: Needed Tag_ABI_FP_exceptions: Needed Tag_ABI_FP_number_model: IEEE 754 Tag_ABI_align_needed: 8-byte Tag_ABI_align_preserved: 8-byte, except leaf SP Tag_ABI_enum_size: int Tag_ABI_HardFP_use: SP and DP Tag_ABI_optimization_goals: Aggressive Speed Tag_CPU_unaligned_access: v6
So this library is for ARMv7-a, which is what we want.
}}
Now, install it into our PREFIX:
./b2 \ --without-python --without-container --without-context \ --without-coroutine --without-graph --without-graph_parallel \ --without-iostreams --without-locale --without-log --without-math \ --without-mpi --without-signals --without-timer --without-wave \ link=static runtime-link=static threading=multi threadapi=pthread \ target-os=linux --stagedir=android --build-dir=android \ --prefix=$PREFIX install
FFTW for Android
- Grab the FFTW tarball from their site. I'm using the latest 3.3.4.
- Unpack it
tar xzf fftw-3.3.4.tar.gz cd fftw-3.3.4
- Setup the environment, build, and install:
mkdir build; cd build export SYS_ROOT="$ANDROID_STANDALONE_TOOLCHAIN/sysroot" export CC="arm-linux-androideabi-gcc --sysroot=$SYS_ROOT" export LD="arm-linux-androideabi-ld" export AR="arm-linux-androideabi-ar" export RANLIB="arm-linux-androideabi-ranlib" export STRIP="arm-linux-androideabi-strip" ../configure --enable-single --enable-static --enable-threads \ --enable-float --enable-neon \ --host=armv7-eabi --build=x86_64-linux \ --prefix=$PREFIX \ LIBS="-lc -lgcc -march=armv7-a -mfloat-abi=softfp -mfpu=neon" \ CC="arm-linux-androideabi-gcc -march=armv7-a -mfloat-abi=softfp -mfpu=neon" make make install
- puts libfftw3f.a and libfftw3_threads.a into $PREFIX/lib
- and fftw3.h into $PREFIX/include
Thrift
Required for using ControlPort on Android.
(Work-in-progress: Thrift stopped building cleanly for me so the following instructions are just a placeholder as I work through that.)
OpenSSL for Android
Thrift requires some OpenSSL libraries, like libcrypto, so we need to build these first and install them into the toolchain.
- IMPORTANT: Do all of this in a new shell since we'll be polluting the environmental variables.
- Set the toolchain bin path to the prebuilt one in the NDK since that's where OpenSSL will go look for everything:
export PATH=$ANDROID_NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin:$PATH export ANDROID_NDK_ROOT=$ANDROID_NDK
- Download OpenSSL
' https://www.openssl.org/source/
' Select the latest in the 1.0.2 series (1.0.2a as of writing this)
'* Update: 1.1.0 has been released but is structured differently; we have not updated for that, yet.
tar xzf openssl-1.0.2a.tar.gz cd openssl-1.0.2a/
- Get and edit a special shell script to build OpenSSL for Android:
wget https://wiki.openssl.org/images/7/70/Setenv-android.sh chmod +x Setenv-android.sh . ./Setenv-android.sh perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org ./config --prefix=/usr shared no-ssl2 no-ssl3 no-comp no-hw no-engines --openssldir=$ANDROID_STANDALONE_TOOLCHAIN/sysroot/usr/ssl/$ANDROID_API make depend make all cp libcrypto.* $ANDROID_STANDALONE_TOOLCHAIN/sysroot/usr/lib cp libssl.* $ANDROID_STANDALONE_TOOLCHAIN/sysroot/usr/lib/ ln -s `pwd`/include/openssl $ANDROID_STANDALONE_TOOLCHAIN/sysroot/usr/include
- See this page if anything goes wrong:
- Close this shell! Do not proceed to the next steps within this shell.
Apache Thrift
- Download Apache Thrift:
' https://thrift.apache.org/download
git clone https://git-wip-us.apache.org/repos/asf/thrift.git thrift cd thrift git checkout 0.9.3
- Go into configure.ac and comment out lines:
- 598 (AC_FUNC_MALLOC)
- 600 (AC_FUNC_REALLOC)
- Configure and build thrift
export SYS_ROOT="$ANDROID_STANDALONE_TOOLCHAIN/sysroot/" export CC="arm-linux-androideabi-g++ --sysroot=$SYS_ROOT" export CXX="arm-linux-androideabi-g++ --sysroot=$SYS_ROOT" export LD="arm-linux-androideabi-ld" export AR="arm-linux-androideabi-ar" export RANLIB="arm-linux-androideabi-ranlib" export STRIP="arm-linux-androideabi-strip" ./bootstrap.sh ./configure --prefix=$PREFIX --disable-tests --disable-tutorial --with-cpp \ --without-python --without-c_glib --without-php --without-csharp --without-java \ --without-libevent --without-zlib \ --with-boost=$PREFIX --host=arm-eabi --build=x86_64-linux \ CPPFLAGS="-I$ANDROID_STANDALONE_TOOLCHAIN/include/c++/4.8/arm-linux-androideabi/armv7-a" \ LDFLAGS="-L$ANDROID_STANDALONE_TOOLCHAIN/arm-linux-androideabi/lib/armv7-a -lgnustl_shared" make make install
- We should now have a libthrift.a file in $PREFIX/lib.
Zeromq (optional)
- Download ZeroMQ
wget http://download.zeromq.org/zeromq-3.2.4.tar.gz tar -xvf zeromq-3.2.4.tar.gz cd zeromq-3.2.4
- Turn off Werror. Edit configure by setting libzmq_werror="yes" to no.
# By default compiling with -Werror except OSX. libzmq_werror="no"
- Configure, and build. We turn off libsodium since we haven't built it.
./configure --enable-static --disable-shared --host=arm-linux-androideabi \ --prefix=$PREFIX LDFLAGS="-L$OUTPUT_DIR/lib \ -L$ANDROID_STANDALONE_TOOLCHAIN/arm-linux-androideabi/lib/armv7-a \ -lgnustl_shared" CPPFLAGS="-fPIC -I$PREFIX/include \ -I$ANDROID_STANDALONE_TOOLCHAIN/include/c++/4.8/arm-linux-androideabi/armv7-a" \ LIBS="-lgcc" --with-libsodium=no make make install
- Get the C++ ZMQ header that doesn't come with the normal (C-only) source:
wget -O $PREFIX/include/zmq.hpp https://raw.githubusercontent.com/zeromq/cppzmq/master/zmq.hpp
Support for Radio Front-Ends
Once again, from the previous steps in building up the GNU Radio support, I set up a few environmental variables:
Make sure that ANDROID_STANDALONE_TOOLCHAIN points to the toolchain project we've created; PREFIX points to where we'll install everything; and TOOLCHAIN points to the Android Toolchain cmake file that comes with GNU Radio. These are the examples from what we have been using:
export ANDROID_NDK=/opt/ndk export PATH=$PATH:$ANDROID_NDK export PREFIX=/opt/grandroid export TOOLCHAIN=/cmake/Toolchains/AndroidToolchain.cmake export ANDROID_STANDALONE_TOOLCHAIN=/opt/android-toolchain
libusb
Clone a forked version of the libusb repo that includes a patch for an Android 5 selinux problem:
git clone https://github.com/trondeau/libusb cd libusb git checkout v1.0.19-and5
Now build the libusb-1.0.so from the JNI and make links to it in our prefix:
cd android/jni ndk-build ln -s /android/libs/armeabi-v7a/libusb1.0.so $PREFIX/lib ln -s /libusb $PREFIX/include
RTL-SDR
Clone the trondeau's forked repo that includes a set of patches for Android 5 selinux issues and to work with our patched libusb.
git clone https://github.com/trondeau/rtl-sdr.git cd rtl-sdr git checkout android5
Now build and install using the CMake toolchain:
mkdir build; cd build cmake -DCMAKE_INSTALL_PREFIX=$PREFIX \ -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN \ -DLIBUSB_INCLUDE_DIR=$PREFIX/include/libusb \ -DLIBUSB_LIBRARIES=$PREFIX/lib/libusb1.0.so \ ../
Run this twice. The first time produces an error, but the second time succeeds. Seems to work, though it's probably not the "right thing." (NOTE: add -DTHREADS_PTHREAD_ARG=0. See /opt/code/rtl-sdr/build/TryRunResults.cmake for details. Gist is THREADS_PTHREAD_ARG would be the return code of a demo example)
make make install
UHD
The UHD library requires libusb, so make sure that is built first.
The current support for UHD is still experimental. It only works with a B200 or a B210. The UHD driver will load the firmware and FPGA images onto the device, but there are issues still with permissions. Because the firmware changes how the USRP looks to the OS, the OS needs to get the permissions from the user again. In my test apps, I (annoyingly) run it once to load the firmware, kill the app, and run it a second time. It asks for USB permissions both times, but the second time it will load the FPGA image and start running. So long as the device is powered on, it will keep the firmware and FPGA images so we don't have to do this again. If you have access to wall power, this can help make sure that the device stays programmed.
NOTE When testing on a Nexus 7 tablet, the USB OTG is not able to provide enough power to the B210. Wall power is required for operating this device. The B200 will run off of just the USB cable. Other devices might provide different results.
If you have any issues loading the firmware and/or FPGA images, it might be easier to pre-load them onto the device. To do this, make sure it's plugged into wall power, connect it to a computer, and run uhd_usrp_probe that will load both the firmware and FPGA files. Then you can reconnect the USRP to the Android device's USB port and continue from there.
git clone https://github.com/trondeau/uhd.git cd uhd/host git checkout android mkdir build; cd build cmake -DCMAKE_INSTALL_PREFIX=$PREFIX \ -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN \ -DBOOST_ROOT=$PREFIX \ -DLIBUSB_INCLUDE_DIRS=$PREFIX/include/libusb \ -DLIBUSB_LIBRARIES=$PREFIX/lib/libusb1.0.so \ -DPYTHON_EXECUTABLE=/usr/bin/python \ -DENABLE_STATIC_LIBS=True -DENABLE_USRP1=False \ -DENABLE_USRP2=False -DENABLE_B100=False \ -DENABLE_X300=False -DENABLE_OCTOCLOCK=False \ -DENABLE_TESTS=False -DENABLE_ORC=False \ ../ make make install
Other Info / Older and Obsolete Stuff
Older Boost (1.55) for Android
Originally, we had found this Boost-for-Android repo on github that made it pretty easy to build Android 1.55. More recent versions of Boost, 1.58 at least, have direct support for building Android, and so we have updated the directions. We are keeping these instructions here in case you still wish to use this older method.
Follow these steps:
git clone https://github.com/wuqian/Boost-for-Android.git
- In build-android.sh:
- Change BOOST_VER2=55 (line 31)
- Add "10d (64-bit)" to build-android.sh (line 260)
- change to using the 4.8 toolchain (line 261)
- Building Boost 1.55
cd Boost-for-Android ./build-android.sh --prefix=$PREFIX ln -s $PREFIX/include/boost-1_55/boost $PREFIX/include/boost for f in `ls $PREFIX/lib/libboost*.a`; do ln -s $f ${f%-gcc-mt-1_55.*}.a; done
- In the installed thread_data.hpp file,comment out the include <asm/page.h>
#if defined(__ANDROID__) //#include // http://code.google.com/p/android/issues/detail?id=39983 #endif
' Found: $PREFIX/include/boost/thread/pthread/thread_data.hpp
' Looks like a previous problem with an Andriod NDK no longer applicable to the version we're using.