Home > Android > Compile a native C Android application

Compile a native C Android application

Searching on the web you can find many ways of compiling Android native applications, I mean, the usual console application, daemon, C/C++ library, etc. you usually compile with no problem in your computer.

In order to compile for Android you need an ARM toolchain. The two main options I have found consists on using Android Prebuilt toolchain and the CodeSourcery one:

  • Android Prebuilt toolchain
  • Android doesn’t come with the traditional libc library. On the contrary it comes with Bionic, a slim libc developed by Google for use in the Android mobile software platform. Bionic is clearly tailored for supporting the Android system. In [1] you can find some of the peculiarities of this library.
    The Android prebuilt toolchain has a prefix arm-linux-androideabi-.

  • CodeSourcery toolchain
  • CodeSourcery, in partnership with ARM, Ltd., develops improvements to the GNU Toolchain for ARM processors and provides regular, validated releases of the GNU Toolchain. This toolchains are provided in many different versions with this naming convention [2]. For our case the one it is going to be used is arm-none-linux-gnueabi, which includes the glibc. In case using the arm-none-eabi, non glibc is included and it is oriented to be used to compile complete native libraries and applications (like for instance in FreeRTOS).

It is up to you to use one or the other option and choose which is the best one. On my personal opinion, for building applications for Android from scratch you should you Bionic, while in case you are trying to migrate a library from a computer environment, I think it is easier to use the CodeSourcery. If you are using threads or C++ exceptions, Bionic library doesn’t fully support them (actually it doesn’t support exceptions).

AFAK cross-compilation can only be done using a Linux environment or, in case in Windows, using Cygwin.

I highly recommend to have a look at Android NDK | Android Developers and download the prebuilt NDK, which is the same as the one you get from the git repository except for the name change on the files (arm-eabi- to arm-linux-androideabi-). After unzipping the files go to the doc directory and open the help html files. Although it is seems it is not the target you are aiming, it will help you quite a bit in understanding what is following.

$ firefox /documentation.html

Using agcc.pl [3]

The agcc.pl is a script initially developed by Andrew Ross, that allows you to use the Android ARM toolchain gcc in an easy way by automatically including the most commonly required libraries. It is somehow like an ordenary Makefile.

Requirements

The Android Open Source repository should have been downloaded. It is at least required the following projects:

  • development
  • ndk
  • system
  • bionic
  • dalvik

but problably some other. The system used for this tutorial is compiled for the Nexus S (full_crespo).

Update: after writing this I realize that you can also use the Android NDK as it also comes with a prebuilt toolchain. Be aware that the path and names of toolchain must be updated accordingly.

Download the required git repositories for build the platforms (you already have them, but I put them here as a reference).

git clone git://android.git.kernel.org/platform/ndk.git ndk
git clone git://android.git.kernel.org/platform/development.git development

Create the NDK (Native) platforms as by default they are not included even after compilation.

$ cd mydroid
$ export NDK=`pwd`/ndk
$ $NDK/build/tools/build-platforms.sh

You will see now a directory tree like $NDK/platforms/android-NUM/... In it there will be the /usr lib and include files that are necessary to compile a C application.

agcc script configuration

Download agcc.pl script (by Andrew Ross) for getting the original script. It is a perl wrapper for the arm-eabi-gcc that comes with the android’s prebuilt cross compiler. If you have a look into the code, you can notice that is like a Makefile and includes all the libraries (includes and libs), compiler options, etc.

This scripts compile the application (.c, etc.) and link them using dynamic libraries. In order to link in shared mode used -share as it is said in the header of the file.

Modify the agcc to fit your needs, that is, mainly just change the platform or the toolchain for the one you are using. The file agcc_jlanza.pl is a modification of the script in order to fit the changes in my Android platform.

Compiling the HelloWorld application

It is mandatory you set the arm-eabi-gcc so include it. The sdk-tools-x86_64 is a compilation of all the tools required to comunicate and do stuff on the phone. You have them on /out/host/linux-x86/bin after compilation of the android platform. A suggestion is to create a source file.

$ cat > myenvsetup.sh
SDK_TOOLS_X86_64=/home/jlanza/android/sdk-tools-x86_64
TOOLCHAIN=/home/jlanza/android/mydroid/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin

export PATH=$PATH:$SDK_TOOLS_X86_64:$TOOLCHAIN

$ source myenvsetup.sh

You have just updated the path with the needed tools for application compilation.

Create the helloworld application

$ cat > hello.c
#include 

int main(int argc, char* argv[])
{
  printf("Hello jlanza\n");
  return 0;
}

$ agcc hello.c -o hello
$ file  hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
$ agcc -static hello.c -o hello_static
$ file  hello_static
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, not stripped

Note: the static version seems to report several problems during compilation due to the internal use of 32 bits in the libraries and that the system we tried it on is 64 bits, but the execution of the program is correct.

Now it is time to move the files to the phone. It is better you move them to /data/local as in the /sdcard it is not allowed to execute commands

$ ls -l
-rwxr-xr-x 1 jlanza jlanza   3708 2011-08-23 19:15 hello
-rwxr-xr-x 1 jlanza jlanza 318197 2011-08-23 20:52 hello_static
$ adb push hello /data/local/
$ adb push hello_static /data/local/
$ adb shell
$ cd /data/local
$ ls -l
drwxrwx--x shell    shell             2011-08-19 17:14 tmp
-rwxrwxrwx shell    shell        3708 2011-08-23 17:15 hello
-rwxrwxrwx shell    shell      318197 2011-08-23 18:52 hello_static
$ ./hello
Hello jlanza
$ ./hello_static
Hello jlanza

You’ve made it. First native Android application running.

You should notice that the files have been installed in /data/local directory in stead of the /sdcard directory. This is because the /sdcard directory for security reasons doesn’t allow execution mode.

$ cp hello /sdcard
$ cd /sdcard
$ ls
----rwxr-x system   sdcard_rw     3708 2011-08-23 18:55 hello
$ ./hello
./hello: permission denied
$ chmod +x hello
Bad mode
$ su
# cd /sdcard
# chmod +x hello
Bad mode

Using a Makefile

Using the Makefile from [4], it seems that the HelloWorld application previouly developed (hello.c) is compiling and executing correctly. Some modifications to the original Makefile has been done using the agcc as a reference for libraries and linking options.

AR = arm-eabi-ar
AS = arm-eabi-as
CC = arm-eabi-gcc
CXX = arm-eabi-c++
LD = arm-eabi-ld

NDK_KIT = /home/jlanza/android/android-ndk-r6/
PLATF_KIT = platforms/android-9/

ARM_INC = $(NDK_KIT)/$(PLATF_KIT)/arch-arm/usr/include
ARM_LIB = $(NDK_KIT)/$(PLATF_KIT)/arch-arm/usr/lib

OBJS = hello.o
EXES = hello

hello: hello.o
    $(LD) \
        --dynamic-linker /system/bin/linker -nostdlib \
        -rpath /system/lib -rpath $(ARM_LIB) -rpath-link $(ARM_LIB) \
        $(ARM_LIB)/crtend_android.o $(ARM_LIB)/crtbegin_dynamic.o \
        -L$(ARM_LIB) $(ARM_LIB)/libc.a -lc -o hello hello.o 

hello.o: hello.c
    $(CC) -I $(ARM_INC) -c hello.c

clean:
    rm -f $(OBJS) $(EXES)

The issue with the Makefile is that you have to be really careful with the libraries that are needed and so on. You have to learn better than I the behavior of the linking and compiling options.

Using CodeSourcery toolchain

This option is the one I like most, at least for the moment. The reason is very simple: I’m compiling Linux libraries from their source code and using the Bionic library leads to a lot of changes that have to be done to the code (includes, function that doesn’t exists, etc.).

As already introduced, here you can find the slight differences between the various toolchains CodeSourcery offers.

Toolchain Description
arm-none-linux-gnueabi glibc is to be used and it seems that is mimicking or running on a Linux environment
arm-none-eabi for bare-metal use, compiling the system from scratch natively

Then for normal use get the arm-none-linux-gnueabi toolchain. Download it from here. If you use the .bin installer you will keep things in a better order as all the toolchains will be automatically installed in the same directory, provided you do so. By default it installs in $HOME/CodeSourcery, but for a more professional installation it is interesting to put in /opt and run the .bin command with superuser permissions.

After installing the CodeSourcery toolchains, it is advisable to put the $INSTALLATION_PATH/CodeSourcery/Sourcery_G++_Lite/bin in the PATH, so it will easy the scripts configuration and compilation tasks.

The main difference between using the Android toolchain or the CodeSourcery is the glibc library. As Android comes with Bionic, the solution to use CodeSourcery toolchain and its LibC library is to compile in static. This way the necessary function will be embedded in the final binaries, avoiding any further problems of libraries not found, wrong directories, etc.

In [5 ] you can find what I considered a great tutorial on how to compile dynamically using the CodeSourcery toolchain. It consists on using the glibc linker and coping all the necessary dynamic libraries files to the phone. I haven’t already tested it, but I think it is quite easy to follow. As soon as I have time I will include a post entry explaining my experience on compiling dynamically using CodeSourcery.

Compiling HelloWorld application

Let’s try to compile the easiest application. Use the hello.c code as in previous sections.


$ arm-none-linux-gnueabi -static hello.c -o hello_sourcery

Copy it to the phone and execute the application.

$ adb push hello_sourcery /data/local/
$ adb shell
$ cd /data/local
$ ./hello_sourcery
Hello jlanza

And voila! First application using the CodeSourcery toolchain.

In [6][7][8][9][10][11] you can find additional references on how to compile using CodeSourcery toolchains, some of the includes some extra information on using dynamic libraries.

What is more in [12][13] it is explained the way to replace the Android toolchain by the CodeSourcery one and compile the Android applications using the ndk_build.

References

[1] Coding Relic: The Six Million Dollar LibC
[2] Can anyone explain the gcc cross-compiler naming convention? – Stack Overflow
[3] Android Tricks: Hello World C program using Android Toolchain
[4] How to compile native android code – xda-developers
[5] Without Android NDK — Native Linux binaries with Exceptions and RTTI
[6] Native C, dynamically linked and shared library “Hello World” run. – Android Internals | Google Groups
[7] motz diary: Dynamically linked “Hello, world!” for Android
[8] motz diary: Shared library “Hello World!” for Android
[9] motz diary: Initialize libc for Android.
[10] Android programming
[11] CodeSourcery: List Archives:
[12] using codesourcery for static libs – android-ndk | Google Groups
[13] using codesourcery for static libs – android-ndk | Google Groups

Advertisements
Categories: Android Tags: , ,
  1. April 17, 2013 at 04:15

    I’m amazed, I must say. Rarely do I come across a blog that’s both equally educative and entertaining, and let me tell you,
    you have hit the nail on the head. The issue is an issue that not enough men
    and women are speaking intelligently about. I am very
    happy that I came across this during my search for something regarding this.

    • jlanza
      April 17, 2013 at 09:02

      Thanks a lot for your compliments 😉 The main problem is that now I don’t have time to write about other issues I’m on. Hope this summer I can.

  2. February 15, 2014 at 14:04

    Why not just use CppDroid – free C/C++ IDE and compiler on Android? It has a lot of included C/C++ examples and tutorials. But lacks of command-line support. Check it yourself. Blog: http://cppdroid.blogspot.com, Google Play: https://play.google.com/store/apps/details?id=name.antonsmirnov.android.cppdroid

    • jlanza
      February 18, 2014 at 10:19

      I didn’t find that project at the time I was playing around with this stuff.

  3. August 8, 2014 at 20:09

    My brother suggested I would possibly like this blog. He was totally right.
    This put up truly made my day. You cann’t believe simply how so much time I had spent for this info!
    Thank you!

  1. September 12, 2011 at 17:32

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: