You can use the toolchains provided with the Android NDK independently or as plug-ins with an existing IDE. This flexibility can be useful if you already have your own build system, and only need the ability to invoke the cross-compiler in order to add support to Android for it.
Select your toolchain
Before anything else, you need to decide which processor architecture your
standalone toolchain is going to target. This is done with the --arch
flag.
Select your sysroot
The next thing you need to do is define your sysroot. A sysroot is a directory containing the system headers and libraries for your target. To define the sysroot, you must must know the Android API level you want to target for native support; available native APIs vary by Android API level.
Libraries for native APIs for the respective Android API levels reside under
$NDK/platforms/
; each API-level directory, in turn, contains subdirectories
for the various CPUs and architectures. The headers reside in $NDK/sysroot
.
For more detail about the Android API levels and the respective native APIs they support, see Native APIs.
Create the toolchain
The NDK provides the make_standalone_toolchain.py
script to allow you to
perform a customized toolchain installation from the command line.
This is a new tool that replaces the old make-standalone-toolchain.sh
. It has
been reimplented in Python so that Windows users will not need to install
Cygwin or MSYS
to run it.
The script is located in the $NDK/build/tools/
directory, where $NDK
is the
installation root for the NDK.
An example of the use of this script appears below:
$NDK/build/tools/make_standalone_toolchain.py \
--arch arm --api 21 --install-dir /tmp/my-android-toolchain
This command creates a directory named /tmp/my-android-toolchain/
, containing
a copy of the android-21/arch-arm
sysroot, and of the toolchain binaries for a
32-bit ARM target.
Note that the toolchain binaries do not depend on or contain host-specific paths. In other words, you can install them in any location or even move them if you need to.
The --arch
argument is required, but the API level will default to the minimum
supported level for the given architecture (currently 16 for 32-bit
architectures and 21 for 64-bit architectures).
Since r18, all standalone toolchains use Clang and libc++. The libc++ shared
library will be used by default unless building a static executable. To force
the use of the static library, pass -static-libstdc++
when linking. This
behavior matches that of a normal host toolchain.
As mentioned in C++ library support, you will often need to
pass -latomic
when linking against libc++.
Note that if you omit the --install-dir
option, the tool creates a tarball in
the current directory named $TOOLCHAIN_NAME.tar.bz2
. The tarball can be placed
in a different directory by using --package-dir
.
For more options and details, use --help
.
Work with Clang
Clang binaries are automatically included in standalone toolchains.
There are also two wrapper scripts, named clang
and clang++
,
under <install-dir>/bin
. These scripts invoke the clang
binary with the
correct target architecture flags. In other words, they should work without any
modification, and you should be able to use them in your own builds by just
setting the CC
and CXX
environment variables to point to them.
There are also wrapper scripts named gcc
and g++
that also call Clang.
This is to provide some level of compatibility for build files that explicitly
refer to GCC even though the NDK no longer contains GCC. Obviously, if a build
file uses command-line options that aren't supported by Clang, you'll need to
remove or replace them.
Clang targets with ARM
When building for ARM, Clang changes the target based on the presence of the
-march=armv7-a
and/or -mthumb
compiler flags:
Table 1. Specifiable -march
values and their resulting targets.
-march value |
Resulting target |
---|---|
-march=armv7-a |
armv7-none-linux-androideabi |
-mthumb |
thumb-none-linux-androideabi |
Both -march=armv7-a and -mthumb |
thumbv7-none-linux-androideabi |
You may also override with your own -target
if you wish.
clang
and clang++
should be drop-in replacements for gcc
and g++
in a
makefile. When in doubt, use the following options when invoking the compiler to
verify that they are working properly:
-v
to dump commands associated with compiler driver issues-###
to dump command line options, including implicitly predefined ones.-x c < /dev/null -dM -E
to dump predefined preprocessor definitions-save-temps
to compare*.i
or*.ii
preprocessed files.
ABI compatibility
By default, an ARM Clang standalone toolchain will target the armeabi-v7a ABI.
This can be overridden by passing the appropriate -march
or -target
option.
We recommend using the -mthumb
compiler flag to force the generation of
16-bit Thumb-2 instructions. If omitted, the toolchain will emit 32-bit ARM
instructions.
To use NEON instructions, you must use the -mfpu
compiler flag: -mfpu=neon
.
Note that this setting forces the use of VFPv3-D32
, per the ARM specification.
Also, make sure to provide the following two flags to the linker:
-march=armv7-a -Wl,--fix-cortex-a8
.
The first flag instructs the linker to pick toolchain libraries which are tailored for armv7-a. The 2nd flag is required as a workaround for a CPU bug in some Cortex-A8 implementations.
You don't have to use any specific compiler flag when targeting the other ABIs.
To learn more about ABI support, see Android ABIs.
Warnings and limitations
Windows support
The Windows binaries do not depend on Cygwin. This lack of dependency makes them
faster. The cost, however, is that they do not understand Cygwin path
specifications like cygdrive/c/foo/bar
, as opposed to C:/foo/bar
.
Exceptions, RTTI, and STL
The toolchain binaries support C++ exceptions and RTTI by default. To disable
C++ exceptions and RTTI when building sources (to generate lighter-weight
machine code, for example), use -fno-exceptions
and -fno-rtti
.
C++ STL support
The standalone toolchain includes a C++ Standard Template Library (STL) implementation.
Use
-static-libstdc++
to get the static library version of libc++. Doing so ensures that all required C++ STL code is included into your final binary. This method is ideal if you are only generating a single shared library or executable, which is our recommendation.The shared library version of libc++ will be used by default. No additional flags are needed to link against the shared library. You must package
libc++_shared.so
in your app, or your code will not load.Table 2 shows where this file is for each architecture.
Table 2. Specifiable
-march
values and their resulting targets.Toolchain Location arm $TOOLCHAIN/arm-linux-androideabi/lib/
arm64 $TOOLCHAIN/aarch64-linux-android/lib/
x86 $TOOLCHAIN/i686-linux-android/lib/
x86_64 $TOOLCHAIN/x86_64-linux-android/lib/
Build open source projects with standalone toolchains
Given this example toolchain:
# Create an arm64 API 26 libc++ toolchain.
$NDK/build/tools/make_standalone_toolchain.py \
--arch arm64 \
--api 26 \
--install-dir=my-toolchain
Here's how you'd set up your environment to use it to build a traditional open source project:
# Add the standalone toolchain to the search path.
export PATH=$PATH:`pwd`/my-toolchain/bin
# Tell configure what tools to use.
target_host=aarch64-linux-android
export AR=$target_host-ar
export AS=$target_host-clang
export CC=$target_host-clang
export CXX=$target_host-clang++
export LD=$target_host-ld
export STRIP=$target_host-strip
# Tell configure what flags Android requires.
export CFLAGS="-fPIE -fPIC"
export LDFLAGS="-pie"
Projects with custom build systems
As an example, here's how to build toybox after performing the previous steps:
git clone https://github.com/landley/toybox.git
cd toybox
make defconfig && make
Projects with autoconf
Alternatively a autoconf-based project would look more like this:
tar zxvf make-4.2.tar.gz
cd make-4.2
./configure --host=$target_host && make
Note that autoconf-based projects vary wildly in their support for
cross-compilation. Note also that if you git clone
a autoconf-based
project, it's unlikely to have a checked-in configure
script, so you'll
have to follow that project's documentation for how to bootstrap.