Node.js for Android committed on github

Yesterday, I posted my initial port of Node.js for Android on github (https://github.com/ldesegur/nodejs-android). This is a very early work, as my main job has kept me away from making more progress. However, results are showing some promises. I am sharing this code so other people are able to help.

So far, v8 and libev seem to work. libeio needs some more work on the I/O side. I’ve wrapped all the missing bionic kernel calls, so they are emulated correctly on the thwarted libc available on Android. They appear with ANDROID defines. Maybe node.js main could take those back into their repo? I have yet to modify the makefiles, conforming to ndk-buiid, to generate JS2CC files, so for now, the translated js to native are committed in the repo. Running basic eval commands with node.js returns results in the log files.

Why am I working on this and how can it benefit other developers?

I believe there is a tremendous benefit to have Node.js running client side. In my personal quest to find a way to write JS code performing well on mobile devices, offering native functionalities and being modular so it’s updatable using AJAX, I couldn’t find a better solution than what node.js provides to server side developers. Node.js gives very simple and elegant way to write JavaScript code in multiple modules with ‘export’ and ‘require’ declarations. The ‘process’ mechanism lets JavaScript access bindings and native code. V8 offers native-style performance and the V8 bridge is simple and will allow other libraries to be developed as local and remote modules.

My goal, as I move forward with this project, is to offer all functionalities that a modern browser DOM would supply (including xmlhttprequest and webgl), to the client JavaScript executables.

Porting node.js to Android

After spending a couple of days dealing with Android NDK madness, some esoteric and intricate Linux implementations on this device, I finally got node js latest to run as a native app on Android.

I was planning to originally run a v8 client on Android so I started with the v8 port. That one was easy. However, when I realized how much benefits node brings to any JavaScript development, and
not only server side, it was obvious that the rest of the stack needed to be ported.

I did some research, hoping someone had gone thru the hoops already. But all I could find was a direct port done on Linux arm and running with root privilege. I couldn’t adopt this approach because my ultimate goal is to deliver JavaScript apps running on standard phones and available on Android market.

Now that I am done with the initial port, my next task is to clean up the codebase, refine some of the plug-in native bindings, fix a bunch of remaining specific issues (e.g. fs, console, ipv6, etc…) and post the result of this work on github (ldesegur/nodejs-android.)

Let me know if you have any interest. I would certainly appreciate any help on this project.

Building libev and libeio with Android NDK

First, libeio: I beat autoconf, autoreconf and automake until I was able to get a config.h. Surprise! It’s equivalent to config.in with all options on.  Next, I added this lines in the xthread.h file, just after include <pthread>

#ifdef ANDROID
#include <asm/page.h>
#endif

This takes care of the PAGE_SIZE definition missing from <limits.h> (it’s defined as itself in that file, I kid you not…)

And since bionic is built non-posix, I added these lines after include <sys/select.h>, in the unix section (!WIN32):

  #ifndef ANDROID
  #include <sys/statvfs.h>
  #else
  #include <sys/vfs.h>
  #define statvfs statfs
  #define fstatvfs fstatfs
  #endif

The Android.mk is very straightforward, I just build the eio.c file pointing local includes to the same dir.

To build libev, you’ll need to add the following lines to ev_select.h:

#ifdef ANDROID
typedef int fd_mask;
#endif

That’s how the openssl people apparently solved this missing type definition.

We are almost there. Next, add the following lines just after EV_USE_CLOCK_SYSCALL:

#ifndef ANDROID
# include <syscall.h>
#else
# include <sys/syscall.h>
#endif

Finally, the next thing to do is to compile two files: ev.c & event.c with local includes set to the same dir. That sounds simple when you read this, but since the extra c files are included by the ev.c main file, compiling them directly with their headers will result in undefining variables, and this won’t compile. It would have been nice to wrap the .c files around an #ifdef #endif, to avoid this. The configuration works with all setting turned on (including latest GCC and libc).