Tips & Tricks on Android

Wednesday, February 25, 2009

Hello World C program using Android Toolchain

I had reported earlier how I had gotten a C Hello World statically-linked program running on my Android phone using CodeSourcery's toolchain (on linux). Today I got a dynamically-linked Hello World program running on the phone, compiled using Android's prebuilt toolchain from the source.

It's well known that Android uses a stripped down version of libc, called bionic. When you compile your program with static linking, you don't use bionic because well, you linked statically. This is non-ideal. You want to use the bionic library on the phone, and besides you want to compile using Android's prebuilt cross-compiler arm-eabi-gcc

If you are anxious to get things working, use agcc, a perl wrapper over arm-eabi-gcc that sets up everything for you so that you can just:
$ agcc hello.c -o hello
and the resulting binary (hello) just works. Of course you should have the directory containing arm-eabi-gcc in your PATH for agcc to work.

Let's explore a bit deeper. But let me first simplify my hello program to contain just a main
$ cat hello.c int main(int argc, char* argv[]) {
return 0;
}


The minimal set of flags to pass to arm-eabi-gcc to get this working is:
$ arm-eabi-gcc -o hello hello.c -Wl,-rpath-link=/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib -L/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib -nostdlib /Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/crtbegin_dynamic.o -lc

Here /Users/nirnimesh/NIR/android/mydroid/cupcake is the root of my Android source.

$ file hello

hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

Note that the executable binary is dynamically linked.

If you leave out -Wl,-rpath-link=/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib you get
/Users/nirnimesh/NIR/android/mydroid/cupcake/prebuilt/darwin-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/../../../../arm-eabi/bin/ld: warning: libdl.so, needed by /Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/libc.so, not found (try using -rpath or -rpath-link) /Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/libc.so: undefined reference to `dl_unwind_find_exidx' collect2: ld returned 1 exit status

If you leave out -L/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib you get
/Users/nirnimesh/NIR/android/mydroid/cupcake/prebuilt/darwin-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/../../../../arm-eabi/bin/ld: cannot find -lc collect2: ld returned 1 exit status

If you leave out -nostdlib you get
/Users/nirnimesh/NIR/android/mydroid/cupcake/prebuilt/darwin-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/../../../../arm-eabi/bin/ld: crt0.o: No such file: No such file or directory collect2: ld returned 1 exit status

If you leave out /Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/crtbegin_dynamic.o you get
/Users/nirnimesh/NIR/android/mydroid/cupcake/prebuilt/darwin-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/../../../../arm-eabi/bin/ld: crt0.o: No such file: No such file or directory collect2: ld returned 1 exit status

And finally, f you leave out -lc your compilation fails with:
/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/crtbegin_dynamic.o: In function `_start': bionic/libc/arch-arm/bionic/crtbegin_dynamic.S:(.text+0x10): undefined reference to `__libc_init' collect2: ld returned 1 exit status

So far we've been able to compile C programs using Androids toolchain and run on the phone.
To summarize, it's the most convenient to use agcc as the compiler so you don't have to bother.

29 comments:

  1. Wow!

    I just need it now =)

    Thousands of thanks!

    ReplyDelete
  2. I followed those steps and run it on the emulator/cupcake branch. It did not work. I got file not found.
    Neil

    ReplyDelete
  3. Awesome man, keep up the updates. I just got my dev phone and have used a few of your posts already.

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. I created similar tool named 'droid-wrapper'. It can be used for generic software using 'configure' script.

    I published it at http://github.com/tmurakam/droid-wrapper/

    ReplyDelete
  6. just like neiln, I get:

    # ./hw
    ./hw: not found

    my compile options add a couple of -I because the compiler didn't find the headers. also, trying to compile the cupcake from sources (pulled via git) does not compile bionic. do you know anything about that?

    ReplyDelete
  7. For those with the "not found" problem:

    That's because you have to specify the path to the Android dynamic linker:

    arm-eabi-gcc [...] -Wl,-rpath-link=...,-dynamic-linker=/system/bin/linker

    I've had a hard time with this issue, too.

    ReplyDelete
  8. Hi,You helped me so much :)

    But I developed an application using threads,and made the make file as you stated ,but each time I try to run it on the target ,it arisen a linking error that tells me that it doesn't can to link "libpthread.s0.6",,I know that android uses different libc implementation bionic,,How can I resolve this matter ??

    Any help will be appreciated :)

    ReplyDelete
  9. Using the NDK r3 in Android 2.1, I was able to compile with the following (from the ndk directory):

    ./build/prebuilt/darwin-x86/arm-eabi-4.2.1/bin/arm-eabi-gcc -o hello hello.c -Wl,-rpath-link=./build/platforms/android-5/arch-arm/usr/lib/,-dynamic-linker=/system/bin/linker -L./build/platforms/android-5/arch-arm/usr/lib/ ./build/platforms/android-5/arch-arm/usr/lib/crtbegin_dynamic.o -I./build/platforms/android-5/arch-arm/usr/include -nostdlib -lc

    Don't know if it works -- I don't have an Android device, just the SDK emulator!

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. hi, i am trying to compile Hello.c same as above

    arm-eabi-gcc -o hello hello.c -Wl,-rpath-link=/home/builds/android/out/target/product/generic/obj/lib -L/home/builds/android/out/target/product/generic/obj/lib -nostdlib /home/builds/android/out/target/product/generic/obj/lib/crtbegin_dynamic.o -lc

    I am getting below error, can any one help me

    /home/builds/android/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/bin/ld: cannot find -lc
    collect2: ld returned 1 exit status

    ReplyDelete
  12. I just installed the new NDK (android-ndk-r3)...before which I was using CodeSourcery's toolchain.

    When I try to compile from command line, I get the following:

    main.c:14:24: error: sys/socket.h: No such file or directory
    main.c: In function 'main':
    main.c:31: error: 'pthread_t' undeclared (first use in this function)
    main.c:31: error: (Each undeclared identifier is reported only once
    main.c:31: error: for each function it appears in.)
    main.c:31: error: expected ';' before 'listenerThread'
    main.c:38: error: 'listenerThread' undeclared (first use in this function)
    main.c: In function 'openSocket':
    main.c:53: error: 'AF_INET' undeclared (first use in this function)
    main.c:53: error: 'SOCK_STREAM' undeclared (first use in this function)

    And so on. The NDK cannot find the #includes.

    Any way around this? With CodeSourcery I was able to compile from command line very simply:

    arm-none-linux-eabi-gcc -static -pthread main.c -o main

    It is not working as I expected. Please advise!


    Thank you.

    ReplyDelete
  13. The agcc wrapper doesn't work with android-ndk-r4b due to changed paths. I hacked it enough to get a simple printf("Hello, world!") to compile. Modified agcc here:

    https://docs.google.com/leaf?id=0B8R6VSvTZHZWYWI5OTY3NDgtNmFmMS00OTY2LWI1MmMtYTc0ZmZkZDBmZjk2&hl=en

    ReplyDelete
  14. Here is another copy of patched up agcc script. http://bit.ly/91wnsa

    @lunkwill You've beaten me by a few days, unfortunately your link is not valid. Could you fix it?

    ReplyDelete
  15. This article is old. You now can use the NDK to compile a native C code file, not only JNI libraries.

    Here's how to do it:
    http://www.pocketmagic.net/?p=1462

    Hope this helps.

    ReplyDelete
  16. I can't stress this enough to my friends and people I talk to about Android apps in general- Most of the best Android apps are the free ones.

    best android apps

    best iphone apps

    ReplyDelete
  17. Great article. I like esp. your analysis of leaving out each options and showing the affect.

    Thanks a lot.

    ReplyDelete
  18. @Nirnimesh : This method is better than NDK ??

    ReplyDelete
  19. Great post, you have pointed out some wonderful details, I as well conceive this s a very excellent website. Hong Kong Company

    ReplyDelete
  20. The most pervasive influence on these languages has been syntactical, and they tend to combine the recognizable expression and statement syntax of C with underlying type systems and data models that can be radically different. C++ started as a preprocessor for C and is currently nearly a superset of C. Thanks.
    Regards,
    website design company

    ReplyDelete
  21. I managed to get a "Hello, World!" application running under Android 4.1 with the command line below:

    arm-eabi-gcc -o hello hello.c -I/home/sandy/android/google_repositories/arm-toolchain/prebuilt/ndk/android-ndk-r7/platforms/android-14/arch-arm/usr/include -Bdynamic -Wl,--gc-section -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,--dynamic-linker=/system/bin/linker -Wl,-rpath-link=/home/sandy/android/google_repositories/android-4.0.4_r1/prebuilt/ndk/android-ndk-r7/platforms/android-14/arch-arm/usr/lib -L/home/sandy/android/google_repositories/android-4.0.4_r1/prebuilt/ndk/android-ndk-r7/platforms/android-14/arch-arm/usr/lib -nostdlib /home/sandy/android/google_repositories/android-4.0.4_r1/prebuilt/ndk/android-ndk-r7/platforms/android-14/arch-arm/usr/lib/crtend_android.o /home/sandy/android/google_repositories/android-4.0.4_r1/prebuilt/ndk/android-ndk-r7/platforms/android-14/arch-arm/usr/lib/crtbegin_dynamic.o -lc

    Application Source:
    #include
    #include

    int main( int argc, char **argv )
    {
    printf( "Hello, World!\n" );
    return 0;
    }

    I only tested this on the AVD emulator so your mileage may vary...

    ReplyDelete
  22. A simple house is a house with few exterior corners. Every house corner beyond a simple box will add roofing complications and increase the cost of building the house. The simplest house is a square or rectangle. Reducing the number of interior walls will also reduce the cost and complexity of a house. Thanks.
    Web design norwich

    ReplyDelete
  23. This article is old. You now can use the NDK to compile a native C code file, not only JNI libraries.
    cheap jerseys
    wholesale cheap jerseys

    ReplyDelete
  24. Your photos are lovely. The time you have taken to invest in preserving memories is priceless.I hope more. Great job on the site, it looks wonderful. I am going to bookmark it and will make sure to visit often.

    jerseys cheap

    ReplyDelete
  25. Hello! I simply would really like to present large thumbs up for the nice information you’ve got here on this post. i’ll be coming to your journal for a lot of before long

    cheap jersey
    cheap nike jerseys
    cheap jerseys wholesale
    cheap mlb jerseys

    ReplyDelete
  26. Here is the perfect app for you guys http://akshayeminem.blogspot.in/2013/01/c-and-c-programming-in-android.html

    ReplyDelete