Software Development Tips and Tricks


Cross-Compiling Node.js for Raspberry Pi

I’ve been working a lot with Z-Wave lately and went out and purchased a RaZberry Z-Wave daughter card module that plugs in to my Raspberry Pi. There’s something more aesthetically pleasing about a snap-on module the size of a couple of postage stamps than a bulky USB stick hanging out there.

The RaZberry comes instructions on how to download a Z-Way server which allows for a nice web UI for including/excluding Z-Wave devices and controlling them. Also included with Z-Way is a JavaScript-based control engine, and I wanted to integrate with the engine.

Unfortunately I’ve already done quite a bit of work with the Python Twisted framework, and didn’t want to rewrite everything using Node.js (and to be honest, I’m not the biggest fan of JavaScript), so decided to take a look at using PyExecJS. After reading a bit it quickly became apparent that PyExecJS needs a runtime and that a popular Javascript runtime is Node.js. So, although I wasn’t willing to rewrite everything, I could at least use the Node.js interpreter to execute JavaScript.

So, I rolled up my sleeves, downloaded Node.js to my Raspberry Pi, ran the configure script followed by make. Unfortunately I got a linker error after waiting a couple of hours and ran into an error that actually is described here. Ugh!

I wasn’t about to start over and wait another two hours (yes, yes, I know make is smart enough not to recompile dependencies if it doesn’t have to), but decided instead, let’s finally do what it takes to get cross-compiling for the Pi working.

First, let’s get the cross-compiler tool chain for a basic Linux x86 PC. I’m running Ubuntu 12, but that shouldn’t matter. It wasn’t too hard to find the GitHub repository for cross-compiler tools, and there’s a nice write-up on how to use them to build the Linx kernel here. I like to keep my filesystem as organized as much possible, so I did

Underneath the tools directory are a number of toolchains, and quite frankly, it was confusing deciding which one to pick. So, I looked at the gcc compiler that comes with the Raspbian distribution on the Pi:

Given the tuple arm-linux-gnueabihf and the fact the RaspberryPi has a 32-bit processor, we choose the toolchain in gcc-linaro-arm-linux-gnueabihf-raspbian. So let’s add that to our path:

Now that we have our cross-compiler let’s try it out on something simple.

#include <stdio.h>

int main (void) {
  printf("Hello, world!n");

Save that into helloworld.c and then (on the x86 PC, mind you):

Of course you can try to execute the resulting binary on the PC, only to be met with cannot execute binary file. So scp it over to your Pi and run:

This is going to save us a lot of time. Note though that cross-compiling is not always this easy. Many times you are compiling larger packages such as OpenCV, libsodium, etc.; packages that come with an output of header files, libraries, executable tools. To navigate those waters you will want to get comfortable with using configure and supplying the --build and --host options. Rather than take the detour now, I’ll post a supplementary example of cross-compiling libsodium for the Pi.

Moving on to cross-compiling node.js, we can follow the instructions at http://n8.io/cross-compiling-nodejs-v0.8/, as they are still relevant, we’ll just be using a later version.

Going back to our /usr/local/src/raspberry/ directory on the PC, let’s clone node straight of its Github repository.

Looking at the various branches (git branch -a) my first inclination was to jump straight to version 0.11.13 with git checkout v0.11.13-release, but unfortunately ran into issues with unresolved symbols at the end of the link stage. Looking back on Issue 8062, I decided to go back and use the release branch mentioned in the post, v0.10. So run git checkout v0.10.

The configure script in the node directory is not an autoconf script, so the cross-compilation technique here is different. You’ll need to set all of the following environment variables in your shell:

Then issue

The configure script does its configuring, and then you should be able to type make -j N where N is the number of cores you have on your system.

After waiting a minute and a half (it seemed like it would never end) I had my cross-compiled node binary.

Place the resulting binary in /usr/bin/ on your Pi and fire up the node console:

Now that we’ve done all this work getting node on the Pi we should take advantage of it. Install PyExecJS on the Pi (using easy_install or pip) and with node in place you should be able to run a few of the examples.

The end goal of this endeavour was to control my Z-Way server with PyExecJS. After rereading the documentation on Z-Way, I’m not entirely sure that’s possible. What it appears like is that you write server-side code JavaScript and drop into a Z-Way folder, which then exposes your routines to the running server. Unfortunately those routines are triggered by calling a webservice. That is, there doesn’t seem to be a way I can take custom JavaScript and run it within my Python code and interact with the Z-Way server. But hey, that’s okay. I now have a nice cross-compile toolchain for the Pi and drastically reduced the amount of time it takes to build custom packages.

One Response to Cross-Compiling Node.js for Raspberry Pi

  1. Giuseppe says:

    Hi! I know this is an old post but I just approached cross-compiling for my raspberry and this was so helpful! I still get an error though so I hope you can help me. When I run ‘make -j 4’ it runs till it says
    ‘../deps/openssl/openssl/crypto/arm_arch.h:46:6: error: #error “unsupported ARM architecture” ‘
    and then exits with Error 2. Can you help me figuring this out?

Leave a Reply

Your email address will not be published. Required fields are marked *