Home | History | Annotate | Download | only in text
      1 USING THE ANDROID TOOLCHAIN AS A STANDALONE COMPILER
      2 ======================================================
      3 
      4 It is now possible to use the toolchains provided with the Android NDK as
      5 standalone compilers. This can be useful if you already have your own build
      6 system, and only need to ability to invoke the cross-compiler to add support
      7 to Android for it.
      8 
      9 A typical use case if invoking the 'configure' script of an open-source
     10 library that expects a cross-compiler in the CC environment variable.
     11 
     12 
     13 This document explains how to do that:
     14 
     15 1/ Selecting your toolchain:
     16 ----------------------------
     17 
     18 Before anything else, you need to decide whether your standalone toolchain
     19 is going to target ARM-based devices, x86-based, or MIPS-based one.
     20 Each architecture corresponds to a different toolchain name.  For example:
     21 
     22   * arm-linux-androideabi-4.6   => targeting ARM-based Android devices
     23   * x86-4.6                     => targeting x86-based Android devices
     24   * mipsel-linux-android-4.6    => targeting MIPS-based Android devices
     25 
     26 2/ Selecting your sysroot:
     27 --------------------------
     28 
     29 The second thing you need to know is which Android native API level you want
     30 to target. Each one of them provides a different various APIs, which are
     31 documented under doc/STABLE-APIS.html, and correspond to the sub-directories
     32 of $NDK/platforms.
     33 
     34 This allows you to define the path to your 'sysroot', a GCC term for a
     35 directory containing the system headers and libraries of your target.
     36 Usually, this will be something like:
     37 
     38         SYSROOT=$NDK/platforms/android-<level>/arch-<arch>/
     39 
     40 Where <level> is the API level number, and <arch> is the architecture
     41 ("arm", "x86", and "mips" are the supported values). For example, if you're
     42 targeting Android 2.2 (a.k.a. Froyo), you would use:
     43 
     44         SYSROOT=$NDK/platforms/android-8/arch-arm
     45 
     46 IMPORTANT: Note that X86 and MIPS architectures are only supported at android-9 and later.
     47 
     48 3/ Invoking the compiler (the hard way):
     49 ----------------------------------------
     50 
     51 Invoke the compiler using the --sysroot option to indicate where the system
     52 files for the platform you're targeting are located. For example, do:
     53 
     54         export CC="$NDK/toolchains/<name>/prebuilt/<system>/bin/<prefix>gcc --sysroot=$SYSROOT"
     55         $CC -o foo.o -c foo.c
     56 
     57 Where <name> is the toolchain's name, <system> is the host tag for your system,
     58 and <prefix> is a toolchain-specific prefix. For example, if you are on Linux
     59 using the NDK r5 toolchain, you would use:
     60 
     61         export CC="$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT"
     62 
     63 As you can see, this is rather verbose, but it works!
     64 
     65 IMPORTANT NOTE:
     66 
     67 > Using the NDK toolchain directly has a serious limitation:
     68   You won't be able to use any C++ STL (STLport, libc++,
     69   the GNU libstdc++) with it. Also no exceptions and no RTTI.
     70 
     71 > For clang, you need to add correct "-target" for given architecture, and add
     72   "-gcc-toolchain" to path of GNU-based toolchain for "as" and "ld", eg.
     73 
     74   1. Add "-target armv7-none-linux-androideabi" for armeabi-v7a, "-target armv5te-none-linux-androideabi"
     75      for armeabi, "-target i686-none-linux-android" for x86, "-target mipsel-none-linux-android" for mips, and
     76   2. Add "-gcc-toolchain $NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64"
     77 
     78 
     79 4/ Invoking the compiler (the easy way):
     80 ----------------------------------------
     81 
     82 The NDK allows you to create a "customized" toolchain installation to make
     83 life easier. For example, consider the following command:
     84 
     85         $NDK/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain
     86 
     87 This will create a directory named /tmp/my-android-toolchain containing a
     88 copy of the android-5/arch-arm sysroot, and of the toolchain binaries.
     89 
     90 Note that by default, the 32-bit ARM-based GCC 4.6 toolchain will be selected by the script.
     91 Use the '--arch=x86' option to specify the x86 GCC 4.6, or add '--arch=mips' option
     92 to specify the MIPS GCC 4.6, or alternatively
     93 '--toolchain=<name>'.  For example:
     94 
     95         --toolchain=x86-4.8                    # select x86 GCC 4.8 compiler
     96         --toolchain=arm-linux-androideabi-4.7  # select ARM GCC 4.7 compiler
     97         --toolchain=mipsel-linux-android-4.6   # select MIPS GCC 4.6 compiler, same as --arch=mips
     98 
     99 If you wish, add '--llvm-version=3.3' to also copy clang/llvm 3.3, or
    100 use --toolchain with '-clang3.3' suffix.  For example:
    101 
    102         --toolchain=arm-linux-androideabi-clang3.3  # same as --arch=arm --llvm-version=3.3
    103 
    104 You may specify --system=linux-x86_64 on 64-bit Linux or --system=darwin-x86_64 on 64-bit
    105 MacOSX to make 64-bit host toolchain instead of the 32-bit one (default).
    106 See IV of NDK-BUILD.html
    107 
    108 You may specify --stl=stlport to copy libstlport instead of libgnustl. Note that
    109 to link against the shared library, you will have to explicitely use -lstlport_shared
    110 in this case, just like you need to use -lgnustl_shared for the GNU libstdc++ case.
    111 Static linking doesn't require anything special.
    112 
    113 Likewise you may specify --stl=libc++ to copy LLVM libc++ headers and libraries. Note that
    114 to link against the shared library, you will have to explicitely use -lc++_shared.
    115 
    116 You can later use it directly with something like:
    117 
    118         export PATH=/tmp/my-android-toolchain/bin:$PATH
    119         export CC=arm-linux-androideabi-gcc   # or export CC=clang
    120         export CXX=arm-linux-androideabi-g++  # or export CXX=clang++
    121 
    122 Note that without the --install-dir option, make-standalone-toolchain.sh will
    123 create a tarball in /tmp/ndk/<toolchain-name>.tar.bz2. This allows you to
    124 archive and redistribute the binaries easily.
    125 
    126 Another important benefit is that this standalone toolchain will contain a
    127 working copy of a C++ STL library, with working exceptions and RTTI support.
    128 
    129 Use --help for more options and details.
    130 
    131 > IMPORTANT: The toolchain binaries do not depend or contain host-specific paths,
    132            in other words, they can be installed in any location, or even
    133            moved if you need to.
    134 
    135 > NOTE: You can still use the --sysroot option with the new toolchain, but it
    136       is now simply optional!
    137 
    138 
    139 5/ About Clang
    140 ---------------------
    141 
    142 It is possible to also install Clang binaries in the standalone
    143 installation by using the --llvm-version=<version> option, where
    144 <version> is a LLVM/Clang version number (e.g. `3.2` or `3.3`). E.g.:
    145 
    146         build/tools/make-standalone-toolchain.sh \
    147             --install-dir=/tmp/mydir \
    148             --toolchain=arm-linux-androideabi-4.7 \
    149             --llvm-version=3.3
    150 
    151 Note that Clang binaries are copied in addition to the GCC ones, because
    152 they rely on the same assembler, linker, headers, libraries and C++
    153 STL implementation.
    154 
    155 This also installs two scripts under <install-dir>/bin/ named '`clang`'
    156 and '`clang++`' which invoke the real clang binary with default
    157 target architecture flags. In other words, they should "just work" and
    158 you should be able to use them in your own builds by setting CC and CXX
    159 environment variables to point to them.
    160 
    161 The rest of this section gives more detail about how these work, in case
    162 you encounter some unexpected problems.
    163 
    164 For example, in an ARM standalone installation built with
    165 `--llvm-version=3.3`, `clang` is a one-liner that looks like this on Unix:
    166 
    167         `dirname $0`/clang31 -target armv5te-none-linux-androideabi "$@"
    168 
    169 And `clang++` invokes `clang++31` in the same way.
    170 
    171 Note that for ARM, `clang` will change target based on the presence of
    172 subsequent option "`-march=armv7-a`" and/or "`-mthumb`".  ie.
    173 
    174   1. With "`-march=armv7-a`", -target becomes `armv7-none-linux-androideabi`.
    175   2. With "`-mthumb`", -target becomes `thumb-none-linux-androideabi`.
    176   3. With both, -target becomes `thumbv7-none-linux-androideabi`.
    177 
    178 You may override with your own -target if you wish.
    179 
    180 There is no need for "-gcc-toolchain" because clang locates "as" and "ld" in
    181 predefined relative location in standalone package.
    182 
    183 Extra efforts have been made to make clang/clang++ easier drop-in
    184 replacements for gcc/g++ in Makefile.  When in doubt, use the following
    185 common techniques to check:
    186 
    187   1. Add option "`-v`" to dump commands compiler driver issues
    188   2. Add option "`-###`" to dump command line options, including those
    189      implicitly predefined.
    190   3. Use "`-x c` `/dev/null` `-dM` `-E`" to dump predefined preprocessor definitions
    191   4. Add option "`-save-temps`" and compare the preprocessed files `*.i` or `*.ii`
    192 
    193 See http://clang.llvm.org/ , especially the GCC compatibility section.
    194 
    195 
    196 6/ ABI Compatibility:
    197 ---------------------
    198 
    199 The machine code generated by the ARM toolchain should be compatible with
    200 the official Android 'armeabi' ABI (see docs/CPU-ARCH-ABIS.html) by default.
    201 
    202 It is recommended to use the -mthumb compiler flag to force the generation
    203 of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones).
    204 
    205 If you want to target the 'armeabi-v7a' ABI, you will need ensure that the
    206 following flags are being used:
    207 
    208         CFLAGS='-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16'
    209 
    210 Note: The first flag enables Thumb-2 instructions, and the second one
    211       enables H/W FPU instructions while ensuring that floating-point
    212       parameters are passed in core registers, which is critical for
    213       ABI compatibility. Do *not* use these flags separately before
    214       NDK r9b!
    215 
    216 If you want to use Neon instructions, you will need to change the -mfpu
    217 compiler flag:
    218 
    219         CFLAGS='-march=armv7-a -mfloat-abi=softfp -mfpu=neon'
    220 
    221 Note that this forces the use of VFPv3-D32, as per the ARM specification.
    222 
    223 Also, make sure the following two flags are provided to linker:
    224 
    225         LDFLAGS='-march=armv7-a -Wl,--fix-cortex-a8'
    226 
    227 Note: The first flag instructs linker to pick libgcc.a, libgcov.a and
    228       crt*.o tailored for armv7-a.  The 2nd flag is *required* to route
    229       around a CPU bug in some Cortex-A8 implementations:
    230 
    231 Since NDK r9b, all Android native APIs taking or returning double/float
    232 has __attribute__((pcs("aapcs"))) for ARM.  It's possible to compile
    233 user code in -mhard-float (which implies -mfloat-abi=hard) and still
    234 link with Android native APIs which follow softfp ABI.  Please see
    235 tests/device/hard-float/jni/Android.mk for details.
    236 
    237 If you want to use Neon intrinsics on x86 they can be translated to the native
    238 x86 SSE ones using special C/C++ language header with the same name as
    239 standard arm neon intrinsics header "arm_neon.h".
    240 By default x86 ABI supports SIMD up to SSE3 and the header covers ~83% NEON
    241 functions (1551 of total 1872). It is recommended to use the -mssse3 compiler
    242 flag which extends SIMD up to SSSE3 and in this case the header will cover
    243 ~98% NEON functions (1827 of total 1872):
    244 
    245         CFLAGS='-mssse3'
    246 
    247 To learn more about it, see docs/CPU-X86.html
    248 
    249 If none of the above makes sense to you, it's probably better not to use
    250 the standalone toolchain, and stick to the NDK build system instead, which
    251 will handle all the details for you.
    252 
    253 You don't have to use any specific compiler flag when targeting the MIPS ABI.
    254 
    255 7/ Warnings and Limitations:
    256 --------------------------
    257 
    258 ### 7.1/ Windows support:
    259 
    260 The Windows binaries do *not* depend on Cygwin. The good news is that they
    261 are thus faster, the bad news is that they do not understand the Cygwin
    262 path specification like `/cygdrive/c/foo/bar` (instead of `C:/foo/bar`).
    263 
    264 The NDK build system ensures that all paths passed to the compiler from Cygwin
    265 are automatically translated, and deals with other horrors for you. If you have
    266 a custom build system, you may need to deal with the problem yourself.
    267 
    268 NOTE: There is no plan to support Cygwin / MSys at the moment, but
    269       contributions are welcome. Contact the android-ndk forum for details.
    270 
    271 
    272 ### 7.2/ wchar_t support:
    273 
    274 As documented, the Android platform did not really support wchar_t until
    275 Android 2.3. What this means in practical terms is that:
    276 
    277   - If you target platform android-9 or higher, the size of wchar_t is
    278     4 bytes, and most wide-char functions are available in the C library
    279     (with the exception of multi-byte encoding/decoding functions and
    280      wsprintf/wsscanf).
    281 
    282   - If you target any prior API level, the size of wchar_t will be 1 byte
    283     and none of the wide-char functions will work anyway.
    284 
    285 We recommend any developer to get rid of any dependencies on the wchar_t type
    286 and switch to better representations. The support provided in Android is only
    287 there to help you migrate existing code.
    288 
    289 
    290 ### 7.3/ Exceptions, RTTI and STL:
    291 
    292 The toolchain binaries *do* support C++ exceptions and RTTI by default.
    293 They are enabled by default, so use -fno-exceptions and -fno-rtti if you
    294 want to disable them when building sources with them (e.g. to generate
    295 smaller machine code).
    296 
    297 NOTE: If you use the GNU libstdc++, you will need to explicitly link with
    298 libsupc++ if you use these features. To do this, use -lsupc++ when
    299 linking binaries, as in:
    300 
    301           arm-linux-androideabi-g++ .... -lsupc++
    302 
    303 This is not needed when using the STLport or libc++ library.
    304 
    305 
    306 ### 7.4/ C++ STL support:
    307 
    308 The standalone toolchain includes a copy of a C++ Standard Template Library
    309 implementation, either the GNU libstdc++, STLport, or libc++, determined by your
    310 use of the --stl=<name> option described previously. To use this STL
    311 implementation, you however need to link your project with the proper
    312 library:
    313 
    314   * Use -lstdc++ to link against the _static_ library version of any
    315     implementation. This ensures that all required C++ STL code is
    316     included into your final binary. This is ideal if you are only
    317     generating a **single** shared library or executable.
    318 
    319     This is the recommended way to do it.
    320 
    321   * Use -lgnustl_shared to link against the _shared_ library version of
    322     GNU libstdc++. If you use this option, you need to ensure that
    323     `libgnustl_shared.so` is also copied to your device for your code to
    324     load properly. The file is at:
    325 
    326         $TOOLCHAIN/arm-linux-androideabi/lib/  for ARM toolchains.
    327         $TOOLCHAIN/i686-linux-android/lib/     for x86 ones.
    328         $TOOLCHAIN/mipsel-linux-android/lib/   for MIPS toolchains.
    329 
    330     IMPORTANT: The GNU libstdc++ is licensed under the **GPLv3** with a
    331                linking exception. See the following URL for details:
    332 
    333 > http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01s02.html
    334 
    335 > If you cannot comply with its requirements, i.e. you cannot redistribute
    336   the shared library, do not use it in your project.
    337 
    338   * Use -lstlport_shared to link against the _shared_ library version of
    339     STLport. If you use this option, you need to ensure that
    340     `libstlport_shared.so` is also copied to your device for your code
    341     to load properly. They are found at the same locations than those
    342     for `gnustl_shared`.
    343 
    344 **VERY** **IMPORTANT** **NOTE**:
    345 If your project contains _multiple_ shared libraries or
    346 executables, you **must** link against a shared library STL implementation.
    347 Otherwise, some global variables won't be defined uniquely, which can
    348 result in all kind of weird behaviour at runtime, like crashes, exceptions
    349 not being caught properly, and more surprises.
    350 
    351 The reason the shared version of the libraries is not simply called
    352 `libstdc++.so` is not called libstdc++.so is because this would conflict
    353 at runtime with the system's own minimal C++ runtime, which is
    354 `/system/lib/libstdc++.so`. This enforces a new name for the GNU ELF
    355 library. This is not a problem for the static library.
    356