Building an Android NDK with recent GCC and binutils

As of writing, the latest Native-code Development Kit for Android (r6) comes with gcc 4.4.3 and binutils 2.19 for ARM. The combination is a quite old toolchain, that lacks various novelties, such as properly working Profile Directed Optimization (a.k.a. Profile Guided Optimization), or Identical Code Folding.

The first thing that is needed to rebuild a custom NDK, is the NDK itself.

$ wget http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2
$ tar -xjf android-ndk-r6-linux-x86.tar.bz2
$ cd android-ndk-r6

Next, you need to get the NDK source (this can take a little while and requires git, but see further below if you want to skip this part):

$ ./build/tools/download-toolchain-sources.sh src

Rebuilding the NDK toolchain binaries is quite simple:

$ ./build/tools/build-gcc.sh $(pwd)/src $(pwd) arm-linux-androideabi-4.4.3

But this doesn't get you anything modern. It only rebuilds what you already have.

The GCC 4.4.3 that comes with the NDK is actually quite heavily patched. Fortunately, only a few patches are required for gcc 4.6.1 to work with the NDK (corresponding upstream bug).

In order to build a newer GCC and binutils, you first need to download the source for GCC (I took 4.6.1) and binutils (I took the 2.21.53 snapshot, see further below), as well as GMP, MPFR and MPC. The latter was not a requirement to build GCC 4.4. GMP and MPFR are with the NDK toolchain sources, but the versions available there are too old for GCC 4.6.

All the sources must be placed under src/name, where name is gcc, binutils, mpc, mpfr, or gmp. The sources for MPC, MPFR and GMP need to remain as tarballs, but the sources for GCC and binutils need to be extracted (don't forget to apply the patch linked above to GCC). In the end you should have the following files/directories:

  • src/gcc/gcc-4.6.1/
  • src/binutils/binutils-2.21.53/
  • src/gmp/gmp-5.0.2.tar.bz2
  • src/mpc/mpc-0.9.tar.gz
  • src/mpfr/mpfr-3.0.1.tar.bz2

If you skipped the NDK toolchain source download above, you will also need the gdb sources. NDK comes with gdb 6.6, so you should probably stay with that one. The source needs to be extracted like GCC and binutils, so you'll have a src/gdb/gdb-6.6/ directory. Another part you will need is the NDK build scripts, available on git://android.git.kernel.org/toolchain/build.git. They should be put in a src/build/ directory. For convenience, you may directly download a tarball.

You then need to edit the build/tools/build-gcc.sh script to add support for MPC:

Add the following lines somewhere around similar lines in the script:

MPC_VERSION=0.8.1
register_var_option "--mpc-version=<version>" MPC_VERSION "Specify mpc version"

And add the following to the configure command in the script:

--with-mpc-version=$MPC_VERSION

If you want to use gold by default instead of GNU ld, you can also add, at the same place:

--enable-gold=default

If you want a GNU libstdc++ compiled as Position Independent Code (note that by default, the NDK won't use GNU libstdc++, but its own), you can add, at the same place:

--with-pic

Once all this preparation is done, you can build your new NDK toolchain with the following command:

$ ./build/tools/build-gcc.sh --gmp-version=5.0.2 --mpfr-version=3.0.1 --mpc-version=0.9 --binutils-version=2.21.53 $(pwd)/src $(pwd) arm-linux-androideabi-4.6.1

If you're running a 64-bits system on x86-64, you can also add the --try-64 option to the above command, which will give you a 64-bits toolchain to cross-build ARM binaries, instead of the 32-bits toolchain you get by default.

When building Firefox with this new toolchain, you need to use the following in your .mozconfig:

ac_add_options --with-android-toolchain=/path/to/android-ndk-r6/toolchains/arm-linux-androideabi-4.6.1/prebuilt/linux-x86

Or the following for the 64-bits toolchain:

ac_add_options --with-android-toolchain=/path/to/android-ndk-r6/toolchains/arm-linux-androideabi-4.6.1/prebuilt/linux-x86_64

Note that currently, elfhack doesn't support the resulting binaries very well, so you will need to also add the following to your .mozconfig:

ac_add_options --disable-elf-hack

Or, if you don't want to build it yourself, you can get the corresponding pre-built NDK (32-bits) (thanks to Brad Lassey for the temporary hosting). Please note it requires libstdc++ from gcc 4.5 or higher.

Here is a list of things you may need to know if you want to try various combinations of versions, and that I had to learn the hard way:

  • GCC 4.6.1 doesn't build with binutils 2.19 (GNU assembler lacks support for a few opcodes it uses)
  • GNU ld >= 2.21.1 has a crazy bug that leads to a crash of Firefox during startup. There is also a workaround.
  • Gold fails to build with gcc 4.1.1 (I was trying to build in the environment we use on the buildbots) because of warnings (it uses -Werror) in some versions, and because of an Internal Compiler Error with other versions.
  • When building with a toolchain that is not in the standard directory and that is newer than the system toolchain (like, in my case, using gcc 4.5 in /tools/gcc-4.5 instead of the system gcc 4.1.1), gold may end up with a libstdc++ dependency that is not satisfied with the system libstdc++. In that case, the NDK toolchain build will fail with the error message "Link tests are not allowed after GCC_NO_EXECUTABLES.", which isn't exactly helpful to understand what is wrong.
  • At some point, I was getting the same error as above when the build was occurring in parallel, and adding -j1 to the build-gcc.sh command line solved it. It hasn't happened to me in my recent attempts, though.
  • Gold 2.21.1 crashes when using Identical Code Folding. This is fixed on current binutils HEAD (which is why I took 2.21.53).

2011-08-01 17:48:16+0900

p.m.o

You can leave a response, or trackback from your own site.

19 Responses to “Building an Android NDK with recent GCC and binutils”

  1. Mike Long Says:

    This is exactly what I needed to jumpstart my attempts to build a *proper* Fortran compiler for Android!

    Thank you!!

  2. EricB Says:

    When adding the MPC_VERSION / register_var_option lines to build-gcc.sh, part of the second line was eaten by the HTML renderer, it should read :
    register_var_option “–mpc_version=’left-angled-bracket’version’right-angled-bracket'” MPC_VERSION “Specify mpc version”

    I guess some &lt / &gt are probably missing somewhere :)

    Otherwise, many thanks for this very useful post, it worked perfectly.

  3. glandium Says:

    EricB: fixed. Thanks.

  4. hudvin Says:

    Do you have copy of toolchain/binutils?
    Kernel.org is down.

  5. Vishrut Shah Says:

    Hi,
    I am currently trying to build GNU-static with full support of exceptions and rtti on Native Android Environment. With NDK, we are using it by APP_STL under NDK in Application.mk to use it but I need GNU-static for Native Android Environment. I check Android.mk file for building gnustl_static.a. But it is using the per-built libstdc++ library. How do I build it under Native Android Environment. I need a build process of building libstdc++.a. I checked it in build_gcc.sh. Seems like they are probably building it by doing make -j$JOBS but not sure. Can anyone help me how do I build libstdc++.a under Native Android Environment?

    Thanks,
    Vishrut Shah

  6. rp Says:

    @Vishrut: add –copy-libstdcxx to the build-gcc.sh command and you will get the libstdc++ from the compiler you are building.

  7. Vishrut Shah Says:

    Thanks rp.

  8. Jackie Gleason Says:

    Any idea why I am getting the following. I notice the library is in the ls I added at the end… http://pastebin.com/cw1j9LYX

    Great work btw!

  9. glandium Says:

    Jackie: no idea, sorry.

  10. Jackie Gleason Says:

    So does this work for sure with r6 and r6b?

  11. Jackie Gleason Says:

    nm

  12. Jackie Gleason Says:

    BTW per the bug list…

    This is not a defect, but a feature request :-).

    GMP 5.0.2 is not part of the toolchain sources distributed at android.googlesource.com/toolchain/gmp.git (note the new URL since we’re not using kernel.org anymore), so it’s no wonder that the build script fails to find it.

  13. Jackie Gleason Says:

    Got it but had to use their GMP. I just use my own binutils and GCC. Also had to add the following in build-gcc

    # Spot fix for binutils
    # Currently this seems to be a bug not sure
    # If it is due to the new Bin utils I am using
    dump “Fixing Google Bug Copying from $SRC_DIR/binutils/binutils-$BINUTILS_VERSION/binutils/sysinfo.h to $BUILD_OUT/binutils-2.22.51/binutils/sysinfo.h”
    mkdir -p $BUILD_OUT/binutils-2.22.51/binutils
    cp $SRC_DIR/binutils/binutils-$BINUTILS_VERSION/binutils/sysinfo.h $BUILD_OUT/binutils-2.22.51/binutils/

    # build the toolchain

  14. Rebuilding the Android NDK for Objective-C Support Says:

    […] Building an Android NDK with Recent GCC and Binutils. Hommey, Mike. Glandium. 1 Aug. 2011. […]

  15. Mikael Says:

    Jackie:

    I got that error when i used mpfr 3.1.0 instead of 3.0.1.

  16. halsafar Says:

    –copy-libstdcxx does not work anymore. How does one get the stl into the custom toolchain built.

  17. halsafar Says:

    I was wrong. The STL stuff copies fine. However compiling with the toolchain it can’t find basic stuff like string, vector. If I manually add the include line like (-I$(NDK_TOOLCHAIN)/arm-linux-androideabi/include/c++/4.6/ ) then it finds them. If I manually add all the includes it works. Surely something is broken.

  18. Oliver Stieber Says:

    I just pulled the latest r8 ndk and am trying to get it to work on arm, on ubuntu under android.

    So far I had to set
    USER=foobar
    to get the download to work as $USER had spaces in it
    also according to the bug report linked most of the issues solved by the patch are now non-issues, if not all of them. esp if you only want to target newer versions of Android

  19. Android JNI MAC OS环境配置 - 编程语言综合 - 开发者问答 Says:

    […] ndk是一个开发工具包,你也可以查看它的源码、进行编译,具体参考:http://glandium.org/blog/?p=2146 […]

Leave a Reply