现在已经可以把Android NDK提供的工具链以独立编译器的方式使用了!如果你已经有了自己的构建系统,这就很有用了。

一个典型的应用场景是调用一个依赖于CC环境变量开源库的'configure'脚本进行跨平台编译。

本文档将解释如何那样做。

1 选择你的工具链:

首先 ,你需要确定你的独立工具链所面向的目标CPU加构,是ARM-based设备、x86-based设备,还是MIPS-based设备。每个架构对应不同的工具链名字:

* arm-linux-androideabi-4.6 => 面向ARM-based Android设备

* x86-4.6 => 面向x86-based Android设备

* mipsel-linux-android-4.6 => 面向MIPS-based Android设备

2 选择你的sysroot:

你应该了解的第二项事情是你想面向那一级Android nativeAPI 。每一级都提供了不同的API,它们被文档doc/STABLE-APIS.html所描述,并对应于$NDK/platforms的子文件夹。这使得你可以定义指向你的'sysroot'的路径 ,GCC路径下包含系统头文件和库。通常看起来像这样:

SYSROOT=$NDK/platforms/android-<level>/arch-<arch>/

<level> 是API level 数,<arch> 是体系结构("arm", "x86", 和"mips" 都可以作为值)。例如,如果你面向 Android2.2 (a.k.a. Froyo),你应使用:

SYSROOT=$NDK/platforms/android-8/arch-arm

注意:X86 和MIPS体系仅在android-9才开始支持。

3调用编译器(笨办法):

使用--sysroot选项调用编译器,以表明你所面向的平台的系统文件的路径。例如:

export CC="$NDK/toolchains/<name>/prebuilt/<system>/bin/<prefix>gcc--sysroot=$SYSROOT"

$CC -o foo.o -c foo.c

<name> 是工具链的名字,<system> 是宿主系统,<prefix> 是特定工具链的前缀。例如,如果你在Linux上使用NDK r5 工具链,你将使用:

exportCC="$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc--sysroot=$SYSROOT"

就像你看到的,这很啰嗦,但的确能工作!

注意:

直接使用NDK 工具链具有很多限制:

你不能使用任何C++ STL (无论是STLport 或GNU libstdc++) 。也不能使用异常和RTTI。

4调用编译器(容易的办法):

NDK 允许你创建一个"自定义的" 工具链并安装以使生活更简单。例如,下面的命令:

$NDK/build/tools/make-standalone-toolchain.sh --platform=android-5--install-dir=/tmp/my-android-toolchain

这将创建一个文件夹,名为 /tmp/my-android-toolchain,包含一个android-5/arch-armsysroot的考贝和工具链的执行文件。

注意,默认下,ARM-based GCC 4.6 工具链将被脚本所选择。使用'--arch=x86' 来指定x86-based 的GCC,使用'--arch=mips' 来指定MIPS-based 的GCC,或使用

'--toolchain=<name>'来指定。例如:

--toolchain=x86-4.4.3 # select x86 GCC 4.4.3 compiler

--toolchain=mipsel-linux-android-4.6# select MIPS GCC 4.6compiler, same as --arch=mips

如果你想,可以通过添加 --llvm-version=3.1 来把clang/llvm3.1也考贝过去。你可以在之后直接使用它。就像:

exportPATH=/tmp/my-android-toolchain/bin:$PATH

exportCC=arm-linux-androideabi-gcc # or export CC=clang

exportCXX=arm-linux-androideabi-g++ # or export CXX=clang++

注意,不使用 --install-dir 选项,make-standalone-toolchain.sh将创建一个名为/tmp/ndk/<toolchain-name>.tar.bz2的tarball。这使你可以很容易的存储并重新发布二进制工具包。

另一个重要的好处是这个独立的工具链将包含一个GNU libstdc++的考贝,它能支持异常和RTTI (当你链接到libstdc++ 或 libsupc++)。

重点:工具链执行文件不依赖于或包含宿主上的特点路径,换句话说,它们可以被安装于任何位置,或移动到另外位置。

注意:你依然可以对新的工具链使用—sysroot选项,但是现在变简单了!

5 ABI 兼容性:

通过ARM 工具链产生的机器码应该与官方的Android 'armeabi' ABI兼容。推荐使用-mthumb 编译标志来强制产生16位Thumb-1指令 (默认是32-bit 的)。

如果你想面向'armeabi-v7a' ABI,你应该确保下面的标志被使用:

CFLAGS='-march=armv7-a-mfloat-abi=softfp -mfpu=vfpv3-d16'

注:第一个标志启用Thumb-2指令,第二个启用H/W FPU指令同时确保浮点参数被传入核心寄存器,这是ABI兼容的关键。*不要*分开使用这些标志!

如果你想使用Neon指令,你需要改变-mfpu编译标志:

CFLAGS='-march=armv7-a-mfloat-abi=softfp -mfpu=neon'

注意这会强制使用VFPv3-D32。

还要确保下面两个标志也提供给链接器:

LDFLAGS='-march=armv7-a-Wl,--fix-cortex-a8'

注:第一个标志指示链接器为armv7-a选择合适的libgcc.a、libgcov.a和crt*.o。第二个标志用于在某些Cortex-A8装置中绕过一个CPU bug。

如果上面这些还不能满足你,那么你最好不要用独立的工具链了,而是坚守NDK构建系统,它将为你处理所有细节。

当你面向x86 ABI 或MIPS ABI时你不需要使用任何特定的编译器标志。

6 警告和限制:


Windows support:

Windows下的二进制文件*不*依赖于Cygwin。好消息是它们因此会运行快,坏消息是它们不明白Cygwin的路径形式,比如/cygdrive/c/foo/bar (而不是 C:/foo/bar)。

NDK构建系统保证所有从Cygwin传给编译器的路径都被自动转换,并且为你应付那些难搞的事情。如果有一个自定义构建系统,你需要自己应付所有的问题。

注:当前没有支持Cygwin / MSys的计划。

wchar_t 支持:

在Android 2.3之前,Android平台并不真的支持wchar_t。这表示:

l 如果你面向android-9 或更高平台,wchar_t的大小是4bytes,并且大多数C库中的宽字节函数都可用(例外是多字节编解码函数和wsprintf/wsscanf函数)。

l 如果你面向任何更低的API level,wchar_t 只有一个字节并且任何宽字节函数都 不能用。

我们建议所有开发者都移除对wchar_t的任何依赖,并且转换到更好的方式。Android所提供的支持仅仅是为了帮助整合已存在的代码。

异常、RTTI和STL:

工具链执行文件默入是支持C++异常和RTTI的。所以当你不需要时,使用-fno-exceptions和-fno-rtti来禁止它们 (产生更少的机器码)。

注:如果你想使用这些特性,你将需要明确的链接到libsupc++。要这样做,在要在链接成二进制文件时使用-lsupc++ :

arm-linux-androideabi-g++ .... -lsupc++

C++ STL 支持:

独立工具链也带有一个GNU libstdc++ 库的考贝,它提供了C++标准模版库的一个实现。要使用它,你还需要链接到正确的库:

l 使用-lstdc++ 来链接静态库版。这保证了所有需要的C++ STL代码都包含到了你的最终文件中。这是推荐的方式。

l 使用-lgnustl_shared 来链接动态库版。如果你使用此方式,你需要确保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.

动态库版的GNU libstdc++不叫libstdc++.so的原因是这将导致在运行时与系统自己的最小C++运行时(/system/lib/libstdc++.so)冲突。这对静态库就没影响了。

更多相关文章

  1. Python3原生编写月份计算工具
  2. 一款常用的 Squid 日志分析工具
  3. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. [Android]BootChart在Android中的应用
  6. [置顶] 自己开发的Android(安卓)软件发布贴(11月6日)
  7. Android(安卓)Studio构建工具Gradle构建原理
  8. Android(安卓)-- Init进程对信号的处理流程
  9. [置顶] Android调试工具之adbs

随机推荐

  1. ImageView
  2. 书籍
  3. Hack Android(安卓)SD Card support
  4. Android(安卓)tips tool 发现的性能问题
  5. android生命周期onstop不一定会执行
  6. android 图片合成
  7. Android之SharedPreferences权限
  8. Android(安卓)APIDemo gif图片显示
  9. Android加载html实现文件上传功能
  10. Android之Spinner用法