{"id":505,"date":"2014-08-30T15:45:28","date_gmt":"2014-08-30T21:45:28","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=505"},"modified":"2014-08-30T15:45:28","modified_gmt":"2014-08-30T21:45:28","slug":"cross-compiling-node-js-for-raspberry-pi","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/cross-compiling-node-js-for-raspberry-pi\/","title":{"rendered":"Cross-Compiling Node.js for Raspberry Pi"},"content":{"rendered":"<p>I&#8217;ve been working a lot with Z-Wave lately and went out and purchased a <a href=\"http:\/\/razberry.z-wave.me\/\">RaZberry<\/a> Z-Wave daughter card module that plugs in to my Raspberry Pi.  There&#8217;s something more aesthetically pleasing about a snap-on module the size of a couple of postage stamps than a <a href=\"http:\/\/www.amazon.com\/Aeon-Labs-DSA02203-ZWUS-Z-Wave-Z-Stick\/dp\/B003MWQ30E\/ref=sr_1_2?ie=UTF8&#038;qid=1409224125&#038;sr=8-2&#038;keywords=aeon+z-wave\">bulky USB stick<\/a> hanging out there.<\/p>\n<p>The RaZberry comes instructions on how to download a <a href=\"http:\/\/razberry.z-wave.me\/index.php?id=24\">Z-Way server<\/a> 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.<\/p>\n<p>Unfortunately I&#8217;ve already done quite a bit of work with the Python <a href=\"https:\/\/twistedmatrix.com\/trac\/\">Twisted<\/a> framework, and didn&#8217;t want to rewrite everything using <a href=\"http:\/\/nodejs.org\/\">Node.js<\/a> (and to be honest, I&#8217;m not the biggest fan of JavaScript), so decided to take a look at using <a href=\"https:\/\/pypi.python.org\/pypi\/PyExecJS\">PyExecJS<\/a>.  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&#8217;t willing to rewrite everything, I could at least use the Node.js interpreter to execute JavaScript.<\/p>\n<p>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 <a href=\"https:\/\/github.com\/joyent\/node\/issues\/8062\">here<\/a>.  Ugh!<\/p>\n<p>I wasn&#8217;t about to start over and wait another two hours (yes, yes, I know <code>make<\/code> is smart enough not to recompile dependencies if it doesn&#8217;t have to), but decided instead, let&#8217;s <i>finally<\/i> do what it takes to get cross-compiling for the Pi working.<\/p>\n<p>First, let&#8217;s get the cross-compiler tool chain for a basic Linux x86 PC.  I&#8217;m running Ubuntu 12, but that shouldn&#8217;t matter.  It wasn&#8217;t too hard to find the GitHub repository for cross-compiler tools, and there&#8217;s a nice write-up on how to use them to build the Linx kernel <a href=\"http:\/\/www.raspberrypi.org\/documentation\/linux\/kernel\/building.md\">here<\/a>.  I like to keep my filesystem as organized as much possible, so I did<\/p>\n<pre>\r\nsudo su\r\ncd \/usr\/local\/src\/\r\nmkdir raspberry\r\ncd raspberry\r\ngit clone https:\/\/github.com\/raspberrypi\/tools\r\n<\/pre>\n<p>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:<\/p>\n<pre>\r\nroot@raspberrypi:\/home\/pi# gcc -v\r\nUsing built-in specs.\r\nCOLLECT_GCC=gcc\r\nCOLLECT_LTO_WRAPPER=\/usr\/lib\/gcc\/arm-linux-gnueabihf\/4.6\/lto-wrapper\r\nTarget: arm-linux-gnueabihf\r\nConfigured with: ..\/src\/configure -v --with-pkgversion='Debian 4.6.3-14+rpi1' --with-bugurl=file:\/\/\/usr\/share\/doc\/gcc-4.6\/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=\/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=\/usr\/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=\/usr\/include\/c++\/4.6 --libdir=\/usr\/lib --enable-nls --with-sysroot=\/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf\r\nThread model: posix\r\ngcc version 4.6.3 (Debian 4.6.3-14+rpi1) \r\n<\/pre>\n<p>Given the tuple <code>arm-linux-gnueabihf<\/code> and the fact the RaspberryPi has a 32-bit processor, we choose the toolchain in <code>gcc-linaro-arm-linux-gnueabihf-raspbian<\/code>.  So let&#8217;s add that to our path:<\/p>\n<pre>\r\nexport PATH=\/usr\/local\/src\/raspberry\/tools\/arm-bcm2708\/gcc-linaro-arm-linux-gnueabihf-raspbian\/bin:$PATH\r\n<\/pre>\n<p>Now that we have our cross-compiler let&#8217;s try it out on something simple.<\/p>\n<p>[c]<br \/>\n#include &lt;stdio.h&gt;<\/p>\n<p>int main (void) {<br \/>\n  printf(&quot;Hello, world!\\n&quot;);<br \/>\n}<br \/>\n[\/c]<\/p>\n<p>Save that into <code>helloworld.c<\/code> and then (on the x86 PC, mind you):<\/p>\n<pre>\r\narm-linux-gnueabihf-gcc -o helloworld helloworld.c\r\n<\/pre>\n<p>Of course you can try to execute the resulting binary on the PC, only to be met with <code>cannot execute binary file<\/code>.  So <code>scp<\/code> it over to your Pi and run:<\/p>\n<pre>\r\npi@raspberrypi:\/home\/pi# .\/helloworld\r\nHello, world!\r\n<\/pre>\n<p>This is going to save us a <i>lot<\/i> 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 <code>configure<\/code> and supplying the <code>--build<\/code> and <code>--host<\/code> options.  Rather than take the detour now, I&#8217;ll post a supplementary example of cross-compiling <a href=\"https:\/\/github.com\/jedisct1\/libsodium\">libsodium<\/a> for the Pi.<\/p>\n<p>Moving on to cross-compiling <code>node.js<\/code>, we can follow the instructions at <a href=\"http:\/\/n8.io\/cross-compiling-nodejs-v0.8\/\">http:\/\/n8.io\/cross-compiling-nodejs-v0.8\/<\/a>, as they are still relevant, we&#8217;ll just be using a later version.<\/p>\n<p>Going back to our <code>\/usr\/local\/src\/raspberry\/<\/code> directory on the PC, let&#8217;s clone <code>node<\/code> straight of its Github repository.<\/p>\n<pre>\r\ncd \/usr\/local\/src\/raspberry\r\ngit clone https:\/\/github.com\/joyent\/node\/\r\ncd node\r\n<\/pre>\n<p>Looking at the various branches (<code>git branch -a<\/code>) my first inclination was to jump straight to version 0.11.13 with <code>git checkout v0.11.13-release<\/code>, but unfortunately ran into issues with unresolved symbols at the end of the link stage.  Looking back on <a href=\"https:\/\/github.com\/joyent\/node\/issues\/8062\">Issue 8062<\/a>, I decided to go back and use the release branch mentioned in the post, v0.10.  So run <code>git checkout v0.10<\/code>.<\/p>\n<p>The <code>configure<\/code> script in the node directory is <i>not<\/i> an autoconf script, so the cross-compilation technique here is different.  You&#8217;ll need to set all of the following environment variables in your shell:<\/p>\n<pre>\r\nexport AR=arm-linux-gnueabihf-ar\r\nexport CC=arm-linux-gnueabihf-gcc\r\nexport CXX=arm-linux-gnueabihf-g++\r\nexport LINK=arm-linux-gnueabihf-g++\r\n<\/pre>\n<p>Then issue<\/p>\n<pre>\r\n.\/configure --without-snapshot --dest-cpu=arm --dest-os=linux\r\n<\/pre>\n<p>The <code>configure<\/code> script does its configuring, and then you <i>should<\/i> be able to type <code>make -j N<\/code> where N is the number of cores you have on your system.<\/p>\n<p>After waiting a minute and a half (it seemed like it would never end) I had my cross-compiled node binary.<\/p>\n<pre>\r\nmake[1]: Leaving directory `\/usr\/local\/src\/raspberry\/node\/out'\r\nln -fs out\/Release\/node node\r\n\r\nreal\t1m29.227s\r\nuser\t9m23.913s\r\nsys\t0m45.459s\r\n<\/pre>\n<p>Place the resulting binary in <code>\/usr\/bin\/<\/code> on your Pi and fire up the <code>node<\/code> console:<\/p>\n<pre>\r\n> theAnswer = 42;\r\n42\r\n> console.log(\"And the answer is... %d\", theAnswer);\r\nAnd the answer is... 42\r\n<\/pre>\n<p>Now that we&#8217;ve done all this work getting node on the Pi we should take advantage of it.  Install <a href=\"https:\/\/pypi.python.org\/pypi\/PyExecJS\">PyExecJS<\/a> on the Pi (using <code>easy_install<\/code> or <code>pip<\/code>) and with <code>node<\/code> in place you should be able to run a few of the examples.<\/p>\n<pre>\r\nroot@raspberrypi:~# python\r\nPython 2.7.3 (default, Mar 18 2014, 05:13:23) \r\n[GCC 4.6.3] on linux2\r\nType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\r\n>>> import execjs\r\n>>> execjs.eval(\"'red yellow blue'.split(' ')\")\r\n[u'red', u'yellow', u'blue']\r\n>>> \r\n<\/pre>\n<p>The end goal of this endeavour was to control my Z-Way server with PyExecJS.  After rereading the documentation on Z-Way, I&#8217;m not entirely sure that&#8217;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&#8217;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&#8217;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.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;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&#8217;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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14,13],"tags":[],"class_list":["post-505","post","type-post","status-publish","format-standard","hentry","category-node-js","category-raspberry-pi"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/505"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=505"}],"version-history":[{"count":25,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/505\/revisions"}],"predecessor-version":[{"id":530,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/505\/revisions\/530"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=505"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=505"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=505"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}