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 (either STLport or
     69   the GNU libstdc++) with it. Also no exceptions and no RTTI.
     70 
     71 
     72 4/ Invoking the compiler (the easy way):
     73 ----------------------------------------
     74 
     75 The NDK allows you to create a "customized" toolchain installation to make
     76 life easier. For example, consider the following command:
     77 
     78         $NDK/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain
     79 
     80 This will create a directory named /tmp/my-android-toolchain containing a
     81 copy of the android-5/arch-arm sysroot, and of the toolchain binaries.
     82 
     83 Note that by default, the 32-bit ARM-based GCC 4.6 toolchain will be selected by the script.
     84 Use the '--arch=x86' option to specify the x86 GCC 4.6, or add '--arch=mips' option
     85 to specify the MIPS GCC 4.6, or alternatively
     86 '--toolchain=<name>'.  For example:
     87 
     88         --toolchain=x86-4.8                    # select x86 GCC 4.8 compiler
     89         --toolchain=arm-linux-androideabi-4.7  # select ARM GCC 4.7 compiler
     90         --toolchain=mipsel-linux-android-4.6   # select MIPS GCC 4.6 compiler, same as --arch=mips
     91 
     92 If you wish, add '--llvm-version=3.3' to also copy clang/llvm 3.3, or
     93 use --toolchain with '-clang3.3' suffix.  For example:
     94 
     95         --toolchain=arm-linux-androideabi-clang3.3  # same as --arch=arm --llvm-version=3.3
     96 
     97 You may specify --system=linux-x86_64 on 64-bit Linux or --system=darwin-x86_64 on 64-bit
     98 MacOSX to make 64-bit host toolchain instead of the 32-bit one (default).
     99 See IV of NDK-BUILD.html
    100 
    101 You may specify --stl=stlport to copy libstlport instead of libgnustl. Note that
    102 to link against the shared library, you will have to explicitely use -lstlport_shared
    103 in this case, just like you need to use -lgnustl_shared for the GNU libstdc++ case.
    104 Static linking doesn't require anything special.
    105 
    106 You can later use it directly with something like:
    107 
    108         export PATH=/tmp/my-android-toolchain/bin:$PATH
    109         export CC=arm-linux-androideabi-gcc   # or export CC=clang
    110         export CXX=arm-linux-androideabi-g++  # or export CXX=clang++
    111 
    112 Note that without the --install-dir option, make-standalone-toolchain.sh will
    113 create a tarball in /tmp/ndk/<toolchain-name>.tar.bz2. This allows you to
    114 archive and redistribute the binaries easily.
    115 
    116 Another important benefit is that this standalone toolchain will contain a
    117 working copy of a C++ STL library, with working exceptions and RTTI support.
    118 
    119 Use --help for more options and details.
    120 
    121 > IMPORTANT: The toolchain binaries do not depend or contain host-specific paths,
    122            in other words, they can be installed in any location, or even
    123            moved if you need to.
    124 
    125 > NOTE: You can still use the --sysroot option with the new toolchain, but it
    126       is now simply optional!
    127 
    128 
    129 5/ About Clang
    130 ---------------------
    131 
    132 It is possible to also install Clang binaries in the standalone
    133 installation by using the --llvm-version=<version> option, where
    134 <version> is a LLVM/Clang version number (e.g. `3.2` or `3.3`). E.g.:
    135 
    136         build/tools/make-standalone-toolchain.sh \
    137             --install-dir=/tmp/mydir \
    138             --toolchain=arm-linux-androideabi-4.7 \
    139             --llvm-version=3.3
    140 
    141 Note that Clang binaries are copied in addition to the GCC ones, because
    142 they rely on the same assembler, linker, headers, libraries and C++
    143 STL implementation.
    144 
    145 This also installs two scripts under <install-dir>/bin/ named '`clang`'
    146 and '`clang++`' which invoke the real clang binary with default
    147 target architecture flags. In other words, they should "just work" and
    148 you should be able to use them in your own builds by setting CC and CXX
    149 environment variables to point to them.
    150 
    151 The rest of this section gives more detail about how these work, in case
    152 you encounter some unexpected problems.
    153 
    154 For example, in an ARM standalone installation built with
    155 `--llvm-version=3.3`, `clang` is a one-liner that looks like this on Unix:
    156 
    157         `dirname $0`/clang31 -target armv5te-none-linux-androideabi "$@"
    158 
    159 And `clang++` invokes `clang++31` in the same way.
    160 
    161 Note that for ARM, `clang` will change target based on the presence of
    162 subsequent option "`-march=armv7-a`" and/or "`-mthumb`".  ie.
    163 
    164   1. With "`-march=armv7-a`", -target becomes `armv7-none-linux-androideabi`.
    165   2. With "`-mthumb`", -target becomes `thumb-none-linux-androideabi`.
    166   3. With both, -target becomes `thumbv7-none-linux-androideabi`.
    167 
    168 You may override with your own -target if you wish.
    169 
    170 Extra efforts have been made to make clang/clang++ easier drop-in
    171 replacements for gcc/g++ in Makefile.  When in doubt, use the following
    172 common techniques to check:
    173 
    174   1. Add option "`-v`" to dump commands compiler driver issues
    175   2. Add option "`-###`" to dump command line options, including those
    176      implicitly predefined.
    177   3. Use "`-x c` `/dev/null` `-dM` `-E`" to dump predefined preprocessor definitions
    178   4. Add option "`-save-temps`" and compare the preprocessed files `*.i` or `*.ii`
    179 
    180 See http://clang.llvm.org/ , especially the GCC compatibility section.
    181 
    182 
    183 6/ ABI Compatibility:
    184 ---------------------
    185 
    186 The machine code generated by the ARM toolchain should be compatible with
    187 the official Android 'armeabi' ABI (see docs/CPU-ARCH-ABIS.html) by default.
    188 
    189 It is recommended to use the -mthumb compiler flag to force the generation
    190 of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones).
    191 
    192 If you want to target the 'armeabi-v7a' ABI, you will need ensure that the
    193 following flags are being used:
    194 
    195         CFLAGS='-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16'
    196 
    197 Note: The first flag enables Thumb-2 instructions, and the second one
    198       enables H/W FPU instructions while ensuring that floating-point
    199       parameters are passed in core registers, which is critical for
    200       ABI compatibility. Do *not* use these flags separately!
    201 
    202 If you want to use Neon instructions, you will need to change the -mfpu
    203 compiler flag:
    204 
    205         CFLAGS='-march=armv7-a -mfloat-abi=softfp -mfpu=neon'
    206 
    207 Note that this forces the use of VFPv3-D32, as per the ARM specification.
    208 
    209 Also, make sure the following two flags are provided to linker:
    210 
    211         LDFLAGS='-march=armv7-a -Wl,--fix-cortex-a8'
    212 
    213 Note: The first flag instructs linker to pick libgcc.a, libgcov.a and
    214       crt*.o tailored for armv7-a.  The 2nd flag is *required* to route
    215       around a CPU bug in some Cortex-A8 implementations:
    216 
    217 If none of the above makes sense to you, it's probably better not to use
    218 the standalone toolchain, and stick to the NDK build system instead, which
    219 will handle all the details for you.
    220 
    221 You don't have to use any specific compiler flag when targeting the x86 ABI
    222 or the MIPS ABI.
    223 
    224 7/ Warnings and Limitations:
    225 --------------------------
    226 
    227 ### 7.1/ Windows support:
    228 
    229 The Windows binaries do *not* depend on Cygwin. The good news is that they
    230 are thus faster, the bad news is that they do not understand the Cygwin
    231 path specification like `/cygdrive/c/foo/bar` (instead of `C:/foo/bar`).
    232 
    233 The NDK build system ensures that all paths passed to the compiler from Cygwin
    234 are automatically translated, and deals with other horrors for you. If you have
    235 a custom build system, you may need to deal with the problem yourself.
    236 
    237 NOTE: There is no plan to support Cygwin / MSys at the moment, but
    238       contributions are welcome. Contact the android-ndk forum for details.
    239 
    240 
    241 ### 7.2/ wchar_t support:
    242 
    243 As documented, the Android platform did not really support wchar_t until
    244 Android 2.3. What this means in practical terms is that:
    245 
    246   - If you target platform android-9 or higher, the size of wchar_t is
    247     4 bytes, and most wide-char functions are available in the C library
    248     (with the exception of multi-byte encoding/decoding functions and
    249      wsprintf/wsscanf).
    250 
    251   - If you target any prior API level, the size of wchar_t will be 1 byte
    252     and none of the wide-char functions will work anyway.
    253 
    254 We recommend any developer to get rid of any dependencies on the wchar_t type
    255 and switch to better representations. The support provided in Android is only
    256 there to help you migrate existing code.
    257 
    258 
    259 ### 7.3/ Exceptions, RTTI and STL:
    260 
    261 The toolchain binaries *do* support C++ exceptions and RTTI by default.
    262 They are enabled by default, so use -fno-exceptions and -fno-rtti if you
    263 want to disable them when building sources with them (e.g. to generate
    264 smaller machine code).
    265 
    266 NOTE: If you use the GNU libstdc++, you will need to explicitly link with
    267 libsupc++ if you use these features. To do this, use -lsupc++ when
    268 linking binaries, as in:
    269 
    270           arm-linux-androideabi-g++ .... -lsupc++
    271 
    272 This is not needed when using the STLport library.
    273 
    274 
    275 ### 7.4/ C++ STL support:
    276 
    277 The standalone toolchain includes a copy of a C++ Standard Template Library
    278 implementation, either the GNU libstdc++, or STLport, determined by your
    279 use of the --stl=<name> option described previously. To use this STL
    280 implementation, you however need to link your project with the proper
    281 library:
    282 
    283   * Use -lstdc++ to link against the _static_ library version of any
    284     implementation. This ensures that all required C++ STL code is
    285     included into your final binary. This is ideal if you are only
    286     generating a **single** shared library or executable.
    287 
    288     This is the recommended way to do it.
    289 
    290   * Use -lgnustl_shared to link against the _shared_ library version of
    291     GNU libstdc++. If you use this option, you need to ensure that
    292     `libgnustl_shared.so` is also copied to your device for your code to
    293     load properly. The file is at:
    294 
    295         $TOOLCHAIN/arm-linux-androideabi/lib/  for ARM toolchains.
    296         $TOOLCHAIN/i686-linux-android/lib/     for x86 ones.
    297         $TOOLCHAIN/mipsel-linux-android/lib/   for MIPS toolchains.
    298 
    299     IMPORTANT: The GNU libstdc++ is licensed under the **GPLv3** with a
    300                linking exception. See the following URL for details:
    301 
    302 > http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01s02.html
    303 
    304 > If you cannot comply with its requirements, i.e. you cannot redistribute
    305   the shared library, do not use it in your project.
    306 
    307   * Use -stlport_shared to link against the _shared_ library version of
    308     STLport. If you use this option, you need to ensure that
    309     `libstlport_shared.so` is also copied to your device for your code
    310     to load properly. They are found at the same locations than those
    311     for `gnustl_shared`.
    312 
    313 **VERY** **IMPORTANT** **NOTE**:
    314 If your project contains _multiple_ shared libraries or
    315 executables, you **must** link against a shared library STL implementation.
    316 Otherwise, some global variables won't be defined uniquely, which can
    317 result in all kind of weird behaviour at runtime, like crashes, exceptions
    318 not being caught properly, and more surprises.
    319 
    320 The reason the shared version of the libraries is not simply called
    321 `libstdc++.so` is not called libstdc++.so is because this would conflict
    322 at runtime with the system's own minimal C++ runtime, which is
    323 `/system/lib/libstdc++.so`. This enforces a new name for the GNU ELF
    324 library. This is not a problem for the static library.
    325