Icecream Scratchbox Howto

Original instructions written by Anderson Lizardo.

Contents

[edit] Icecream + Scratchbox HOWTO

NB: With some Scratchbox versions, distributed arm target compilations occasionally fail due to gcc/g++ targeting wrong ARM variant. Once a workaround is developed, this warning will disappear.

From Icecream web page [1]:

"Icecream is created by SUSE and is based on ideas and code by distcc. Like distcc it takes compile jobs from your build and distributes it to remote machines allowing a parallel build on several machines you've got."

This document describes how to use icrecream for parallel compilation inside Scratchbox.

[edit] Prerequisites

Skip this section if you have a working Icecream setup on your network.

Before attempting to use icecc with Scratchbox, be absolutely certain it runs without any issues on the host itself (and that the processes migrate properly in the network). Basic Icecream installation includes once machine running the scheduler and every participating host running the icecc daemon.

On Ubuntu, a basic Icecream setup can be achieved by installing the package icecc on every participating host. On the scheduler, modify /etc/default/icecc to enable the scheduler daemon. If some host can't find the scheduler, modify /etc/icecc/icecc.conf to explicitly set the scheduler hostname.

Make sure the host sees the scheduler by running icemon (package icecc-monitor on Ubuntu). You can leave icemon running to observe the task migration during compilations.

To enable automatic distributed compilations on the host OS in Ubuntu, add the following snippet to $HOME/.bashrc:

# set the ICECC version and enable it by default
. /etc/lsb-release
procfamily=$(uname -m)
icecc_tarball="$(readlink -f $HOME/icecc/icecc-$procfamily-$DISTRIB_CODENAME.tar.gz)"
if [ -f "$icecc_tarball" ]; then
    export ICECC_VERSION=$icecc_tarball
    export PATH=/usr/lib/icecc/bin:$PATH
    export DEB_BUILD_OPTIONS=$DEB_BUILD_OPTIONS,parallel=12
fi
unset icecc_tarball procfamily DISTRIB_ID DISTRIB_RELEASE DISTRIB_CODENAME DISTRIB_DESCRIPTION

Note that on other distributions than Ubuntu, you might have to modify this, depending on the contents on /etc/lsb-release.

Also note the "parallel=N" parameter being added to DEB_BUILD_OPTIONS. This enables parallel builds (limited to N parallel jobs) for those packages that support it. Alternatively, if you are doing your own builds by calling "make", you should instead pass the "-jN" parameter to enable parallel builds, e.g. "make -j12".

Then, create directory $HOME/icecc and run
icecc --build-native
there. Symlink the created tarball to a descriptive name, e.g. icecc-i686-karmic.tar.gz (this name has to match the $icecc_tarball variable in the .bashrc snippet above).

Now, open a new terminal and ensure that $ICECC_VERSION variable is set. Then run a test compilation to see that the compilation tasks really migrate to other hosts.

Do not proceed beyond this point before you have made a test compilation and seen that your Icecream setup works as intended.

[edit] Compiling icecc

To be able to use icecc both on ARM and x86 targets, we need to compile it use the "special" host-gcc and host-g++ compilers inside a scratchbox target. The binaries generated by these compilers can then be run from any target, because they link to scratchbox own libraries.

We will use only the icecc client, and share the icecc daemon with the host. This allows using icecc both inside and outside scratchbox.

To compile icecc, enter a scratchbox target (the architecture set on it is not important) and unpack the icecc source tarball (you can download it from [2]). Next, enter the source directory and run:

sbox > ./configure --prefix=/scratchbox/tools CC=host-gcc CXX=host-g++
sbox > make

[edit] Installing icecc

The next commands should be done outside scratchbox, as root.

Copy the "client/icecc" binary to /scratchbox/tools/bin and a "icecc++" symlink necessary for compiling C++ programs:

host# cp -a client/icecc /scratchbox/tools/bin/icecc
host# ln -sfn icecc /scratchbox/tools/bin/icecc++

[edit] Preparing toolchain tarballs

To make sure that the correct compiler is used, it is necessary to create a tarball containing all files required by the toolchain. This can be done either manually, or by using the "icecc_create_env_sbox.sh" script.

  1. Download icecc_create_env_sbox.sh script.
  2. (Optional) Edit the script and change the "sbox_dir" variable, in case your scratchbox is not installed in /scratchbox
  3. Run the script for each target you wish to use icecc for. E.g.:
  4. host$ ./icecc_create_env_sbox.sh FREMANTLE_ARMEL
    host$ ./icecc_create_env_sbox.sh FREMANTLE_X86
    

For each run, two files will be created:

  • a tarball named <md5>.tar.gz, where <md5> is the MD5 signature of the tarball contents.
  • a symbolic link to this tarball, named "icecc_box-<compiler_name>.tar.gz"

Place the tarballs in $HOME/icecc inside Scratchbox. These tarballs will be used later when running icecc. It is important that they uniquely identify the toolchain, because all peers in the build network will use the same tarball, and will cache the toolchain locally using that name. Therefore we use the MD5 signature, plus a symlink to easily map it to the actual Scratchbox toolchain name.

[edit] Using icecc

In order to run icecc, you need to set the ICECC_VERSION environment variable to point to the tarball created in previous section. Note that this variable will be set to different values, depending on which target icecc will run (ARM or x86).

The ICECC_VERSION variable has the following format:

<build_architecture>:<cross_toolchain_for_target>

Hint:

You can add the following snippet to ~/.bashrc (inside scratchbox) and have that variable set automatically to the right value (change tarball names and path accordingly):

sbox_compiler="$(sb-conf show --compiler)"
# use the tarball name with the MD5, avoiding conflicting names in peer caches
icecc_tarball="$(readlink -f $HOME/icecc/icecc_sbox-$sbox_compiler.tar.gz)"
if [ -f "$icecc_tarball" ]; then
    export ICECC_VERSION="i486:$icecc_tarball"
    # comment the following line if you don't want to build in parallel by default
    export MAKEFLAGS="-j12"
fi
unset icecc_tarball sbox_compiler

Done! To effectively use icecc to compile code, set the compiler to "icecc". This is usually done by setting the CC and CXX environment variables.

[edit] Using icecc "transparently" under Scratchbox

Modifying build systems to use "icecc" instead of the defaults g++/gcc can be error prone. Therefore, the following instructions can be used to make it transparent:

  1. Create a "/host_usr/bin" directory if it does not exist already:
  2. sbox > mkdir -p /host_usr/bin

    (This directory is automatically added by Scratchbox to beginning of the PATH, therefore it is not necessary to add it manually.)

  3. Create "gcc" and "g++" symlinks into that directory, pointing to icecc:
  4. sbox > ln -sfn /scratchbox/tools/bin/icecc /host_usr/bin/gcc
    sbox > ln -sfn /scratchbox/tools/bin/icecc++ /host_usr/bin/g++
    
  5. Disable Scratchbox redirection for the gcc and g++ binaries:
  6. sbox > export SBOX_REDIRECT_IGNORE=/usr/bin/gcc,/usr/bin/g++
    

The snippet above can be placed in .bashrc as well.

You can now build applications normally and they will automatically use icecc when calling gcc or g++.

[edit] References

  1. http://en.opensuse.org/Icecream
  2. ftp://ftp.suse.com/pub/projects/icecream/