Skip to content
This repository has been archived by the owner on Jun 7, 2023. It is now read-only.

Usage Guide

tjanson edited this page Sep 23, 2014 · 4 revisions

Preparation

First of all, install the dependencies (note the version requirements).

Then clone the rpi-cross repo:

cd some/folder
git clone https://github.com/tjanson/rpi-cross.git
cd rpi-cross

Now, please follow along to get an overview of what’s about to happen.

Vagrantfile and Ansible Playbook

First, take a look at the Vagrantfile (e.g., nano Vagrantfile) and read the comments. Vagrant is a tool that’ll set up a headless VM (that is, a virtual machine without graphical interface) based on these settings.

Done? We’ll continue our tour with provisioning/playbook.yml. This is the meats: a list of state descriptions and commands that Ansible will execute automatically during “provisioning”.

These tasks, listed under tasks (line 40), perfom three functions (besides some basic system maintenance):

  • installing crosstool-NG and building a toolchain based on a CTNG config file
  • unpacking a prebuilt toolchain
  • installing and configuring distcc

You’ll only want either build your own toolchain, or use a prebuilt one (and you’ll be prompted to choose during provisioning). Variables starting with ctng relate to the former, prebuilt_xt to the latter — it’s safe to ignore whatever doesn’t apply to you.

If you don’t know what any of this means, the following should suffice: A toolchain is a set of programs working together to compile software for a certain target architecture, in this case our Raspberry Pi. One of these tools is the gcc compiler, which you probably use on your Pi, but quite a few others are needed in the background. The crosstool-NG docs explain toolchains in detail.

Using the prebuilt tarball linaro-arm-linux-gnueabihf-raspbian.201408.modified.tar.xz is a convenient option, based on the official Raspbian Linaro toolchain, but updated with more recent (possibly unstable) tools. We’ll use it for this guide.

Back at the top of the file, the vars section defines various paths and source files. (Again: The ctng options are for custom building only.)

The following defaults work for us; the tarball will automatically be downloaded if it isn’t already present.

  prebuilt_xt: "/vagrant/prebuilt-toolchains/linaro-arm-linux-gnueabihf-raspbian.201408.modified.tar.xz"
  prebuilt_xt_url: "https://github.com/tjanson/rpi-cross/releases/download/v0.1/linaro-arm-linux-gnueabihf-raspbian.201408.modified.tar.xz"

VM provisioning

Call Vagrant to set up the VM, in the root directory of the project (which contains the Vagrantfile):

vagrant up

This will take a while and prompt you occasionally. Ideally, this will finish successfully. If you encounter any errors, please file an issue.

Okay, that’s it! You can now ssh into your VM:

vagrant ssh

In the new shell, the output of which arm-linux-gnueabihf-gcc should be /home/vagrant/x-tools6h/bin/arm-linux-gnueabihf-gcc, and ls x-tools6h should yield this (or something similar – but definitely not empty):

arm-linux-gnueabihf  bin  bin-tupleless  build.log.bz2  include  lib  libexec  share

In particular, bin-tupleless should be present (and contain symlinks to various tools). Try ./x-tools6h/bin-tupleless/gcc --version. Does it output the gcc version information (numbers will vary), e.g., gcc [...] 4.9.2 [...]?

Finally, check /etc/init.d/distcc status. It should already be running.

Hello, World!

If all that went well, you have a working cross compiler! Let’s try it: Create the following in hello.c:

#include <stdio.h>

int main() {
    printf("Hello World");
    return 0;
}

Cross-compile it with arm-linux-gnueabihf-gcc hello.c -o hello, and check file hello:

hello: ELF 32-bit LSB  executable, ARM, EABI5 …

This program won’t run in the VM — it’s for the Pi! Note the “ARM”. You may copy it to your Pi (e.g., scp hello pi@raspberry:~), and try it.

Using distcc to delegate compilation from your Pi

Finally, you can use distcc to off-load compilation from your Pi to the rpi-cross VM. We’ll try a real world example: Compiling Node.js.

On your Raspberry Pi (presumably running Raspbian), install distcc. And while we’re at it git and python2, if not already present, which we’ll need for Node:

sudo apt-get install distcc distcc-pump
sudo apt-get install git python2.7

Clone the Node repository. We’ll take a walk on the wild side and checkout the v0.10 dev branch. (There’s actually a good reason: We need the as of yet unreleased fix for #8062.)

git clone https://github.com/joyent/node.git
cd node
git checkout v0.10

Then set the following environment variables:

export DISTCC_HOSTS=vagrant-ubuntu-trusty-64,cpp,lzo
export DISTCC_SKIP_LOCAL_RETRY=1 ; export DISTCC_FALLBACK=0
export DISTCC_VERBOSE=1
export PATH=/usr/lib/distcc:${PATH}

From the top:

  1. Add our VM as a distcc compilation slave capable of compression and pump mode (substitute the IP if your network doesn’t resolve hostnames)
  2. Disable local compilation if distributed compilation fails, or if no slave is available. If it does fail, we want to be aware of it.
  3. Lots of debug output.
  4. Alter the PATH (temporarily) to include the distcc masquerading directory, which contains “decoys” of gcc, which in fact point to distcc. Thus, if a Makescript or similar calls the compiler, the distcc wrapper will take over.

Even more env vars for building Node. I’ve taken them from Nodejs-ARM-Builder, which was actually the inspiration for rpi-cross (thanks!).

export CCFLAGS="-march=armv6j -mfpu=vfp -mfloat-abi=hard -DUSE_EABI_HARDFLOAT"
export CXXFLAGS="-march=armv6j -mfpu=vfp -mfloat-abi=hard -DUSE_EABI_HARDFLOAT"
export OPENSSL_armcap=6
export GYPFLAGS="-Darmeabi=hard -Dv8_use_arm_eabi_hardfloat=true -Dv8_can_use_vfp3_instructions=false -Dv8_can_use_vfp2_instructions=true -Darm7=0 -Darm_vfp=vfp"
export VFP3=off
export VFP2=on
PREFIX_DIR="/usr/local"

Finally, ready to go: Configure, and make!

./configure --without-snapshot --dest-cpu=arm --dest-os=linux --prefix="${PREFIX_DIR}"
make -j4

(You may experiment with the -j value.) The important point, though, is that a ton of distcc debug output should be scrolling across your screen. On the rpi-cross VM, sudo tail -f /var/log/distccd.log should bear witness to successful compilations thusly:

distccd[32620] (dcc_job_summary) client: 192.168.1.176:59815 COMPILE_OK exit:0 sig:0 core:0 ret:0 time:12113ms g++ ../src/node_crypto.cc

Once finished (it’ll take a while, even with rpi-cross), ./out/Release/node -v should respond with Node’s version. You can install it, if you wish:

sudo make -j4 install CC=distcc CXX=distcc

What’s that CC=… stuff you ask? I’m not sure why, actually, but masquerading fails here, and specifying distcc as the compiler works. (Let me know if you know.)

This concludes the guide — I hope you found it useful!