I am trying to build a native daemon on Android. The purpose to to control some specific hardware, and Java applications will be able to communicate to this daemon using sockets.
I have been using cmake meanwhile to compile my libraries, demos and the real daemon (which works fine BTW). I am now trying to do 2 different things:
Build the same apps using ndk-build.
Port the C++ daemon to an Android service, by making JNI calls very similar to the way the c++ daemon works.
As far as I understand, ndk-build cannot make native applications, but only native libraries, which in turn can be loaded by the Java GUI... am I correct? For step1 I don't really need java (and I have proven it already), but I have yet found a way for ndk-build to spit an elf application.
For reference - I am using cmake, as described here: http://opekar.blogspot.com/2011/06/android-cmake-is-much-easier-in-ndk-r5b.html
This way I can have builds for "normal" linux, and also android using out of source builds. Quite nice hack if you ask me.
An alternative is to use the script make-standalone-toolchain.sh bundled with the NDK to create a stand-alone toolchain, then use it to compile your project. The shell code below illustrates how to use it:
# Assumed path to the NDK, change it to suit your environment.
NDK_HOME=$HOME/bin/android-ndk-r8e
# Desired API and NDK versions and destination folder of
# the stand-alone toolchain, change them to suit your needs.
api=14
ver=4.7
folder=$HOME/bin/android-$api-ndk-$ver
# Create folder if it doesn't already exist.
mkdir -p $folder
$NDK_HOME/build/tools/make-standalone-toolchain.sh \
--toolchain=arm-linux-androideabi-$ver \
--platform=android-$api --install-dir=$folder
Running the lines above will generate a new stand-alone toolchain at $HOME/bin/android-14-ndk-4.7, which you can then use as any regular C/C++ cross-compilation toolchain.
The advantage of working with a stand-alone toolchain is that it makes cross-compiling Linux projects to Android a breeze; see for example my port of Valgrind to Android ARMv7.
As mentioned by #Mārtiņš Možeik in one of the comments, this pice of Android.mk will work:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_daemon
LOCAL_C_INCLUDES := src
LOCAL_SRC_FILES := src/daemon.c
include $(BUILD_EXECUTABLE)
One thing I do notice is that the binary produced by this "makefile" is 130k, while the binary produced by cmake was ~40 kb. This is because I used -s as a C_FLAG and then gcc will strip the produced object on the fly. This can be done later on by calling $NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-strip or the corresponding strip for your arch.
As I have not found documentation of this feature on the internet, some more words:
This works quite good, no problem here :)
This must be saved in a file called jni/Android.mk.
The code must be saved inside the JNI directory
If your code is outside of the jni directory this get ugly, but not impossible. You just need to prefix the code with the corresponding prefixes, don't forget to modify also the include path. This is left to the reader as an exercise.
Still unsure why the code generated from Android build system is larger then the code generated by cmake. I previously said that strip is not called - but it is called before the *.so are copied to the lib directory.
Still don't know how to package that binary into an android package, and not even how to run it (for example when the system is up) without modifying the Android code. I assume I can write a Java service that starts on boot and then execvps the daemon.
Your option 2 is the only way to do it AFAIK.
Related
I build a C++ project depending on the Boost library using CMake (3.4.1). Host platform is Linux, targets are that host and cross-build Android NDK.
I'm only using Boost header files and I just downloaded/extracted the boost folder (and I don't have a /usr/include/boost directory).
In my CMakeLists.txt file I declare the dependency to Boost like this:
find_package(Boost 1.57 REQUIRED)
And I configure my build like this:
BOOST_ROOT=/path/to/boost cmake ../src
Which actually works as expected for my native build.
When I now configure a build exactly the same way (only specifying some more environment variables and a CMAKE_TOOLCHAIN_FILE) CMake gives me:
BOOST_ROOT=/path/to/boost JAVA_HOME=/bla/bla/bla \
ANDROID_NDK=/bla/bla/bla \
ANDROID_SDK=/bla/bla/bla \
ANT=/usr/bin/ant \
cmake ../src -DCMAKE_TOOLCHAIN_FILE=/bla/bla/android.toolchain.cmake
CMake Error at /usr/share/cmake/Modules/FindBoost.cmake:1247 (message):
Unable to find the requested Boost libraries.
Unable to find the Boost header files. Please set BOOST_ROOT to the root
directory containing Boost or BOOST_INCLUDEDIR to the directory containing
Boost's headers.
Call Stack (most recent call first):
CMakeLists.txt:4 (find_package)
So I believe I did almost the same to build for the Android target but the very same method that finds Boost for the host-build doesn't work here.
I tried to set Boost_DIR, BOOSTROOT and BOOST_INCLUDEDIR all with the same effect. Also I've deleted all content in the build directory before trying anything new.
What can be possible reasons for this behavior? I've already tried to print BOOST_ROOT directly in the FindBoost.cmake script like this:
message("BOOST_ROOT: $ENV{BOOST_ROOT}")
With the expected behavior (writing BOOST_ROOT: /path/to/boost).
Of course I can cheat now and just link the boost folder into the include folder of the cross compiler but that's not nice of course and I want to find out what's going on.
When cross-compiling, the toolchain file normally sets the variable CMAKE_FIND_ROOT_PATH. Combined with the CMAKE_FIND_ROOT_PATH_MODE_LIBRARY variable set to ONLY, CMAKE_FIND_ROOT_PATH variable is used as effective chroot for find_library calls, so only libraries under the given prefix(es) are searched.
Analogue variables exist to adjust the behavior for find_path (used for searching include paths) and find_program.
THe toolchain file you use actually sets CMAKE_FIND_ROOT_PATH at line 1521:
set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin"
"${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}"
"${ANDROID_SYSROOT}"
"${CMAKE_INSTALL_PREFIX}"
"${CMAKE_INSTALL_PREFIX}/share" )
and below sets CMAKE_FIND_ROOT_PATH_MODE_* variables to ONLY. So you need to have Boost installed under one of these directories, and give hints (like BOOST_ROOT) relative to it.
Note, that Boost should be built for the target platform (Android NDK in you case), not for the platform where you cross-compile (Linux).
I like to have a high level understanding of how the android build system work. That is when does it complement the GNU make and the Linux build system and when and how does it differ? What I mean by this is how come sometimes we use make files to add functionality to the final image, and sometimes we use Andoroid.mk? Then again sometimes we use both. Does anyone have a good grasp of how these components work together?
For example, I used just a make file to add a simple program as a module. On the other hand, looking at the /external directory some of the modules have Android.mk file and some have a make file also. Then there is the bionic directory. Can anyone elaborate please?
# arkascha- I appreciate this but I think there is a little more to it. It seems to me that GNU make has control over the Linux kernel directories and Android.mk over the Android folders; this sounds intuitive doesn't it? I was looking for a comment that would take this further and elaborate on which files need to be updated in order to add functionality. ie. looking at my build environment I have:
0628Samsung build.sh Documentation include Makefile packages sound
abi config-backup drivers init Makefile.bak pdk system
AndroidKernel.mk COPYING drivres ipc Makefile-original Platform.tar.gz tools
arch CREDITS dtbTool Kbuild mkbootimg prebuilts usr
art crypto external Kconfig mm README vendor
bin cts files kernel modules.order REPORTING-BUGS virt
bionic dalvik firmware Kernel.tar.gz ndk samples
block developers frameworks lib net scripts
bootable development fs libcore note3 sdk
build device github-repo libnativehelper out security
build_msm8974pro_kernel.sh docs hardware MAINTAINERS output
I ask this question since there does not seem to be clear understanding of the AOSP environment. For instance, this link has a section called steps for adding a new program to the Android source tree. In it they advise updating the core/main.mk file. But my environment does not really have the lines they mention. Also sometimes one does not really have a choice of using one, make file vs. android.mk, or the other. At least that has been my experience. Maybe I missed something, but what I did was to add a sample program to the external directory. I was able to compile it with the same toolchain I used to create an image and flash my phone. But the executable did not run on my phone, which led me to believe that perhaps I needed to issue other switches and set various environment variables. So I kept trying to build the image with the program included, but the build environment did not go in that directory. After looking through other directories, I realized that most of them had an Android.mk file so I added one in, and it is chugging along right now. I'll let you know how it turns out. That is why I am asking this question. Maybe I am not looking at the right place, there is no clear stable content about how to add functionality to the final image and what are the differences between what resides in each folder. There is a high level description but no discussion on here is how you add a module to this /external, /bionic, ...and here is what the end result would be.
#Dan Albert- Thanks. I am trying to map what is in the /external directory with what is on my device in an effort to get my code into the image. I am not having much luck. I followed a set of procedures to get a simple kernel module in. But I just used a simple make file as follows:
lib_src := src
lib_headers := headers
.PHONY: all $(lib_src) $(lib_headers)
$(lib_src) :
$(MAKE) --directory=$#
$(lib_*): $(MAKE) --directory=$#
obj-$(CONFIG_TOS) += examples.o
So when you say Android just uses Android.mk, I wonder. The reason being, here I just used a make file and I was able to see the resulting code in my image. Further, I'll share another example with you. Within the Android Studio projects, in order to get some native project in, you have to create a make file as well as an Android.mk. So....? There has to be more; no? Each file does have some unique functionality within the build system; don't you agree?
Please note, I am just making this argument in an effort to get my code into the finale image.
I believe I heard what is in /external directory just goes into the /system folder of the final image. But I can not validate that. Here is what is in my external directory:
aac droiddriver hyphenation libpng nist-sip sonivox
android-clat dropbear icu4c libppp noto-fonts speex
android-mock e2fsprogs iproute2 libselinux oauth sqlite
ant-glob easymock ipsec-tools libsepol objenesis srec
antlr ebtables iptables libusb okhttp srtp
apache-harmony eclipse-basebuilder iputils libusb-compat opencv stlport
apache-http eclipse-windowbuilder jack libvorbis openfst strace
apache-qp eigen javasqlite libvpx openssh stressapptest
apache-xml elfutils javassist libxml2 openssl svox
arduino embunit jdiff libxslt open-vcdiff tagsoup
bison emma jhead libyuv oprofile tcpdump
blktrace esd jmdns linux-tools-perf pixman temp
bluetooth expat jmonkeyengine littlemock ppp timezonepicker-support
bouncycastle eyes-free jpeg llvm proguard tinyalsa
brctl fdlibm jsilver lzma protobuf tinycompress
bsdiff flac jsr305 marisa-trie qemu tinyxml
bzip2 freetype junit markdown qemu-pc-bios tinyxml2
ceres-solver fsck_msdos kernel-headers mdnsresponder regex-re2 tremolo
checkpolicy ganymed-ssh2 libcap-ng mesa3d replicaisland v8
chromium gcc-demangle libffi mksh robolectric valgrind
chromium-libpac genext2fs libgsm mockito safe-iop webkit
chromium_org giflib liblzf mockwebserver scrypt webp
chromium-trace google-diff-match-patch libmtp mp4parser sepolicy webrtc
clang grub libnfc-nci mtpd sfntly wpa_supplicant_8
compiler-rt gtest libnfc-nxp naver-fonts shahin xmlwriter
dexmaker guava libnl-headers netcat sil-fonts xmp_toolkit
dhcpcd hamcrest libogg netperf skia yaffs2
dnsmasq harfbuzz libpcap neven smack zlib
doclava harfbuzz_ng libphonenumber nist-pkits smali zxing
This is basically what I have in the external/shahin directory:
sansari#ubuntu:~/WORKING_DIRECTORY/external/shahin$ more Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= hello_world.S
LOCAL_MODULE := shahin
include $(BUILD_EXECUTABLE)
sansari#ubuntu:~/WORKING_DIRECTORY/external/shahin$ more hello_world.S
.syntax unified
.global main
main:
push {ip, lr}
ldr r0, =message
bl printf
mov r0, #0 # Return 0.
pop {ip, pc}
message:
.asciz "Hello, world.\n"
A simple assembly code and an Android.mk file. But when I issue make from the root of the project I am not sure if this is added to the final image. I don't see any object file created afterwards in this directory. Am I mistaken perhaps? My question is how do I get this into the final image?
Only Android.mk is used by the Android platform build system. There are normal makefiles in the external/ directory because those projects use make when built outside Android, and we just mirror their source. Still, we only use the Android.mk to build it for Android.
Bionic is no different than the other projects in Android, it just has somewhat more complicated Android.mk structure to deal with the complexity of CPU specific sources and various issues that come along with building low level system libraries.
Android.mk is still just make. Each include $(BUILD_*) gets handled in build/core to eventually be rewritten as a normal make rule.
My Android application (game) uses native C++ code for certain operations. That is, I use the Android NDK. The native C++ code is compiled for armeabi only (to the default, armeabi-v5).
The last time I built my c++ code into nativestuff.so was a few months ago, in another computer (Windows 7 + cygwin, because cygwin is recommended for compiling with Android NDK).
I just installed the NDK on my current PC (Windows 7), along with the newest cygwin, and rebuilt the c++ code for my app.
To my surprise, it generates an .so file of 14KB, while the previous .so file was 37KB. Note that the c++ source files are exactly the same (they haven't changed for a year), my project is under version control, so I'm 100% sure.
I tested the c++ functionality in the game, and it works exactly as before, without any bugs.
My C++ files use only cstring.h and jni.h as includes. My Android.mk is as follows:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := nativestuff
LOCAL_SRC_FILES := nativestuff.cpp
include $(BUILD_SHARED_LIBRARY)
Any idea why the drastic change in .so filesize?
(I added the linux tag as well to this question, because maybe it's a general thing so I want to make sure that linux gurus also check it.)
Run objdump -x file.so on both versions. This will list all the sections and their sizes. That should give you a clue as to where the problem lies. (i.e. is there a new .debug section that's 23KB long? Maybe debug mode got enabled.)
If your code sections are radically different, compare the output of objdump -d file.so. Maybe your compiler automatically inlined more code, which saved a lot of space.
If another section is new/different, post the output in another SO question.
Maybe the previous .so was generated with debugging information.
(compiled with gcc -g option)
You may try one thing: use the command size executable-name. That will give you size of the different areas of your executable code. If the previous build is available do the same to that. You may get an idea where the change is.
I've got a hold of a proprietary JNI application which I need to build for a MIPS device. I've read "Initializing a Build Environment", parts of the NDK docs, some Google Groups threads and numerous StackOverflow questions, but I'm still short of my answer.
So far, I've checked out the Android source using Google's repo script and have it under ~/AndroidSource. I've also separately downloaded the SDK under ~/AndroidSDK and the NDK under ~/AndroidNDK. The code I'm trying to build is in a separate location. The SDK and NDK binaries are in my path. For building, I tried to use two different versions of the NDK as well as the one under the Android source tree, and experienced different sets of problems. My current setup uses NDK r8b, downloaded separately from the Android source.
The application has its Android.mk and jni/Android.mk. However, several directives in the latter point to paths such as
frameworks/base/include
system/core/include
with no prefixes. I thought these were meant to point to the respective directories in the Android source, so I symlinked them to the current directory. After some more symlinking and makefile and source hacking, I got the application to compile, but am currently stuck on the linking phase with lots of references to missing method bodies. During the whole time I knew I was doing something wrong.
I'm on a Linux x86_64 host, if it is of any concern.
So my question is:
What is the proper method to set up a build environment for JNI applications? What environment variables, symlinks and/or path expansions should I set up? Do I need to call any scripts once or before each ndk-build invocation?
Also, I'd be happy if you corrected me on any concepts or terminology I've gotten wrong.
Your approach wiyh symlinking the AOSP tree for system headers is correct. What you need now are the system libraries compiled for MIPS. The easiest way to get them is to adb pull them from a target device (or emulator image). But you can also build these libraries yourself, as part of the AOSP build (see build instructions for the source tree you downloaded).
If you still have any problems remaining, run your ndk-build with parameter V=1 and publish the link command and its results.
I use the following in my build (YMMV).
Explicitly invoke arm-linux-androideabi-gcc as your compiler or linker (should be in PATH).
NDK_PLATFORM=/path/to/android-ndk-r*/platforms/android-14
Pass -I"$(NDK_PLATFORM)/arch-arm/usr/include" to the compiler
Pass -nostdlib -L"$(NDK_PLATFORM)/arch-arm/usr/lib/" -lgcc -lc -lm to the linker
Is it possible to develop a native application that runs without relying on the Dalvik runtime and any of the Java libraries?
Basically, I want to make a native binary I can run via a shell that would be able to run without the system_server process running. Ideally, I want to be able to create my own Window Server by rendering stuff via the OpenGL system, instead of relying on SurfaceFlinger (which would also be dead due to the fact that system_server isn't running).
The reason I'm asking this is that I want to experiment with lower level Android development in C/C++ at which Java is simply un-necessary. So basically, I'm trying to develop a standalone app that can render things via OpenGL+Cairo and receive HID input.
PS: I know what the NDK is, and it's not what I'm looking for. I want to create standalone binaries instead of creating stuff that runs inside the Dalvik VM.
There are two possibilities to run native code on your device: either using NDK or embedding your application into the framework. As I understand the first approach is not considered, thus, I think you can have a look at the second. Here is an example how to implement the second approach.
An example of porting existing code to a custom Android device
It is due time for another technical post here on the blog. This post will be about porting existing c-libraries to Android, something I did as part of the dev board demos we are doing here at Enea.
Platform addition or NDK
There are two ways of bringing native code to an Android device, either add it to the platform itself and integrate it with the framework, or include it with an application package. The latter method have evolved a lot and with the release of NDK version 5 even allows you to hook directly into the application lifecycle http://developer.android.com/reference/android/app/NativeActivity.html from the NDK. The NDK is useful for any application where you have need of native performance, have portable C libriaries you want to reuse or just some legacy native code that could be included in your application. The NDK integrates well with the Android SDK and is a great way to include native functionality in your application. It should be the preferred way for any application that needs to be reusable across a lot of Android devices.
The other option is to include your functionality, it may be native or Java, as an API extension for all applications to use. This will only work on devices that implement these extensions and it may be a suitable option for device builders. This is the variant that we aim for here.
Analyze the existing project
Porting native code to Android is not always straight forward, especially if we are talking about C++ code due to the fact that Android uses its own c-runtime with limited support for exceptions among other things. If you want to know more about the details of bionic there is an overview in the NDK docs.
The code I wanted to port for this project was the Enea LINX for Linux framework which is a fast IPC framework. My purpose was to be able to interact with control systems running our OSE real time operating system which also implements this kind of IPC. LINX consists of a couple of kernel driver modules, a user space library and some configuration and control utilities. It is written in C. I had created a small demo with LINX in Android before where I compiled it separately and used static linking but for this project I wanted a complete port to the Android build system. It did not have any issues with bionic compatability so the port should be straight forward.
I just want to add a short disclaimer about LINX. I use it here since it is a good example of integrating a solution into Android from kernel drivers up to the API levels. This particular piece of code does add additional IPC mechanisms to the systems which more or less messes up the security model so do not use it unless you are aware of the implications. The steps needed to port code to Android described in this post are however applicable for any type of driver/framework/library that you may want to include on your product.
Adding kernel driver modules
The first step was to add the kernel modules to the Android build. One way would have built a new kernel and include them directly but for this project I chose to keep them as separate modules. Building for the kernel is not handled by the Android build system meaning that we build them as we would do with any Linux system. The target is an Atmel based development board and in the LINX module build I provide the headers and cross compilation toolchain for that kernel and architecture.
Now for the Android specific parts. We need to add the compiled kernel modules to the platform build system in some way and create an Android.mk file that includes them in the system image when we build. Add a folder in the source tree where your project will go, device or external are suitable candidates. I created a folder called linx that will hold the entire linx port and in that I added a subfolder called modules where I place the prebuilt kernel modules. Now what we need is an Android makefile to copy them to the suitable place in the out folder for system image generation. This will look like:
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := linx.ko
LOCAL_MODULE_CLASS := SHARED_LIBRARY
# This will copy the file in /system/lib/modules
#
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/modules
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
The standard location for modules on the Android system image is System/lib/modules so that is where we copy them. If we build the platform now the build system will copy our precompiled module linx.ko to the system image that we use for our device. The next step is to make sure that we have the module installed on the system when we run it. This can either be done manually via the shell or via a script that we run during init.
In this case I have created a shell script to be launched from init.rc with the following content:
#linx init
insmod /lib/modules/linx.ko
insmod /lib/modules/linx_tcp_cm.ko
netcfg eth0 up
ifconfig eth0 192.168.1.12
mktcpcon --ipaddr=192.168.1.21 ControlConn
mklink --connection=tcpcm/ControlConn control_link
This includes installing the modules and configuring the network and LINX-link. We launched this from init.rc by adding:
...
#linx init script
service linx-setup /system/etc/linx_setup.sh
oneshot
...
The setup script is added to the system image in the same way by including it as a prebuilt target.
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := linx_setup.sh
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
Creating Android make files for the user space code
Now that we have the drivers in place the next step is to look at porting the user space libraries. The default LINX build system uses standard GNU make files but we need to create new ones adapted to the Android build system. Start out by adding the source files needed to the linx directory created in the Android source tree. This gives the following structure:
Android.mk
include
liblinx
linx_basic
linxcfg
linx_setup.sh
modules
I have the linx setup script and the main Android.mk file in the top directory and then we have the source files in separate folders and the include files in the include folder. To illustrate how the Android make files for each source component is created we can use liblinx as an example. The Android.mk file looks like:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := linx.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_MODULE := liblinx
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
We set our sources by specifying LOCAL_SRC_FILES and the name of the library by specifying LOCAL_MODULE. We also need to supply the header files in the include directory by specifying LOCAL_C_INCLUDES. Finally this is a shared library that we are porting so use the BUILD_SHARED_LIBRARY template. This will build the library with the Android build system and add it to the system image as a shared library with the name liblinx.so.
The rest of the code is moved to the Android build system in the same way, by creating Android.mk files and specifying type and any dependencies. As another example we may look at the syntax for building the mktcpcon configuration program. This depends on the library we just created and hence the makefile looks entry looks like:
LOCAL_SRC_FILES := mktcpcon.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_STATIC_LIBRARIES += liblinxcfg
LOCAL_SHARED_LIBRARIES += liblinx
LOCAL_MODULE := mktcpcon
include $(BUILD_EXECUTABLE)
Here we use the BUILD_EXECUTABLE template and we also need to specify static and shared libraries that we link against.
Summary
I hope that provides some insight in how you setup the build for an existing linux project to run on an Android system. The steps to follow are:
Build any kernel related things using the correct kernel build system and config for your device
Add the kernel modules (and/or kernel) to the platform build system and create Android.mk files for them using the prebuilt template.
Create config and intialization services for your drivers if needed and add them to init.
Move the rest of your code (user space) to the Android source tree and create Android.mk files for them.
If you encounter build errors work them out in the source code and see what incompatabilities your code have with the specifics of the Android C-runtime.
That wraps up my post for today. Having done this we are now able to use our added drivers and API:s from native programs running in the shell. The next step is to create a JNI layer and java library to allow regular Android applications to make use of our platform additions.
I have been away for half a year on paternal leave (nice Swedish benefit) but now it is full time Android hacking again and pushing the team to publish things. Hopefully you will see more activity here including a follow up on this post discussing applications APIs.
Yes it is possible to develop native (executable binaries) that can be executable via shell but if you trying to cross compile GNU software using NDK can be pain in ass.
I will suggest you to use CodeSourcery or Linaro toolchain any way you can take a look at my approach https://github.com/DroidPHP/DroidPHP/blob/master/docs/Compiling.md