• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1USING THE ANDROID TOOLCHAIN AS A STANDALONE COMPILER
2======================================================
3
4It is now possible to use the toolchains provided with the Android NDK as
5standalone compilers. This can be useful if you already have your own build
6system, and only need to ability to invoke the cross-compiler to add support
7to Android for it.
8
9A typical use case if invoking the 'configure' script of an open-source
10library that expects a cross-compiler in the CC environment variable.
11
12
13This document explains how to do that:
14
151/ Selecting your toolchain:
16----------------------------
17
18Before anything else, you need to decide whether your standalone toolchain
19is going to target ARM-based devices, x86-based, or MIPS-based one.
20Each 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
262/ Selecting your sysroot:
27--------------------------
28
29The second thing you need to know is which Android native API level you want
30to target. Each one of them provides a different various APIs, which are
31documented under doc/STABLE-APIS.html, and correspond to the sub-directories
32of $NDK/platforms.
33
34This allows you to define the path to your 'sysroot', a GCC term for a
35directory containing the system headers and libraries of your target.
36Usually, this will be something like:
37
38        SYSROOT=$NDK/platforms/android-<level>/arch-<arch>/
39
40Where <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
42targeting Android 2.2 (a.k.a. Froyo), you would use:
43
44        SYSROOT=$NDK/platforms/android-8/arch-arm
45
46IMPORTANT: Note that X86 and MIPS architectures are only supported at android-9 and later.
47
483/ Invoking the compiler (the hard way):
49----------------------------------------
50
51Invoke the compiler using the --sysroot option to indicate where the system
52files 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
57Where <name> is the toolchain's name, <system> is the host tag for your system,
58and <prefix> is a toolchain-specific prefix. For example, if you are on Linux
59using 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
63As you can see, this is rather verbose, but it works!
64
65IMPORTANT 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
794/ Invoking the compiler (the easy way):
80----------------------------------------
81
82The NDK allows you to create a "customized" toolchain installation to make
83life 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
87This will create a directory named /tmp/my-android-toolchain containing a
88copy of the android-5/arch-arm sysroot, and of the toolchain binaries.
89
90Note that by default, the 32-bit ARM-based GCC 4.6 toolchain will be selected by the script.
91Use the '--arch=x86' option to specify the x86 GCC 4.6, or add '--arch=mips' option
92to 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
99If you wish, add '--llvm-version=3.3' to also copy clang/llvm 3.3, or
100use --toolchain with '-clang3.3' suffix.  For example:
101
102        --toolchain=arm-linux-androideabi-clang3.3  # same as --arch=arm --llvm-version=3.3
103
104You may specify --system=linux-x86_64 on 64-bit Linux or --system=darwin-x86_64 on 64-bit
105MacOSX to make 64-bit host toolchain instead of the 32-bit one (default).
106See IV of NDK-BUILD.html
107
108You may specify --stl=stlport to copy libstlport instead of libgnustl. Note that
109to link against the shared library, you will have to explicitely use -lstlport_shared
110in this case, just like you need to use -lgnustl_shared for the GNU libstdc++ case.
111Static linking doesn't require anything special.
112
113Likewise you may specify --stl=libc++ to copy LLVM libc++ headers and libraries. Note that
114to link against the shared library, you will have to explicitely use -lc++_shared.
115
116You 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
122Note that without the --install-dir option, make-standalone-toolchain.sh will
123create a tarball in /tmp/ndk/<toolchain-name>.tar.bz2. This allows you to
124archive and redistribute the binaries easily.
125
126Another important benefit is that this standalone toolchain will contain a
127working copy of a C++ STL library, with working exceptions and RTTI support.
128
129Use --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
1395/ About Clang
140---------------------
141
142It is possible to also install Clang binaries in the standalone
143installation 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
151Note that Clang binaries are copied in addition to the GCC ones, because
152they rely on the same assembler, linker, headers, libraries and C++
153STL implementation.
154
155This also installs two scripts under <install-dir>/bin/ named '`clang`'
156and '`clang++`' which invoke the real clang binary with default
157target architecture flags. In other words, they should "just work" and
158you should be able to use them in your own builds by setting CC and CXX
159environment variables to point to them.
160
161The rest of this section gives more detail about how these work, in case
162you encounter some unexpected problems.
163
164For 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
169And `clang++` invokes `clang++31` in the same way.
170
171Note that for ARM, `clang` will change target based on the presence of
172subsequent 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
178You may override with your own -target if you wish.
179
180There is no need for "-gcc-toolchain" because clang locates "as" and "ld" in
181predefined relative location in standalone package.
182
183Extra efforts have been made to make clang/clang++ easier drop-in
184replacements for gcc/g++ in Makefile.  When in doubt, use the following
185common 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
193See http://clang.llvm.org/ , especially the GCC compatibility section.
194
195
1966/ ABI Compatibility:
197---------------------
198
199The machine code generated by the ARM toolchain should be compatible with
200the official Android 'armeabi' ABI (see docs/CPU-ARCH-ABIS.html) by default.
201
202It is recommended to use the -mthumb compiler flag to force the generation
203of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones).
204
205If you want to target the 'armeabi-v7a' ABI, you will need ensure that the
206following flags are being used:
207
208        CFLAGS='-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16'
209
210Note: 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
216If you want to use Neon instructions, you will need to change the -mfpu
217compiler flag:
218
219        CFLAGS='-march=armv7-a -mfloat-abi=softfp -mfpu=neon'
220
221Note that this forces the use of VFPv3-D32, as per the ARM specification.
222
223Also, make sure the following two flags are provided to linker:
224
225        LDFLAGS='-march=armv7-a -Wl,--fix-cortex-a8'
226
227Note: 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
231Since NDK r9b, all Android native APIs taking or returning double/float
232has __attribute__((pcs("aapcs"))) for ARM.  It's possible to compile
233user code in -mhard-float (which implies -mfloat-abi=hard) and still
234link with Android native APIs which follow softfp ABI.  Please see
235tests/device/hard-float/jni/Android.mk for details.
236
237If you want to use Neon intrinsics on x86 they can be translated to the native
238x86 SSE ones using special C/C++ language header with the same name as
239standard arm neon intrinsics header "arm_neon.h".
240By default x86 ABI supports SIMD up to SSE3 and the header covers ~83% NEON
241functions (1551 of total 1872). It is recommended to use the -mssse3 compiler
242flag 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
247To learn more about it, see docs/CPU-X86.html
248
249If none of the above makes sense to you, it's probably better not to use
250the standalone toolchain, and stick to the NDK build system instead, which
251will handle all the details for you.
252
253You don't have to use any specific compiler flag when targeting the MIPS ABI.
254
2557/ Warnings and Limitations:
256--------------------------
257
258### 7.1/ Windows support:
259
260The Windows binaries do *not* depend on Cygwin. The good news is that they
261are thus faster, the bad news is that they do not understand the Cygwin
262path specification like `/cygdrive/c/foo/bar` (instead of `C:/foo/bar`).
263
264The NDK build system ensures that all paths passed to the compiler from Cygwin
265are automatically translated, and deals with other horrors for you. If you have
266a custom build system, you may need to deal with the problem yourself.
267
268NOTE: 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
274As documented, the Android platform did not really support wchar_t until
275Android 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
285We recommend any developer to get rid of any dependencies on the wchar_t type
286and switch to better representations. The support provided in Android is only
287there to help you migrate existing code.
288
289
290### 7.3/ Exceptions, RTTI and STL:
291
292The toolchain binaries *do* support C++ exceptions and RTTI by default.
293They are enabled by default, so use -fno-exceptions and -fno-rtti if you
294want to disable them when building sources with them (e.g. to generate
295smaller machine code).
296
297NOTE: If you use the GNU libstdc++, you will need to explicitly link with
298libsupc++ if you use these features. To do this, use -lsupc++ when
299linking binaries, as in:
300
301          arm-linux-androideabi-g++ .... -lsupc++
302
303This is not needed when using the STLport or libc++ library.
304
305
306### 7.4/ C++ STL support:
307
308The standalone toolchain includes a copy of a C++ Standard Template Library
309implementation, either the GNU libstdc++, STLport, or libc++, determined by your
310use of the --stl=<name> option described previously. To use this STL
311implementation, you however need to link your project with the proper
312library:
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**:
345If your project contains _multiple_ shared libraries or
346executables, you **must** link against a shared library STL implementation.
347Otherwise, some global variables won't be defined uniquely, which can
348result in all kind of weird behaviour at runtime, like crashes, exceptions
349not being caught properly, and more surprises.
350
351The reason the shared version of the libraries is not simply called
352`libstdc++.so` is not called libstdc++.so is because this would conflict
353at 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
355library. This is not a problem for the static library.
356