USING THE ANDROID TOOLCHAIN AS A STANDALONE COMPILER
使用ANDROID作為一個獨立的編譯器工具鏈
======================================================
It is now possible to use the toolchains provided with the Android NDK as
standalone compilers. This can be useful if you already have your own build
system, and only need to ability to invoke the cross-compiler to add support
to Android for it.
現在可以使用Android NDK 作為獨立編譯器。如果你擁有自己的編譯系統這會很有用
,僅僅需要有調用支持Android交叉編譯器的能力。
A typical use case if invoking the 'configure' script of an open-source
library that expects a cross-compiler in the CC environment variable.
一個典型用例,如果調用需要交叉編譯器調用開源庫'configure'腳本(預設CC環境變量)。
This document explains how to do that:
該文檔解釋了如何做:
1/ Selecting your toolchain:
選擇你的工具鏈:
----------------------------
Before anything else, you need to decide whether your standalone toolchain
is going to target ARM-based devices, x86-based, or MIPS-based one.
Each architecture corresponds to a different toolchain name. For example:
做任何東西之前,你需要決定你的獨立的工具鏈是基於arm的設備,基於x86的,或基於mips的哪一個。
每個架構對應一個不同的工具鏈的名字。例如:
* arm-linux-androideabi-4.6 => targeting ARM-based Android devices
* x86-4.6 => targeting x86-based Android devices
* mipsel-linux-android-4.6 => targeting MIPS-based Android devices
2/ Selecting your sysroot:
選擇目錄切換為sysroot:
--------------------------
The second thing you need to know is which Android native API level you want
to target. Each one of them provides a different various APIs, which are
documented under doc/STABLE-APIS.html, and correspond to the sub-directories
of $NDK/platforms.
第二件事你需要知道的是,你需要知道安卓原生API的級別。每一個都提供了一個不同的各種api,
這是記錄在doc/STABLE-APIS.html和對應 $NDK/platforms的子目錄中
This allows you to define the path to your 'sysroot', a GCC term for a
directory containing the system headers and libraries of your target.
Usually, this will be something like:
定義'sysroot'包含目標系統頭文件和庫。通常,如下:
SYSROOT=$NDK/platforms/android-<level>/arch-<arch>/
Where <level> is the API level number, and <arch> is the architecture
("arm", "x86", and "mips" are the supported values). For example, if you're
targeting Android 2.2 (a.k.a. Froyo), you would use:
<level>是API 級別 號,<arch>是架構(支持arm,x86,mips)。
例如:如果目標android是2.2,如下:
SYSROOT=$NDK/platforms/android-8/arch-arm
IMPORTANT: Note that X86 and MIPS architectures are only supported at android-9 and later.
重要:注意X86和MIPS架構只在android-9或更新支持。
3/ Invoking the compiler (the hard way):
調用編譯器(最困難一步)
----------------------------------------
Invoke the compiler using the --sysroot option to indicate where the system
files for the platform you're targeting are located. For example, do:
使用--sysroot選項來指出系統文件位置在哪。例如:
export CC="$NDK/toolchains/<name>/prebuilt/<system>/bin/<prefix>gcc --sysroot=$SYSROOT"
$CC -o foo.o -c foo.c
Where <name> is the toolchain's name, <system> is the host tag for your system,
and <prefix> is a toolchain-specific prefix. For example, if you are on Linux
using the NDK r5 toolchain, you would use:
<name>是工具鏈的名字,<system>是系統主機標志,<prefix>是工具鏈特定前綴,例如在linux下使用NDK r5工具鏈,如下:
export CC="$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT"
As you can see, this is rather verbose, but it works!
可見,這是很繁瑣,但是有效!
IMPORTANT NOTE:
重要事項:
Using the NDK toolchain directly has a serious limitation:
You won't be able to use any C++ STL (either STLport or
the GNU libstdc++) with it. Also no exceptions and no RTTI.
直接使用NDK的工具鏈(非獨立版工具鏈)有嚴重的限制:
你不能使用任何C++ STL(STLport或GNU libstdc++)。也沒有異常和運行時類型檢查。
4/ Invoking the compiler (the easy way):
調用編譯器(最簡單一步):
----------------------------------------
The NDK allows you to create a "customized" toolchain installation to make
life easier. For example, consider the following command:
NDK允許您創建一個“定制”工具鏈安裝。例如,參考下面的命令:
$NDK/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain
This will create a directory named /tmp/my-android-toolchain containing a
copy of the android-5/arch-arm sysroot, and of the toolchain binaries.
這將建立一個路徑/tmp/my-android-toolchain,包含復制的 android-5/arch-arm sysroot 工具鏈 文件。
Note that by default, the ARM-based GCC 4.6 toolchain will be selected by the script.
Use the '--arch=x86' option to specify the x86 GCC 4.6, or add '--arch=mips' option
to specify the MIPS GCC 4.6, or alternatively
'--toolchain=<name>'. For example:
注意默認使用ARM GCC 4.6 工具鏈。使用'--arch=x86'設定x86 GCC 4.6,
或'--arch=mips'設定MIPS GCC 4.6,或者'--toolchain=<name>'來設。例如
--toolchain=x86-4.4.3 # select x86 GCC 4.4.3 compiler
--toolchain=arm-linux-androideabi-4.7 # select ARM GCC 4.7 compiler
--toolchain=mipsel-linux-android-4.6 # select MIPS GCC 4.6 compiler, same as --arch=mips
If you wish, add '--llvm-version=3.1' to also copy clang/llvm 3.1, or
use --toolchain with '-clang3.1' suffix. For example:
'--llvm-version=3.1'可以復制clang/llvm 3.1或使用--toolchain with '-clang3.1'後綴,例如:
--toolchain=arm-linux-androideabi-clang3.1 # same as --arch=arm --llvm-version=3.1
You can later use it directly with something like:
稍後可用類似如下(導入環境變量):
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 without the --install-dir option, make-standalone-toolchain.sh will
create a tarball in /tmp/ndk/<toolchain-name>.tar.bz2. This allows you to
archive and redistribute the binaries easily.
注意未使用--install-dir,make-standalone-toolchain.sh會打包在/tmp/ndk/<toolchain-name>.tar.bz2。
使你可以很容易重新發布文件。
Another important benefit is that this standalone toolchain will contain a
working copy of the GNU libstdc++, with working exceptions and RTTI support
(as long as you link against libstdc++ or libsupc++)
另一個很便利的地方:獨立工具鏈包含GNU libstdc++(支持異常和RTTI機制),只要你鏈接到它。
Use --help for more options and details.
--help查看更多選項和信息。
IMPORTANT: The toolchain binaries do not depend or contain host-specific paths,
in other words, they can be installed in any location, or even
moved if you need to.
重要:工具鏈的二進制文件不依賴或包含特定於主機的路徑,
換句話說,他們可以安裝在任何位置,甚至如果你需要移動。
NOTE: You can still use the --sysroot option with the new toolchain, but it
is now simply optional!
注意:你仍然可以使用--sysroot選項在新的工具鏈,但它現在只是可選的!
5/ About Clang
關於Clang
---------------------
Clang/clang++ uses the same assembler, linker, headers, libraries and GNU
libstdc++ in the same standalone package. Clang/clang++ are actually scripts
with "-target" set to the specified architecture at creation. For example, in
ARM standalone package, clang is a one-liner:
Clang/clang++使用同樣的編譯器,鏈接器,頭文件,庫文件和GNU libstdc++在獨立的包中。
Clang/clang++是個腳本,創建時使用-target指定到特定架構。
例如:在ARM獨立包,clang是個單行:
`dirname $0`/clang31 -target armv5te-none-linux-androideabi "$@"
clang++ is another:
clang++是另一行:
`dirname $0`/clang++31 -target armv5te-none-linux-androideabi "$@"
Note that for arm, clang will change target based on the presence of
subsequent option "-march=armv7-a" and/or "-mthumb". ie.
注意arm,使用-march=armv7-a -mthumb clang將改變-target
1/ With "-march=armv7-a", -target becomes armv7-none-linux-androideabi
2/ With "-mthumb", -target becomes thumb-none-linux-androideabi
3/ With both, -target becomes thumbv7-none-linux-androideabi
You may override with your own -target if you wish.
你可以重寫-target。
Extra efforts have been made to make clang/clang++ easier drop-in
replacements for gcc/g++ in Makefile. When in doubt, use the following
common techniques to check:
做額外的工作替換gcc/g++在Makefile裡。懷疑時,使用下面檢查:
1/ Add option "-v" to dump commands compiler driver issues
-v打印命令編譯器驅動問題
2/ Add option "-###" to dump command line options, including those
implicitly predefined.
-### 打印選項命令行,包含隱式預定義的
3/ Use "-x c /dev/null -dM -E" to dump predefined preprocessor definitions
- x c /dev/null -dM -E 打印預定義的預處理器定義
4/ Add option "-save-temps" and compare the preprocessed files *.i or *.ii
-save-temps比較預處理文件 *.i *.ii
See http://clang.llvm.org/, especially the GCC compatibility section.
6/ ABI Compatibility:
應用二進制接口兼容性:
---------------------
The machine code generated by the ARM toolchain should be compatible with
the official Android 'armeabi' ABI (see docs/CPU-ARCH-ABIS.html) by default.
ARM工具鏈生成的代碼應該默認兼容官方Android 'armeabi'的應用二進制接口(參照/CPU-ARCH-ABIS.html)
It is recommended to use the -mthumb compiler flag to force the generation
of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones).
推薦使用-mthumb 編譯器標識來強制生成16位Thumb-1指令(默認是32位ARM的指令)
If you want to target the 'armeabi-v7a' ABI, you will need ensure that the
following flags are being used:
如果你的目標是'armeabi-v7a'的應用二進制接口,你需要確保使用如下標志:
CFLAGS='-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16'
Note: The first flag enables Thumb-2 instructions, and the second one
enables H/W FPU instructions while ensuring that floating-point
parameters are passed in core registers, which is critical for
ABI compatibility. Do *not* use these flags separately!
注意:第一個標志啟用Thumb-2指令,第二個啟用H/W浮點處理器指令功能,
確保用核心寄存器傳遞浮點參數,它對於ABI兼容性來說是關鍵。不要分開使用這些開關!
If you want to use Neon instructions, you will need to change the -mfpu
compiler flag:
如果你想使用Neon指令(ARM的單指令多數據技術),你需要再增多一個編譯器開關:
CFLAGS='-march=armv7-a -mfloat-abi=softfp -mfpu=neon'
Note that this forces the use of VFPv3-D32, as per the ARM specification.
注意它強制使用VFPv3-D32(注:VFPv3是vector floating point v3的縮寫,
即向量浮點第三版,D32應該是指32個雙精度浮點寄存器),根據ARM規范。
Also, make sure the following two flags are provided to linker:
還有,確保下鏈接器使用以下兩個標志。
LDFLAGS='-march=armv7-a -Wl,--fix-cortex-a8'
Note: The first flag instructs linker to pick libgcc.a, libgcov.a and
crt*.o tailored for armv7-a. The 2nd flag is *required* to route
around a CPU bug in some Cortex-A8 implementations:
注意:第一個標志連接器選擇特別為armv7-a設計的libgcc.a libgcov.a和crt*.o。
第二個標志是繞過一些Cortex-A8 CPU bug的實現所需。
If none of the above makes sense to you, it's probably better not to use
the standalone toolchain, and stick to the NDK build system instead, which
will handle all the details for you.
如果上面的東西對你不起作用,最好不要使用獨立工具鏈,還是堅持使用NDK構建系統,
它將為你處理所有細節。
You don't have to use any specific compiler flag when targeting the x86 ABI
or the MIPS ABI.
當目標是x86 ABI或MIPS ABI時,你不需要使用人任何特殊編譯器標志。
7/ Warnings and Limitations:
警告和限制:
--------------------------
7.1/ Windows support:
Windows支持:
- - - - - - - - - - -
The Windows binaries do *not* depend on Cygwin. The good news is that they
are thus faster, the bad news is that they do not understand the Cygwin
path specification like /cygdrive/c/foo/bar (instead of C:/foo/bar).
Windows二進制文件不依賴於Cygwin。好消息是它們會跑得更快,
而壞消息是它們不理解Cygwin的目錄格式,像/cygdrive/c/foo/bar(但可以理解C:/foo/bar)
The NDK build system ensures that all paths passed to the compiler from Cygwin
are automatically translated, and deals with other horrors for you. If you have
a custom build system, you may need to deal with the problem yourself.
NDK構建系統確保從Cygwin中傳遞的所有路徑被自動翻譯,為你處理其它威脅。
如果你擁有一個定制構建系統,你可能需要自己處理問題。
NOTE: There is no plan to support Cygwin / MSys at the moment, but
contributions are welcome. Contact the android-ndk forum for details.
注意:現在沒計劃支持Cygwin / MSys,但歡迎貢獻。詳細請聯系android-ndk論壇
7.2/ wchar_t support:
wchar_t支持:
- - - - - - - - - - -
As documented, the Android platform did not really support wchar_t until
Android 2.3. What this means in practical terms is that:
正如文檔所寫的,Android平台在Android 2.3之前沒有真正支持wchar_t。
用實際的術語說,這意味著:
- If you target platform android-9 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).
- 如果你的目標平台是android-9或更高,wchar_t的大小是4字節,則在C庫中大多數
寬字符函數可用(例外的是多字節的編碼解碼函數和wsprintf/wsscanf)
- If you target any prior API level, the size of wchar_t will be 1 byte
and none of the wide-char functions will work anyway.
- 如果你的目標是較早的API級別,wchar_t的大小將是1字節,任何寬字符函數都不可工作。
We recommend any developer to 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.
我們建議所有開發者避免對wchar_t類型的依賴,而是轉向更好的表示。
在Android中提供的支持只出現在幫助你遷移現存代碼的地方。
7.3/ Exceptions, RTTI and STL:
異常、運行時類型識別和STL(標准模板庫):
- - - - - - - - - - - - - - -
The toolchain binaries *do* support C++ exceptions and RTTI by default.
They are enabled by default, so use -fno-exceptions and -fno-rtti if you
want to disable them when building sources with them (e.g. to generate
smaller machine code).
工具鏈二進制文件默認支持C++異常和RTTI(運行時類型識別)。
它們默認是打開的,所以如果你想在構建使用它們的代碼時關閉它們,
請使用-fno-exceptions和-fno-rtti(例如,為了生成更小的機器代碼)。
NOTE: You will need to explicitly link with libsupc++ if you use these
features. To do this, use -lsupc++ when linking binaries, as in:
注意:你將需要顯式地用libsupc++鏈接,如果你使用這些特性。
為了做到這點,當鏈接二進制文件時使用-lsupc++,
像這樣:(注:這裡要小心,是libsupc++不是libstdc++!)
arm-linux-androideabi-g++ .... -lsupc++
7.4/ C++ STL support:
C++標准模板庫支持:
- - - - - - - - - - -
The standalone toolchain also comes with a copy of the GNU libstdc++
library, which provides an implementation of the C++ Standard Template
Library. To use it, you however need to link with the proper library:
工具鏈還帶有一個可用的GNU libstdc++實現,它提供一個工作的C++標准模板庫實現。
你將需要顯式地用-lstdc++鏈接以使用它。
* Use -lstdc++ to link against the _static_ library version. This ensures
that all required C++ STL code is included into your final binary. This
is ideal if you are only generating a single shared library or executable.
使用-lstdc++ 來鏈接靜態庫版本。這確保了所需C++STL代碼包含進你的最終二進制文件。
這是一個生成單獨共享庫或執行文件的辦法。
This is the recommended way to do it.
這是推薦的方式。
* Use -lgnustl_shared to link against the _shared_ library version. This
is required if you have several related shared libraries or executables
that need to run in the same address space at runtime (some global variables
need to be defined uniquely, which is not possible if you link the static
libstdc++ against each one of your executables).
使用-lgnustl_shared來鏈接靜態庫版本。如果你有幾個相關的需要運行時在同樣的地址空間
的共享庫或執行文件,這是必須的。
(一些全局變量需要唯一的定義,不適用於每一個可執行文件鏈接靜態的libstdc++)
If you use this option, you need to ensure that libgnustl_shared.so is
also copied to your device for your code to load properly. The file is
at:
如果你使用此選項,你需要確保libgnustl_shared.so拷貝到你設備上以便載入。文件在:
$TOOLCHAIN/arm-linux-androideabi/lib/ for ARM toolchains.
$TOOLCHAIN/i686-linux-android/lib/ for x86 ones.
$TOOLCHAIN/mipsel-linux-android/lib/ for MIPS toolchains.
IMPORTANT: The GNU libstdc++ is licensed under the GPLv3 with a
linking exception. See the following URL for details:
重要:GNU libstdc++ 授權在GPLv3,有一個例外,查看如下URL來詳細描述:
http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01s02.html
If you cannot comply with its requirements, i.e. you cannot redistribute
the shared library, do not use it in your project. www.2cto.com
如果你不能干遵守它的要求,你不能發布這個共享庫,不能使用在你的工程中。
The reason the shared version of GNU libstdc++ is not called libstdc++.so is
because this would conflict at runtime with the system's own minimal C++
runtime, which is /system/lib/libstdc++.so. This enforces a new name for the
GNU ELF library. This is not a problem for the static library.
共享版GNU libstdc++不被叫做libstdc++.so的原因是這將會在運行時和最小C++運行時庫
(/system/lib/libstdc++.so)沖突。這強制了一個GNU ELF庫的新名字。對於靜態庫這不是個問題。