Building node-sass || libsass-python natively on Android 6 & 7

If you've ever used the brilliant Termux[1] application on Android as a frontend developer, you might have wondered, if it is possible to do the complete frontend development process just on your android phone / tablet.

The answer is: yes, it is! Termux has git, and nodejs, and therefore all the basic tools you really need. For editing you can use any other text editing application.

Unfortunately, getting there requires solving a few challenges - the biggest of which is getting the native c++ sass compiler to compile and run on android. In this blog post, I will describe the steps you need to take to get the sass compiler running and kickstart your complete frontend development process on android.

If you run 'npm i' or 'pip install libsass', and get errors such as the below, this guide will help you.

  • Segmentation fault
  • WARNING: linker node-sass/vendor/android-arm-48/binding.node has text relocations. This is wasting memory and prevents security hardening. Please fix.
  • error: invalid argument '-std=gnu++0x' not allowed with 'C/ObjC'
  • error: command 'arm-linux-androideabi-clang' failed with exit status 1
  • Something along the lines of termux-packages#307 (more info): 
  • crtbrand.c:(.text+0x84): undefined reference to `main'
    Release/obj.target/addon/hello.o: In function `demo::Method(v8::FunctionCallbackInfo<v8::Value> const&)':
    hello.cc:(.text+0x20): undefined reference to `v8::String::NewFromUtf8(v8::Isolate*, char const*, v8::String::NewStringType, int)'
  •  You read on the node-sass issue #1648, #1944, or #1960 that it's currently not possible/supported to compile lib-sass / node-sass on android. That statement is outdated, as it's possible to compile.

Setup Android for C++ Compilation & NodeJS development

  • Install Termux [Play Store Link]
  • apt update # update package cache
  • apt upgrade # updates tools, installs packages command
  • packages install nodejs python python-dev make clang git openssh cmake autoconf automake # install build dependencies
  • termux-setup-storage # {optional} Configures storage, makes it possible to clone repositories or node dependencies onto the sd card (however, this will only work properly, if the SD card is EXT4 formatted). See https://termux.com/storage.html for more information
  • cat ~/.ssh/id_rsa.pub # {optional} The key is automatically generated when git/openssh is created | Setup github access via your SSH key, alternatively, use https for cloning.

Install & Compile Node-Sass

  • git clone # {your project with a node-sass dependency}
  • cd # {your project folder}
  • npm i node-gyp # before installing the other dependencies, just install node-gyp separately
  • # do the edits outlined below in your preferred editor (vi, nano)
  • # the path will depend on your node version.
  • vi ~/.node-gyp/6.11.0/include/node/common.gypi
  • nano ~/.node-gyp/6.11.0/include/node/common.gypi
  • npm i # now you can install all your dependencies, including node sass

Updating node-gyp common.gypi config to make node-sass compile correctly

In the node gyp config, you'll find that the c++ flag 'fPIE' is configured for Android in common.gypi. According to my research, this was set in order to compile nodejs for the android platform. Unfortunately, this will prevent libsass.a (which is a library and shouldn't be compiled with fPIE) to work if compiled on Android. Since the node-sass binary incorporates libsass, we have to make the change both for cflags and for ldflags. We also have to remove the -pie ldflag compiler option.
Therefore, we have to replace in the two configurations (Debug and Release), fPIE with fPIC, and remove the -pie flag:

          ['OS == "android"', {
             'cflags': [ '-fPIC' ],
             'ldflags': [ '-fPIC' ]
          }],

After that change, it's possible to install node-sass normally via npm. Since there is no pre-built binary for android, the fallback to compilation will trigger, and the module will be built normally with node-gyp.

You can see the android gyp configuration discussed here if you want to put your blame somewhere. Unfortunately it seems that the solution proposed by @clausreineke was never deployed.

He proposes the following (don't forget to apply the patch for the 2 different build configurations):
diff -u -r ../node-v6.5.0/common.gypi ./common.gypi
--- ../node-v6.5.0/common.gypi> 2016-08-26 11:27:16.000000000 -0400
+++ ./common.gypi>      2016-09-14 06:35:35.551380791 -0400
@@ -78,7 +78,12 @@
           }],
           ['OS == "android"', {
             'cflags': [ '-fPIE' ],
-            'ldflags': [ '-fPIE', '-pie' ]
+            'ldflags': [ '-fPIE' ],
+            'target_conditions': [
+              ['_type == "executable"', {
+              'ldflags': [ '-pie' ]
+              }]
+           ]
           }],
           ['node_shared=="true"', {
             'msvs_settings': {

I haven't used / tested this change, and it has not landed upstream, since creating the pull request would require passing the nodejs testing.

Install & Compile LibSass

To use libsass-python, you will need to play around with the build configuration slightly. Therefore, you can't use pip (which will directly try to compile the original configuration). So first, you need to download the configuration, do a small edit, and then compile manually.

The change is a small hack - in order to compile properly with the Termux android toolchain, we need to apply the same compilation flags, as are applied to Darwin / FreeBSD. Since android is recognized as 'Linux' by the command platform.system(), we just make those flags also apply for 'Linux'.

If you have the time, updating this hack to a generally a working solution, please feel free ;-)

  • git clone git@github.com:dahlia/libsass-python.git 
  • cd libsass-python
  • nano setup.py 
  • vi setup.py
  • Apply the patch below:
- if platform.system() in ['Darwin', 'FreeBSD']: 
+ if platform.system() in ['Darwin', 'FreeBSD', 'Linux']:

Now you should be able to build and run libsass-python.

References

LibSass: https://github.com/sass/libsass
LibSass-Python: https://github.com/dahlia/libsass-python
Node-Sass: https://github.com/sass/node-sass
Git Blame: https://github.com/nodejs/node/commit/271201fea935cdf85336736e87c06104ce185f61

Comments

Popular Posts