Samveen's Blog

22nd August 2013

Bash For Android

There have been multiple attempts to build Bash for Android, most of them successful, yet most instances are compiled statically using non-NDK tool-chains. That seems somewhat wrong to me(See my previous post on Strace for Android). Conversely, given that the Bionic libc is somewhat limited, there are issues with building most software using the NDK.

In comes the Crystax NDK, or The Improved Android NDK by Crystax. The latest version is r8 (which matches Google's NDK r8). The rockstars at Crystax added some extra sugar on top of the NDK (as a static libcrystax) which provides some of the most commonly used standard library functions missing from Bionic.

However, this is not the silver bullet(or pullet, if I remember the Looney Toons correctly). The bash configure script is a different beast altogether (actually any configure script) when cross compiling. Tests that require probing the target system or running commands on the target system will fail during a cross compile. It makes me ask, "Were Art Thou, NDK on Android?".

Exclamations aside, the below was my process to build a dynamically linked Bash for Android.

  • Get Bash-4.2 from the GNU mirrors.
  • Run configure as follows:
    $ export NDKROOT=$HOME/ndk
    $ export SYSROOT=$HOME/ndk/platforms/android-8/arch-arm
    $ export HWKIND=generic
    $ export PATH="$PATH:$NDKROOT/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86_64/bin/" 
    $ ./configure --host=armv7-unknown-linux-androideabi \
    >     --target=armv7-unknown-linux-androideabi \
    >     --build=x86_64-linux-gnu --prefix=/data/local/ \
    >     host_alias=arm-linux-androideabi \
    >     "CFLAGS=--sysroot=$SYSROOT -Wall -Wextra  -I$NDKROOT/sources/crystax/include -L$NDKROOT/sources/crystax/libs/armeabi-v7a" \
    >     CPP=arm-linux-androideabi-cpp CC=arm-linux-androideabi-gcc \
    >     LD=arm-linux-androideabi-ld RANLIB=arm-linux-androideabi-ranlib \
    >     AR=arm-linux-androideabi-ar
  • Epic fail on make with prototype errors for vprintf
  • Modify config.h as follows:
    < /* #undef HAVE_VPRINTF */
    > #define HAVE_VPRINTF 1
  • On examining config.h, realise that config.h is incorrect due to the cross compile, and fix some of the glaring issues:
    < /* #undef HAVE_MKFIFO */
    > #define HAVE_MKFIFO 1
    < #define JOB_CONTROL_MISSING 1
    > /* #undef JOB_CONTROL_MISSING */
  • Minor fail on make, due to linker errors on getpwent and setpwent
  • Google for solution and discover this page, which contains a set of patches to build Bash on Android with the NDK.
  • Get and apply all patches to the code.
  • Rerun configure
  • Re-edit config.h
  • Rerun make and minor fail on missing flag -lm
  • Rerun configure after adding -lm into the CFLAGS variable
  • Re-edit config.h
  • Rerun make For The Win
  • Run arm-linux-androideabi-strip bash to strip the executable.
  • Ship to device and Enjoy