您的位置:首页 > 移动开发 > Android开发

android ndk Toolchain

2015-10-10 14:01 585 查看


Standalone Toolchain独立的工具链


On this page

Selecting Your Toolchain
Selecting Your Sysroot
Invoking the Compiler
Working with Clang
ABI Compatibility
Warnings and Limitations

You can use the toolchains provided with the Android NDK independently独立的, or as plug-ins with an existing IDE, such as Eclipse. 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.
A typical use case is invoking the configure script of an open-source library that expects预料 a cross-compiler in the 
CC
 environment variable.

Note: This page assumes假定 significant重要的 understanding of compiling, linking, and low-level architecture架构. In addition, the techniques it describes are unnecessary不必要的 for most use cases. In most cases, we recommend that you forego放弃 using
a standalone toolchain, and instead stick坚持 to the NDK build system.


Selecting Your Toolchain

Before anything else, you need to decide which processing architecture your standalone toolchain is going to target. Each architecture corresponds对应,相关 to a different toolchain name, as Table 1 shows.
Table 1. 
APP_ABI
 settings for different instruction sets.
ArchitectureToolchain name
ARM-based
arm-linux-androideabi-<gcc-version>
x86-based
x86-<gcc-version>
MIPS-based
mipsel-linux-android-<gcc-version>
ARM64-based
aarch64-linux-android-<gcc-version>
X86-64-based
x86_64-<gcc-version>
MIPS64-based
mips64el-linux-android--<gcc-version>


Selecting 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.
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 following example shows how to define asysroot for a build targeting Android
5.0 (API level 21), for ARM architecture:
SYSROOT=$NDK/platforms/android-21/arch-arm

For more detail about the Android API levels and the respective native APIs they support, see Android
NDK Native APIs.


Invoking the Compiler

There are two ways to invoke the compiler. One method is simple, and leaves most of the lifting to the build system. The other is more advanced, but provides more flexibility灵活性.


Simple method

The simplest way to build is by invoking the appropriate适当 compiler directly from the command line, using the 
--sysroot
 option to indicate指出 the location of the system files
for the platform you're targeting. For example:
export CC="$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/ \
linux-x86/bin/arm-linux-androideabi-gcc-4.8 --sysroot=$SYSROOT"
$CC -o foo.o -c foo.c

While this method is simple, it lacks缺少 in flexibility: It does not allow you to use any C++ STL (STLport, libc++, or the GNU libstdc++) with it. It also does not support exceptions例外 or RTTI.
For Clang, you need to perform an additional two steps:
Add the appropriate适当 
-target
 for the target architecture, as Table 2 shows.
Table 2. Architectures and corresponding values for 
-target
.
ArchitectureValue
armeabi
-target armv5te-none-linux-androideabi
armeabi-v7a
-target armv7-none-linux-androideabi
arm64-v8a
-target aarch64-none-linux-android
x86
-target i686-none-linux-android
x86_64
-target x86_64-none-linux-android
mips
-target mipsel-none-linux-android
Add assembler(汇编程序
汇编器) and linker support by adding the 
-gcc-toolchain
 option, as in the following example:
-gcc-toolchain $NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64


Ultimately最终, a command to compile using Clang might look like this:
export CC="$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/ \
linux-x86/bin/arm-linux-androideabi-gcc-4.8 --sysroot=$SYSROOT" -target \
armv7-none-linux-androideabi \
-gcc-toolchain $NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64"
$CC -o foo.o -c foo.c


Advanced method

The NDK provides the 
make-standalone-toolchain.sh
 shell script to allow you to perform a customized定制的 toolchain installation from the command line. This approach affords提供
you more flexibility灵活性 than the procedure described in Simple method.
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.sh \
--arch=arm --platform=android-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 architecture.
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.
By default, the build system uses the 32-bit, ARM-based GCC 4.8 toolchain. You can specify a different value, however, by specifying 
--arch=<toolchain>
 as an option. Table 3
shows the values to use for other toolchains:
Table 3. Toolchains and corresponding values, using 
--arch
.
ToolchainValue
mips64 compiler
--arch=mips64
mips GCC 4.8 compiler
--arch=mips
x86 GCC 4.8 compiler
--arch=x86
x86_64 GCC 4.8 compiler
--arch=x86_64
mips GCC 4.8 compiler
--arch=mips
Alternatively, you can use the 
--toolchain=<toolchain>
 option. Table 4 shows the values you can specify for
<toolchain>
:
Table 4. Toolchains and corresponding values, using 
--toolchain
.
ToolchainValue
arm
--toolchain=arm-linux-androideabi-4.8
--toolchain=arm-linux-androideabi-4.9
--toolchain=arm-linux-android-clang3.5
--toolchain=arm-linux-android-clang3.6
x86
--toolchain=x86-linux-android-4.8
--toolchain=x86-linux-android-4.9
--toolchain=x86-linux-android-clang3.5
--toolchain=x86-linux-android-clang3.6
mips
--toolchain=mips-linux-android-4.8
--toolchain=mips-linux-android-4.9
--toolchain=mips-linux-android-clang3.5
--toolchain=mips-linux-android-clang3.6
arm64
--toolchain=aarch64-linux-android-4.9
--toolchain=aarch64-linux-android-clang3.5
--toolchain=aarch64-linux-android-clang3.6
x86_64
--toolchain=x86_64-linux-android-4.9
--toolchain=x86_64-linux-android-clang3.5
--toolchain=x86_64-linux-android-clang3.6
mips64
--toolchain=mips64el-linux-android-4.9
--toolchain=mips64el-linux-android-clang3.5
--toolchain=mips64el-linux-android-clang3.6
Note: Table 4 is not an exhaustive详细的 list. Other combinations may also be valid有效的, but are unverified为证实.
You can also copy Clang/LLVM 3.6, using one of two methods: You can append 
-clang3.6
 to the 
--toolchain
option, so that the 
--toolchain
 option
looks like the following example:
--toolchain=arm-linux-androideabi-clang3.6

You can also add 
-llvm-version=3.6
 as a separate option on the command line.

Note: Instead of specifying a specific version, you can also use 
<version>
, which defaults to the highest available version of Clang.
By default, the build system builds for a 32-bit host toolchain. You can specify a 64-bit host toolchain instead. Table 5 shows the value to use with 
-system
 for different platforms.
Table 5. Host toolchains and corresponding values, using 
-system
.
Host toolchainValue
64-bit Linux
-system=linux-x86_64
64-bit MacOSX
-system=darwin-x86_64
64-bit Windows
-system=windows-x86_64
For more information on specifying a 64- or 32-bit instruction host toolchain, see 64-Bit
and 32-Bit Toolchains.
You may specify 
--stl=stlport
 to copy 
libstlport
 instead of the default 
libgnustl
. If you do so, and you wish to link against the
shared library, you must explicitly明确 use 
-lstlport_shared
. This requirement is similar to having to use 
-lgnustl_shared
 for GNU 
libstdc++
.
Similarly, you can specify 
--stl=libc++
 to copy the LLVM libc++ headers and libraries. To link against the shared library, you must explicitly use -lc++_shared.
You can make these settings directly, as in the following example:
export PATH=/tmp/my-android-toolchain/bin:$PATH
export CC=arm-linux-androideabi-gcc   # or export CC=clang
export CXX=arm-linux-androideabi-g++  # or export CXX=clang++

Note that if you omit忽略 the 
-install-dir
 option, the 
make-standalone-toolchain.sh
 shell script creates a tarball(原始码,打包工具)in 
tmp/ndk/<toolchain-name>.tar.bz2
.
This tarball makes it easy to archive档案,归档, as well as to redistribute重新分配 the binaries.
This standalone toolchain provides an additional benefit, as well, in that it contains a working copy of a C++ STL library, with working exceptions and RTTI support.
For more options and details, use 
--help
.


Working with Clang

You can install Clang binaries in the standalone installation by using the 
--llvm-version=<version>
 option.
<version>
 is a LLVM/Clang version number, such
as 
3.5
 or 
3.6
. For example:
build/tools/make-standalone-toolchain.sh \
--install-dir=/tmp/mydir \
--toolchain=arm-linux-androideabi-4.8 \
--llvm-version=3.6

Note that Clang binaries are copied along with the GCC ones, because they rely on the same assembler汇编器, linker, headers, libraries, and C++ STL implementation.
This operation also installs two scripts, named 
clang
 and 
clang++
, under 
<install-dir>/bin/@
. These scripts invoke the real 
clang
 binary
with default 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.

Invoking Clang

In an ARM standalone installation built with 
llvm-version=3.6
, invoking Clang on
a Unix system takes the form of a single line. For instance:
`dirname $0`/clang36 -target armv5te-none-linux-androideabi "$@"

clang++
 invokes 
clang++31
 in the same way.

Clang targets with ARM

When building for ARM, Clang changes the target based on the presence of the 
-march=armv7-a
 and/or 
-mthumb
 options:
Table 5. 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.
The 
-gcc-toolchain
 option is unnecessary because, in a standalone package, Clang locates 
as
 and 
ld
 in a predefined预定义的 relative location.

clang
 and 
clang++
 should be easy drop-in replacements替代  for 
gcc
 and 
g++
 in a
makefile. When in doubt, add the following options 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.
For more information about Clang, see http://clang.llvm.org/, especially特别 the GCC compatibility兼容
section.


ABI Compatibility

The machine code that the ARM toolchain generates should be compatible with the official Android 
armeabi
 ABIby
default.
We recommend use of the 
-mthumb
 compiler flag to force the generation of 16-bit Thumb-1 instructions (the default being 32-bit ARM instructions).
If you want to target the armeabi-v7a ABI, you must set the following flags:
CFLAGS= -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16

The first flag enables Thumb-2 instructions指令,说明. The second flag enables hardware-FPU instructions while ensuring that the system passes floating-point parameters in core registers寄存器, which is
critical关键的 for ABI compatibility.

Note: In versions of the NDK prior to r9b, do not use these flags separately. You must set all or none of them. Otherwise, unpredictable不可预知的 behavior and crashes may result.
To use NEON instructions, you must change the 
-mfpu
 compiler flag:
CFLAGS= -march=armv7-a -mfloat-abi=softfp -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:
LDFLAGS= -march=armv7-a -Wl,--fix-cortex-a8

The first flag instructs the linker to pick 
libgcc.a
libgcov.a
, and 
crt*.o
, which are tailored量身定做
for armv7-a. The 2nd flag is required as a workaround工作区  for a CPU bug in some Cortex-A8 implementations.
Since NDK version r9b, all Android native APIs taking or returning double or float values have
attribute((pcs("aapcs")))
 for ARM. This makes it possible to compile user code
in 
-mhard-float
 (which implies 
-mfloat-abi=hard
), and still link with the Android native APIs that comply with the softfp ABI. For more information on this, see the comments in 
$NDK/tests/device/hard-float/jni/Android.mk
.
If you want to use NEON intrinsics函数 on x86, the build system can translate them to the native x86 SSE intrinsics函数 using a special C/C++
language header with the same name, 
arm_neon.h
, as the standard ARM NEON intrinsics header.
By default, the x86 ABI supports SIMD up to SSSE3, and the header covers ~93% of (1869 of 2009) NEON functions.
You don't have to use any specific compiler flag when targeting the MIPS ABI.
To learn more about ABI support, see x86 Support.


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
.
The NDK build system ensures that all paths passed to the compiler from Cygwin are automatically translated, and manages other complexities复杂性, as well. If you have a custom build system, you may
need to resolve解决 these complexities yourself.
For information on contributing to support for Cygwin/MSys, visit the android-ndk forum.

wchar_t support

The Android platform did not really support 
wchar_t
 until Android 2.3 (API level 9). This fact has several ramifications分支:
If you target platform Android 2.3 or higher, the size of 
wchar_t
 is 4 bytes, and most 
wide-char
 functions are available in the C library (with the exception of multi-byte encoding/decoding
functions and
wsprintf
/
wsscanf
).
If you target any lower API level, the size of 
wchar_t
 is 1 byte, and none of the wide-char functions works.
We recommend that you get rid of any dependencies on the 
wchar_t
 type, and switch to better representations. The support provided in Android is only there to help you migrate移植
existing code.

Exceptions, RTTI运行时类型识别(Run Time Type Identification), and STL标准模板库(Standard Template Library)

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
.
To use these features in conjunction结合 with GNU libstdc++, you must explicitly明确 link with libsupc++. To do so, use 
-lsupc++
 when linking binaries. For example:
arm-linux-androideabi-g++ .... -lsupc++

You do not need to do this when using the STLport or libc++ library.

C++ STL support

The standalone toolchain includes a copy of a C++ Standard Template Library implementation. This implementation is either for GNU libstdc++, STLport, or libc++, depending on what you specify for
the 
--stl=<name>
 option described previously. To use this implementation of STL, you need to link your project with the proper library:
Use 
-lstdc++
 to link against the static library version of any implementation. 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.

This is the method that we recommend.

Alternatively, use 
-lgnustl_shared
 to link against链接对 the shared library version of GNU 
libstdc++
. If you use this option, you must also make sure to copy 
libgnustl_shared.so
 to
your device in order for your code to load properly. Table 6 shows where this file is for each toolchain type.

Note: GNU libstdc++ is licensed许可 under the GPLv3 license许可证, with a linking exception. If you cannot comply遵守 with its requirements, you cannot redistribute重发布 the shared library in your project.

Use 
-lstlport_shared
 to link against the shared library version of STLport. When you do so, you need to make sure that you also copy 
libstlport_shared.so
 to your device in order for
your code to load properly. Table 6 shows where this file is for each toolchain:
Table 6. Specifiable 
-march
 values and their resulting targets.
ToolchainLocation
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/
mips
$TOOLCHAIN/mipsel-linux-android/lib/
mips64
$TOOLCHAIN/mips64el-linux-android/lib/
Note: If your project contains multiple shared libraries or executables, you must link against a shared-library STL implementation. Otherwise, the build system does not define certain global uniquely, which can result in unpredictable不可预知的
runtime behavior. This behavior may include crashes and failure to properly catch exceptions.
The reason the shared version of the libraries is not simply called 
libstdc++.so
 is that this name would conflict冲突 at runtime with the system's own minimal C++ runtime. For this reason, the
build system enforces a new name for the GNU ELF library. The static library does not have this problem.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ndk