Cross-compiling for the Raspberry Pi, Evolved

May 13, 2015

Cross-compilation process evolution

In previous posts, Luis taught us how to cross-compile for the Raspberry Pi. In this post, we’ll discuss an evolved approach for cross-compiling for the Raspberry Pi and Raspberry Pi 2.

The cross-compiling process for this ARM platform from an x86_64 host is now greatly simplified. Also, we can now run the test suite! wOOt!

While cross-compiling, the following improvements are notable, some of which are specific to ITK.

1) The toolchain is a single command away

As discussed in a previous post, Docker is a great, cross-platform way to download and run pre-built and configured toolchains.

 

2) No need to populate a Toolchain.cmake file

Since we used a Docker image that is pre-configured with its own toolchain file, we only need to do is pass CMake the path to this single file, and CMake is informed of all it needs to know about the toolchain.

 

3) No need to populate a TryRunResults.cmake file

CMake gets information specific to the target system with the try_run command. When cross-compiling, access to the target system is not available. By default, CMake will output a TryRunResults.cmake that must be populated by transferring the try_run executables over to the target system, running the commands, and entering the output and return value in this file. This file must then be transferred back to the build host, and then the TryRunResults.cmake are read by CMake before the build process can be continued.

In this case, this entire process is now avoided when a CMAKE_CROSSCOMPILING_EMULATOR is configured in the toolchain file. This emulator is used to run the try_run executables, and the build configuration process proceeds automatically without any user intervention required. The QEMU user-mode emulator is applied for this task.

 

4) No need for TIFF and HDF5 workarounds

ITK has been improved so the internal third-party library builds of TIFF and HDF5 no longer require manual intervention.

 

5) Build all the things

All the default ITK modules, and their tests, now build without issue.

 

6) Run the test suite

The test suite can also be run on the build host. CMAKE_CROSSCOMPILING_EMULATOR will be used to run all tests that use executables built for the target system.

 

7) No Pi required

We don’t actually need a physical Raspberry Pi to develop for one.

 

Get the cross-compiler

If Docker is installed, download the cross-compiler image. This cross-compiler with work will 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

 

Build and test!

Start up a docker container, and mount the source and build directories 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 \
  thewtex/cross-compiler-linux-armv6

The –rm flag tells Docker to remove the image after we exit. The -it flag tells Docker to start up an interactive terminal. Our Docker image is configured to drop us into a new bash shell by default. Next, clear the build tree and configure the build:

cd /usr/src/ITK-build
rm -rf *
cmake \
  -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} \
  -DBUILD_EXAMPLES=OFF \
  -G Ninja \
  ../ITK

The Docker image is configured to set the path to the toolchain file in the CMAKE_TOOLCHAIN_FILE environmental variable. We set BUILD_EXAMPLES to OFF because the test driver executable, used to test the examples, spawns a process to run the example. QEMU does not currently support this, even though the examples build fine. We also tell CMake to use our favorite generator, Ninja.

Next, we will run an Experimental ctest build. CTest does a CMake configuration, executes the build, runs the tests, and submits the results to the CDash dashboard. QEMU user-mode currently is limited in its multi-threading capabilities, so run the tests in single-threaded mode by setting the ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS environmental variable:

export ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS=1
ctest -j $(nproc) -D Experimental

 

Create applications

We can build applications against ITK in a similar way. To build this example:

wget http://itk.org/ITKExamples/src/Core/Common/BuildAHelloWorldProgram/BuildAHelloWorldProgram.tar.gz
tar xvzf BuildAHelloWorldProgram.tar.gz
cd BuildAHelloWorldProgram/build
cmake \
  -G Ninja \
  -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} \
  -DCMAKE_BUILD_TYPE=Release \
  -DITK_DIR=/usr/src/ITK-build \
  ..
ninja

ctest -V

 

Happy hacking!

6 comments to Cross-compiling for the Raspberry Pi, Evolved

  1. Make Error: The source directory “/usr/src/ITK” does not appear to contain CMakeLists.txt.
    Specify –help for usage, or press the help button on the CMake GUI.

    Running on Ubuntu 15.10 (64 bit)
    Instructions worked fine up to:
    cmake
    -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
    -DBUILD_EXAMPLES=OFF
    -G Ninja
    ../ITK

    Please supply the missing file or tell me what I did wrong.
    Many thanks.

  2. When the ‘docker run’ command was executed, was

    -v ~/src/ITK:/usr/src/ITK:ro

    used as listed? Does ~/src/ITK/ on the host contain the ITK source code tree?

  3. Thank you Matt for the refreshingly quick response!

    The problem was that I did not have the ITK source code tree.

    I am now able to get all the way through although quite a few tests had errors. If you would like to see the output from the terminal session I can send it to you. Jeff

  4. I have not yet gotten Create applications to work.
    Please post the terminal output for this step.
    Thanks.

  5. There are currently still some warnings and tests to fix for this platform. See the expected build status on the Nightly dashboard:

    https://open.cdash.org/index.php?project=Insight&filtercount=1&showfilters=1&field1=buildname/string&compare1=63&value1=ARMv6-CrossCompile

    There was a error in the “Create applications” section — the “-G Ninja” flag needs to be passed during CMake configuration to use the Ninja generator. As a result, the build command would be the default “make” instead of “ninja”. The post has been updated.

    Enjoy ITK!

  6. Pingback: Jenkins and Unit Testing with Google Test on raspberry pi | Open Source Solutions

Leave a Reply