Sagar Behere

I doubt, therefore I might be

(Yet another) Guide to cross-compiling the orocos-toolchain

This document describes one method to cross-compile the orocos toolchain. Unlike my previous method, the method described in this document does not make it necessary to cross-compile any of the supporting software libraries needed by orocos, like boost, libxml2 etc.

The method has been tested on hosts running Debian 7.0 (Wheezy), both amd64 and i386. The target computer (armel) is running the same Debian version. It is unlikely that this method will work on other distributions, but feel free to try ;-)

As of now, you cannot cross-compile typelib, corba and mqueue transports of any typekit you make. This is due to a limitation of the typelib build system, which is in the process of getting fixed. See this discussion and the Tips section below.

Step 1: Add the emdebian repo

Reference: http://wiki.debian.org/EmdebianToolchain

apt-get install emdebian-archive-keyring
cat "deb http://www.emdebian.org/debian squeeze main" > /etc/apt/sources.list.d/emdebian.sources.list
apt-get update

Step 2: Cross-compiler toolchain and libraries

apt-get install g++-4.4-arm-linux-gnueabi gcc-4.4-arm-linux-gnueabi
apt-get install xapt
xapt -a armel -m libboost1.49-dev libboost-thread1.49-dev libboost-program-options1.49-dev libboost-filesystem1.49-dev libboost-iostreams1.49-dev libboost-graph1.49-dev libboost-regex1.49-dev libboost-system1.49-dev libxml2-dev libreadline6-dev libncurses5-dev libomniorb4-dev

Now you may need to do the following tweaks

  • Fix broken package dependencies

    aptitude install

This will probably tell you something like

The following packages have unmet dependencies:
g++-4.4-arm-linux-gnueabi : Depends: libstdc++6-4.4-dev-armel-cross (= 4.4.5-8) but 4.4.7-2 is installed.

it will offer to remove that package, but do not choose that solution when it says, "Accept this solution?" (press n). Then it'll offer to remove g++-4.4-armel-cross and downgrade listdc++-6-4.4-dev-armel-cross to 4.4.5-8 (stable). Accept this solution. Verify that no packages are broken with

aptitude install
  • You may have to

    cd /usr/arm-linux-gnueabi/lib; ln -s libstdc++.so.6.0.17 libstdc++.so

You may also have to set some symlinks in /usr/arm-linux-gnueabi/include/c++. For example, I had to

cd /usr/arm-linux-gnueabi/include/c++
ln -s 4.4 4.4.5;
  • You may have to replace all occurrences of TIME_UTC with TIME_UTC_ in /usr/arm-linux-gnueabi/include/boost/thread/xtime.hpp but hold off this step until the subsequent orocos-toolchain compilation process stops with an error related to xtime.hpp

Optional Step: Cross-compile xenomai

Skip this step if you are not going to use xenomai

cd <xenomai source dir>
./configure --host=arm-linux-gnueabi --prefix=/path/to/orocos-armel/install;
make && make install

NOTE: /path/to/orocos-armel is where you will install the cross-compiled version of the orocos-toolchain in a subsequent step.

Optional step: qemu user emulation

This enables your host computer to transparently execute arm binaries

Reference: http://wiki.debian.org/QemuUserEmulation

apt-get install qemu binfmt-support qemu-user-static

(Verify successful registration of formats with:)
update-binfmts --display add the line
EXTRA_OPTS="-L /usr/arm-linux-gnueabi" to /etc/qemu-binfmt.conf (create it if necessary)
cd /etc/qemu-binfmt/ ln -s /usr/arm-linux-gnueabi arm;

Step 3: Create cmake toolchain file

Reference: http://www.cmake.org/Wiki/CMake_Cross_Compiling

Add the following to a file and save it in $HOME/Toolchain-arm-linux-gnueabi.cmake

# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 1)

# specify the cross compiler
SET(CMAKE_C_COMPILER   /usr/bin/arm-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabi-g++)

# where is the target environment 
SET(CMAKE_FIND_ROOT_PATH /path/to/orocos-armel/install  /usr/arm-linux-gnueabi)

# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Note especially the line

SET(CMAKE_FIND_ROOT_PATH /path/to/orocos-armel/install  /usr/arm-linux-gnueabi)

Edit the /path/to/orocos-armel/install as appropriate. This line tells CMake where to look for the cross-compiled libraries and its includes, and these paths are prepended to the regular CMake search path. It is important that these paths come BEFORE the regular search paths, else there is a chance of CMake picking up and using the native system libraries. The risk of this happening can be further lowered by the lines

SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

which tell CMake to not look anythere except the specified paths for its headers and libs.

Step 4: (Cross+)Compile orocos-toolchain

First, we do a native install of the orocos toolchain. This will give us the orogen/typegen tools which we cannot build during the cross-compile.

Reference: http://www.orocos.org/wiki/orocos/toolchain/quick-start-linux

cd /path/to/orocos-native;
wget http://gitorious.org/orocos-toolchain/build/blobs/raw/toolchain-2.6/bootstrap.sh
sh bootstrap.sh
source env.sh
echo "source /path/to/orocos-native/env.sh" >> $HOME/.bashrc

Now we build the cross-compiled version.

cd /path/to/orocos-armel;
wget http://gitorious.org/orocos-toolchain/build/blobs/raw/toolchain-2.6/bootstrap.sh

Now edit bootstrap.sh and comment out the lines at the end as follows (this is intended to interrupt the bootstrapping process, so we can tweak some parameters. If this is not done, then a native install will occur.)

#autoproj update || tellfailupdate
#autoproj fast-build || tellfailbuild

Now do the bootstrap sh bootstrap.sh

Edit the /path/to/orocos-armel/autoproj/manifest file ad comment out the orogen under the layouts section. This disables compilation of orogen. The layout section should look like

layout:
   - typelib
   - utilrb
   - utilmm
   - log4cpp
   - rtt
   - rtt_typelib
#   - orogen
   - ocl

The various software packages in the toolchain are built using CMake and we need to tell CMake to use the cross-toolchain. This is done by passing the flag

-DCMAKE_TOOLCHAIN_FILE=/path/to/cross-toolchain/file

to CMake. To pass this flag everytime a package is built with CMake, add the following lines to $HOME/orocos/autoproj/overrides.rb (This information comes thanks to Thomas Roehr)

Note: Edit the path to the cross-toolchain file according to your setup.

Autobuild::Package.each do |name, pkg|
if pkg.kind_of?(Autobuild::CMake)
pkg.define "CMAKE_TOOLCHAIN_FILE","/home/sagar/Toolchain-arm-linux-gnueabi.cmake"
end
end

That's all. Now build the cross-toolchain as usual with source /path/to/orocos-armel/env.sh autoproj update autoproj build echo "source /path/to/orocos-armel/env.sh" >> $HOME/.bashrc

Tips

  • My $HOME/.bashrc has

the following lines

source /home/sagar/excludes/orocos-native/env.sh
source /home/sagar/excludes/armel-orocos/env.sh
  • If you create a typekit with
    orocreate-pkg MyTypekit typekit

Then you should know that the corba transport will NOT compile. This is probably due to the hosts omniidl being used or some such issue. Also, the typelib thingys will compile, but will probably cause the deployer to segfault on the target. As recommended by this discussion on the mailing list you should disable compilation of corba, mqueue and typelib. You can do this by editing the top level CMakeLists.txt file in the generate typekit folder. Find the line that starts with "orocos_typegen_headers(src/..." and edit it as

orocos_typegen_headers(-n corba,typelib,mqueue src/...