Cross-compile ITK’s Python Wrapping for the Raspberry Pi 2

This post describes how to cross-compile the Insight Toolkit (ITK)'s Python wrapping for the Raspberry Pi 2. The default operating system on the Raspberry Pi 2 is Raspbian, a Debian-based Linux distribution. While Debian provides packages for ITK., these packages are not currently available on Raspbian. We will create a Debian package optimized for the Raspberry Pi 2 that can be installed and uninstalled on our Pi. The process is similar to the previous post on cross-compiling for the Raspberry Pi, with the following additions:

  1. Optimization flags specific to the Raspberry Pi 2.
  2. Build wrapping against the Raspbian Python installation.
  3. Create a Debian package.

Let's go!

Image credit: the PyScience blog

Get the cross-compiler

If Docker is installed, download the cross-compiler image. This cross-compiler with work with both the Raspberry Pi and the Raspberry Pi 2, even though Raspberry Pi is ARMv7.

docker pull thewtex/cross-compiler-linux-armv6

 

Get the code

Download the ITK source tree if it not already available, and create a build directory:

cd ~/src
git clone http://itk.org/ITK.git
mkdir -p ~/bin/ITK-build

We also need the Python headers and library from the Pi so we can compile and link against them. We will log into the Pi, create a tarball of the needed files and directories, and transfer that tarball to the build host.

ssh pi@raspberrypi
sudo apt-get install python-dev
tar cvzf raspbian-python.tar.gz \
  /usr/include/python2.7 \
  /usr/lib/python2.7 \
  /usr/lib/libpython2.7.*
exit
scp pi@raspberrypi:raspbian-python.tar.gz /tmp/
mkdir -p ~/bin/raspbian-python
tar xvzf /tmp/raspbian-python.tar.gz -C ~/bin/raspbian-python/

 

Build and package

Start up the docker container, and mount the source directory, build directory, and Python filesystem directory as volumes in the container:

docker run --rm -it \
  -v ~/src/ITK:/usr/src/ITK:ro \
  -v ~/bin/ITK-build:/usr/src/ITK-build:rw \
  -v ~/bin/raspbian-python:/usr/src/raspbian-python:ro \
  thewtex/cross-compiler-linux-armv6

Next, clear the build tree and configure the build:

cd /usr/src/ITK-build
rm -rf *
export flags='-mfpu=neon-vfpv4 -mcpu=cortex-a7 -mfloat-abi=hard'
cmake \
  -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} \
  -DBUILD_EXAMPLES=OFF \
  -DBUILD_TESTING=OFF \
  -DITK_WRAP_PYTHON=ON \
  -DPYTHON_LIBRARY=/usr/src/raspbian-python/usr/lib/libpython2.7.so.1 \
  -DPYTHON_INCLUDE_DIR=/usr/src/raspbian-python/usr/include/python2.7/ \
  -DPY_SITE_PACKAGES_PATH=lib/python2.7/dist-packages \
  -DCMAKE_CXX_FLAGS="${flags}" \
  -DCMAKE_C_FLAGS="${flags}" \
  -DCMAKE_CXX_COMPILER_TARGET=${CROSS_TRIPLE} \
  -DCMAKE_INSTALL_PREFIX=/usr/ \
  -DCPACK_DEBIAN_PACKAGE_NAME=libinsighttoolkit4.8 \
  -DCPACK_DEBIAN_PACKAGE_ARCHITECTURE=armhf \
  -G Ninja \
  ../ITK

The CMAKE_TOOLCHAIN_FILE option informs CMake about the build toolchain. BUILD_EXAMPLES, BUILD_TESTING, and ITK_WRAP_PYTHON are options for ITK. PYTHON_LIBRARY and PYTHON_INCLUDE_DIR inform CMake of the Python we want to build against. PY_SITE_PACKAGES_PATH tells CMake where to install the Python package. The value used, lib/python2.7/dist-packages, is obtained by running the following command on the Pi:

python -c "from distutils.sysconfig import get_python_lib;print(get_python_lib(1, prefix=''))"

Optimization flags to use features available on the Raspberry Pi 2 processor are passed with the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS options. The cross-compiling target triple, used by the wrapping system, is passed via the CMAKE_CXX_COMPILER_TARGET through the value of the CROSS_TRIPLE enviromental variable. CMAKE_INSTALL_PREFIX, CPACK_DEBIAN_PACKAGE_NAME, and CPACK_DEBIAN_PACKAGE_ARCHITECTURE are options for creating the Debian package. We also tell CMake to use our favorite generator, Ninja.

Build the library:

ninja

Build the package:

cpack -G DEB

This generates a .deb package. Copy it to the Pi:

scp ITK-4.8.0-Linux.deb pi@raspberrypi:

And install it:

ssh pi@raspberrypi
sudo dpkg -i ITK-4.8.0-Linux.deb

Start up Python, and import the itk package:

python
>>> import itk

Enjoy ITK!

Questions or comments are always welcome!