#android-ndk-r8d 使用 独立 编译 工具链 官方文档 中文版

使用ANDROID作为一个独立的编译器工具链
======================================================

该文档解释了如何做:

1/选择你的工具链:
----------------------------

做任何东西之前,你需要决定是否你的独立的工具链是基于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/选择目录切换为sysroot:
--------------------------
第二件事你需要知道的是,你需要知道安卓原生API的级别。每一个都提供了一个不同的各种api,
这是记录在doc/STABLE-APIS.html和对应 $NDK/platforms的子目录中

定义'sysroot'包含目标系统头文件和库。通常,如下:
   SYSROOT=$NDK/platforms/android-<level>/arch-<arch>/

<level>是API 级别 号,<arch>是架构(支持arm,x86,mips)。
例如:如果目标android是2.2,如下:
   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工具链,如下:
    export CC="$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT"

可见,这是很繁琐,但是有效!

重要事项:
    直接使用NDK的工具链(非独立版工具链)有严重的限制:
    你不能使用任何C++ STL(STLport或GNU libstdc++)。也没有异常和运行时类型检查。

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-arm sysroot 工具链 文件。

注意默认使用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

 '--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

稍后可用类似如下(导入环境变量):

   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++

注意未使用--install-dir,make-standalone-toolchain.sh会打包在/tmp/ndk/<toolchain-name>.tar.bz2。
使你可以很容易重新发布文件。

另一个很便利的地方:独立工具链包含GNU libstdc++(支持异常和RTTI机制),只要你链接到它。

--help查看更多选项和信息。

重要:工具链的二进制文件不依赖或包含特定于主机的路径,
   换句话说,他们可以安装在任何位置,甚至如果你需要移动。
 
注意:你仍然可以使用--sysroot选项在新的工具链,但它现在只是可选的!

5/关于Clang
---------------------

Clang/clang++使用同样的编译器,链接器,头文件,库文件和GNU libstdc++在独立的包中。
Clang/clang++是个脚本,创建时使用-target指定到特定架构。
例如:在ARM独立包,clang是个单行:

   `dirname $0`/clang31 -target armv5te-none-linux-androideabi "$@"

clang++是另一行:

   `dirname $0`/clang++31 -target armv5te-none-linux-androideabi "$@"

注意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

你可以重写-target。

做额外的工作替换gcc/g++在Makefile里。怀疑时,使用下面检查:
  1/ Add option "-v" to dump commands compiler driver issues
  打印命令编译器驱动问题
  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
  打印预定义的预处理器定义
  4/ Add option "-save-temps" and compare the preprocessed files *.i or *.ii
  比较预处理文件

See http://clang.llvm.org/, especially the GCC compatibility section.


6/应用二进制接口兼容性:
---------------------

ARM工具链生成的代码应该默认兼容官方Android 'armeabi'的应用二进制接口(参照/CPU-ARCH-ABIS.html)

推荐使用-mthumb 编译器标识来强制生成16位Thumb-1指令(默认是32位ARM的指令)

如果你的目标是'armeabi-v7a'的应用二进制接口,你需要确保使用如下标志:

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

注意:第一个标志启用Thumb-2指令,第二个启用H/W浮点处理器指令功能,
确保用核心寄存器传递浮点参数,它对于ABI兼容性来说是关键。不要分开使用这些开关!

如果你想使用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'

注意:第一个标志连接器选择特别为armv7-a设计的libgcc.a libgcov.a和crt*.o。
      第二个标志是绕过一些Cortex-A8 CPU bug的实现所需。

如果上面的东西对你不起作用,最好不要使用独立工具链,还是坚持使用NDK构建系统,
它将为你处理所有细节。

当目标是x86 ABI或MIPS ABI时,你不需要使用人任何特殊编译器标志。

7/ 警告和限制:
--------------------------

7.1/Windows支持:
- - - - - - - - - - -

Windows二进制文件不依赖于Cygwin。好消息是它们会跑得更快,
而坏消息是它们不理解Cygwin的目录格式,像/cygdrive/c/foo/bar(但可以理解C:/foo/bar)

NDK构建系统确保从Cygwin中传递的所有路径被自动翻译,为你处理其它威胁。
如果你拥有一个定制构建系统,你可能需要自己处理问题。

注意:现在没计划支持Cygwin / MSys,但欢迎贡献。详细请联系android-ndk论坛

7.2/wchar_t支持:
- - - - - - - - - - -

正如文档所写的,Android平台在Android 2.3之前没有真正支持wchar_t。
用实际的术语说,这意味着:

  - 如果你的目标平台是android-9或更高,wchar_t的大小是4字节,则在C库中大多数
    宽字符函数可用(例外的是多字节的编码解码函数和wsprintf/wsscanf)

  - 如果你的目标是较早的API级别,wchar_t的大小将是1字节,任何宽字符函数都不可工作。

我们建议所有开发者避免对wchar_t类型的依赖,而是转向更好的表示。
在Android中提供的支持只出现在帮助你迁移现存代码的地方。

7.3/ 异常、运行时类型识别和STL(标准模板库):
- - - - - - - - - - - - - - -

工具链二进制文件默认支持C++异常和RTTI(运行时类型识别)。
它们默认是打开的,所以如果你想在构建使用它们的代码时关闭它们,
请使用-fno-exceptions和-fno-rtti(例如,为了生成更小的机器代码)。

注意:你将需要显式地用libsupc++链接,如果你使用这些特性。
为了做到这点,当链接二进制文件时使用-lsupc++,
像这样:(注:这里要小心,是libsupc++不是libstdc++!)

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


7.4/ C++ STL 支持:
- - - - - - - - - - -
工具链还带有一个可用的GNU libstdc++实现,它提供一个工作的C++标准模板库实现。
你将需要显式地用-lstdc++链接以使用它。

  * 使用-lstdc++ 来链接静态库版本。这确保了所需C++STL代码包含进你的最终二进制文件。
    这是一个生成单独共享库或执行文件的办法。
    This is the recommended way to do it.
    这是推荐的方式。

  * 使用-lgnustl_shared来链接静态库版本。如果你有几个相关的需要运行时在同样的地址空间
    的共享库或执行文件,这是必须的。
   (一些全局变量需要唯一的定义,不适用于每一个可执行文件链接静态的libstdc++)

    如果你使用此选项,你需要确保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++ 授权在GPLv3,有一个例外,查看如下URL来详细描述:
    http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01s02.html

    如果你不能干遵守它的要求,你不能发布这个共享库,不能使用在你的工程中。

共享版GNU libstdc++不被叫做libstdc++.so的原因是这将会在运行时和最小C++运行时库
(/system/lib/libstdc++.so)冲突。这强制了一个GNU ELF库的新名字。对于静态库这不是个问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值