Node.js 4 on OpenWrt

Update 2017-02-27: I have built Node.js 6 for OpenWRT.
Update 2017-02-20: I migrated the files from DropBox since their public shares will stop working.
Update 2017-02-20: Updated binaries for OpenWRT 15.05.1 and Node.js 4.7.3.

Node.js is merged with io.js, and after Node.js 0.12.7 came version 4.0.0.

Well, the good news is that V8 seems to be competely and officially supported on Raspberry Pi (ARMv6+VFPv2) again (it has been a little in and out).

I intend to build and benchmark Node.js for different possible (and impossible) OpenWRT targets, and share a few binaries.

Binaries

Target Binaries Comments
14.07: brcm2708 4.0.0
15.05: x86 4.1.0
15.05: brcm2708 4.1.0 also works for brcm2709 Raspberry Pi 2
15.05: brcm2709 4.1.2
15.05: mvebu 4.1.2 Not Tested! Please test, run octane-benchmark, and let me know!
15.05: ramips/mt7620 0.10.40
r47168: ramips/mt7620 4.1.2 requires kernel FPU emulation (get custom built r47168)
15.05.1: brcm2708 4.4.5
4.7.3
15.05.1: brcm2709 4.4.5
4.7.3
15.05.1: mvebu 4.7.3 Not Tested! Please test, run octane-benchmark, and let me know!

You need to install dependencies:

# opkg update
# opkg install librt
# opkg install libstdcpp

Benchmarks
Octane (1.0.0) Benchmark:

Target        System             CPU        Score      Time
brcm2708      Raspberry Pi v1    700Mhz       97.1     2496s
brcm2708      Raspberry Pi v2    900Mhz     1325        198s
brcm2709      Raspberry Pi v2    900Mhz     1298        198s
x86           Eee701             900Mhz     2559        118s
mt7620        Archer C20i        ( 64 MB RAM not enough )

Performance has been very consistent through different versions of OpenWRT and Node.js.

Building x86
With the 15.05 toolchain, this script configured Node.js 4.1.0

#!/bin/sh -e

export CSTOOLS="$STAGING_DIR"
export CSTOOLS_INC=${CSTOOLS}/include
export CSTOOLS_LIB=${CSTOOLS}/lib

export CC="i486-openwrt-linux-uclibc-gcc"
export CXX="i486-openwrt-linux-uclibc-g++"
export LD="i486-openwrt-linux-uclibc-ld"

export CFLAGS="-isystem${CSTOOLS_INC}"
export CPPFLAGS="-isystem${CSTOOLS_INC}"

export PATH="${CSTOOLS}/bin:$PATH"

./configure --without-snapshot --dest-cpu=x86 --dest-os=linux --without-npm

bash --norc

Then just run make, and wait.

Building brcm2708 (Raspberry Pi v1)
I configured
– Node.js 4.0.0 with 14.07 toolchain,
– Node.js 4.1.0 with 15.05 toolchain,
– Node.js 4.4.5 with 15.05.1 toolchain
with the following script:

#!/bin/sh -e

export CSTOOLS="$STAGING_DIR"
export CSTOOLS_INC=${CSTOOLS}/include
export CSTOOLS_LIB=${CSTOOLS}/lib

export CC="arm-openwrt-linux-uclibcgnueabi-gcc"
export CXX="arm-openwrt-linux-uclibcgnueabi-g++"
export LD="arm-openwrt-linux-uclibcgnueabi-ld"

export CFLAGS="-isystem${CSTOOLS_INC} -march=armv6j -mfloat-abi=softfp"
export CPPFLAGS="-isystem${CSTOOLS_INC} -march=armv6j -mfloat-abi=softfp"

export PATH="${CSTOOLS}/bin:$PATH"

./configure --without-snapshot --dest-cpu=arm --dest-os=linux --without-npm

bash --norc

Then just run make, and wait.

Building brcm2709 (Raspberry Pi v2)
I configured Node.js 4.1.2 with 15.05 toolchain and 4.4.5 with 15.05.1 toolchain with the following script:

#!/bin/sh -e

#Tools
export CSTOOLS="$STAGING_DIR"
export CSTOOLS_INC=${CSTOOLS}/include
export CSTOOLS_LIB=${CSTOOLS}/lib

export CC="arm-openwrt-linux-uclibcgnueabi-gcc"
export CXX="arm-openwrt-linux-uclibcgnueabi-g++"
export LD="arm-openwrt-linux-uclibcgnueabi-ld"

export CFLAGS="-isystem${CSTOOLS_INC} -mfloat-abi=softfp"
export CPPFLAGS="-isystem${CSTOOLS_INC} -mfloat-abi=softfp"

export PATH="${CSTOOLS}/bin:$PATH"

./configure --without-snapshot --dest-cpu=arm --dest-os=linux --without-npm

bash --norc

Building ramips/mt7620 (Archer C20i)
For Ramips mt7620, Node.js 0.10.40 runs on standard 15.05 and I have posted build instructions for 0.10.38/40 before.

For Node.js 4, you need kernel FPU emulation (which is normally disabled in OpenWRT). The following script configures Node.js 4 for trunk (r47168, to be DD).

#!/bin/sh -e

export CSTOOLS="$STAGING_DIR"
export CSTOOLS_INC=${CSTOOLS}/include
export CSTOOLS_LIB=${CSTOOLS}/lib

export CC="mipsel-openwrt-linux-musl-gcc"
export CXX="mipsel-openwrt-linux-musl-g++"
export LD="mipsel-openwrt-linux-musl-ld"

export CFLAGS="-isystem${CSTOOLS_INC}"
export CPPFLAGS="-isystem${CSTOOLS_INC}"

export PATH="${CSTOOLS}/bin:$PATH"

./configure --without-snapshot --dest-cpu=mipsel --dest-os=linux --without-npm --with-mips-float-abi=soft
bash --norc

Without FPU emulation you will get ‘Illegal Instruction’ and Node.js will not run.

ar71xx (TP-Link WDR3600)
Without a custom built FPU-emulator-enabled kernel, a WDR3600 gives:

root@wdr3600-1505-std:/tmp# ./node 
Illegal instruction

However, with FPU enabled:

root@wdr3600-1505-fpu:/tmp# ./node 
undefined:1



SyntaxError: Unexpected end of input
    at Object.parse (native)
    at Function.startup.processConfig (node.js:265:27)
    at startup (node.js:33:13)
    at node.js:963:3

Same result for 4.1.2 and 4.2.2. That is as far as I have got with ar71xx at the moment (20151115).

Leave a comment ?

11 Comments.

  1. Hi! In another article you demoed how to build Nodejs for OpenWRT on top of RaspberryPI: http://zo0ok.com/techfindings/archives/1954.

    I have a solution I’m developing that uses x86 instead of ARM. Is it possible to build Nodejs 4.0 to this platform? If yes, how can I do it?

  2. Absolutely… building NodeJS 4 for OpenWRT/x86 should be quite easy. I would start trying the official builds, they could work. But I have been thinking about building an x86 build and share. Please keep me updated!

  3. Really nice. I think as NodeJs 4 is an LTS version it should be perfect to use as base package for OpenWRT.
    Meanwhile, do you know any tutorials that could help me build the package?

  4. I think it would be great if you create a post where you write how to build a node package op from node source code for any cow architecture.

  5. Building Node.js for OpenWrt (mipsel) | TechFindings - pingback on 2015/10/11 at 17:11
  6. Luis, well, maybe I get there some day.

    Problems are
    1) I don’t know how to make a real OpenWrt package (that should be pretty easy though).
    2) Many (most) OpenWrt targets do not run Node.js, and perhaps never will. So “any” architecture will most likely be a few selected architectures.
    3) Most supported devices are not powerful enough to run Node.js. It runs on 64MB RAM, but it is not even enough to run a standard benchmark (octane benchmark). Also, the node binary is typically around 15MB. It can probably be made smaller, but typical OpenWrt devices have 8MB of flash.

    Node.js makes sense with
    1) at least 128 MB RAM, preferably more
    2) 128MB of NAND flash
    3) FPU (ARMv7 or x86)

    This basically leave us with WRT1200AC/WRT1900AC and some Single Board Computers (Beaglebone, Raspberry Pi 2).

    So for the time being, I don’t see a generic OpenWrt Node.js package being very relevant.

  7. Same error (Unexpected end of input) on Xiaomi MiWiFi Mini (MT7620N/ramips), offical rom , based on openwrt 14.07

  8. Hello zo0ok!

    You’ve done a great work – I’ve installed node_4.1.2 (with your custom build r47168 with FPU emulation) on my Asus-RT-14u and run some js applications there.
    But ‘Luci’ is absent in your build.
    For me is difficult to configure my routers without Luci.

    Could you please tell me how I can compile luci for this particular custom build ?

    Thank you!

    P.S. Seems you are the only one in inernet who adapt node.js for different hardware.

  9. Jev, cool that you tried the custom build!
    It was, admittedly, more of a proof of concept.
    I don’t have the build tree anymore so I can’t build more packages (like Lucy) for it.

    My build was r47168, between 15.05 and 15.01.1.
    https://wiki.openwrt.org/about/history

    My guess is that you can download official opkg-package files for either 15.05 or 15.05.1 and install them, perhaps with some force-flag since checksums will fail.

    https://wiki.openwrt.org/doc/howto/luci.essentials

    A perhaps better option is that you build your own version of 15.05.1 with Kernel emulation enabled.
    However, it seems I didn’t document the process very well, and I am afraid it was not trivial.
    I think the normal “make menuconfig” does not configure the kernel. So after “make menuconfig” you need to do “make kernel_menuconfig”, I think. If you have never built OpenWRT or the Linux kernel from source, this will be quite some work the first time.

  10. Jev, perhaps I can try to build 15.05.01 with kernel emulation.
    I eventually destroyed my Archer C20i so I will not be able to test my own build at all.

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Time limit is exhausted. Please reload CAPTCHA.

Trackbacks and Pingbacks: