Android NDK开发详解之被弃用的独立工具链

您可以单独使用 Android NDK 附带的工具链,也可以将其作为插件与现有 IDE 结合使用。如果您已拥有自己的构建系统,并且只需要能够调用交叉编译器以便为其添加对 Android 的支持,这种灵活性就会非常有意义。
警告:如果您使用的是 r19 或更高版本,请参阅将 NDK 与其他构建系统配合使用文档,了解有关如何将 NDK 工具链与任意构建系统结合使用的说明。对于 r19 之前的版本,NDK 的默认工具链都是独立工具链,因此无需执行此流程。
注意:此类信息假定您已熟悉如何编译和链接原生代码。如果您是自己编写代码,则无需使用独立工具链;在这类用例中,您应利用 NDK 支持的现有构建系统。如果要构建开源库(例如调用 configure 脚本时),应考虑使用独立的工具链。请参见下文提供的可用示例。

选择您的工具链

首先,您需要确定自己的独立工具链的目标处理器架构。您可以借助 --arch 标志来完成该步骤。

选择您的 sysroot

接下来,您需要定义自己的 sysroot。sysroot 是包含您的目标系统头文件及库的目录。若要定义 sysroot,您必须知道原生支持的目标 Android API 级别;而可用的原生 API 会因 Android API 级别而异。

针对相应 Android API 级别的原生 API 库位于 $NDK/platforms/ 下;每个 API 级别目录又包含针对各种 CPU 和架构的子目录。标头位于 $NDK/sysroot。

如需详细了解 Android API 级别及其支持的对应原生 API,请参阅原生 API。

创建工具链

NDK 提供 make_standalone_toolchain.py 脚本,以便您通过命令行执行自定义工具链安装。

这是用来替代旧式 make-standalone-toolchain.sh 的新工具。此工具已在 Python 中重新实现,因此 Windows 用户无需安装 Cygwin 或 MSYS 即可运行此工具。

脚本位于 $NDK/build/tools/ 目录中,其中 $NDK 是 NDK 的安装根目录。

下面展示了使用此脚本的示例:

$NDK/build/tools/make_standalone_toolchain.py \
    --arch arm --api 21 --install-dir /tmp/my-android-toolchain

此命令创建一个名为 /tmp/my-android-toolchain/ 的目录,其中包含 android-21/arch-arm sysroot 的副本,以及适用于 32 位 ARM 目标的工具链二进制文件的副本。

请注意,工具链二进制文件不依赖或包含主机专属路径。换言之,您可以将其安装在任意位置,甚至可以视需要改变其位置。

–arch 参数是必填项,但 API 级别将默认设为指定架构支持的最低级别(目前,级别 16 适用于 32 位架构,级别 21 适用于 64 位架构)。

自 r18 开始,所有独立工具链都使用 Clang 和 libc++。除非构建静态可执行文件,否则将默认使用 libc++ 共享库。如需强制使用静态库,请在链接时传递 -static-libstdc++。此行为与普通主机工具链的行为一致。

正如 C++ 库支持中所提到的,在链接 libc ++ 时,通常需要传递 -latomic。

请注意,如果您省略 --install-dir 选项,该工具会在当前目录中创建名为 $TOOLCHAIN_NAME.tar.bz2 的 tarball。使用 --package-dir 可将此 tarball 放入不同的目录中。

如需了解更多选项和详情,请使用 --help。

使用 Clang

Clang 二进制文件会自动包含在独立工具链中。

在 /bin 下还有两个名为 clang 和 clang++ 的封装容器脚本。这些脚本会调用带有正确目标架构标记的 clang 二进制文件。换言之,这些脚本无需进行任何修改即可运行,而且您应该能够在自己的构建系统中使用这些脚本,只需设置指向这些脚本的 CC 和 CXX 环境变量即可。

还有名为 gcc 和 g++ 的封装容器脚本也会调用 Clang。尽管 NDK 不再包含 GCC,但这些脚本在一定程度上会兼容明确引用 GCC 的构建文件。很显然,如果构建文件使用 Clang 不支持的命令行选项,您将需要移除或替换这些选项。

Clang 以 ARM 为目标

为 ARM 构建时,Clang 会根据是否存在 -march=armv7-a 和/或 -mthumb 编译器标记来更改目标:

在这里插入图片描述

此外,您也可以视需要替换成自己的 -target。

clang 和 clang++ 应能够轻松替换 makefile 中的 gcc 和 g++。如有疑问,请在调用编译器时使用以下选项来验证其是否运行正常:


    -v:用于转储与编译器驱动程序问题有关的命令
    -###:用于转储命令行选项,包括以隐式方式预定义的选项。
    -x c < /dev/null -dM -E:用于转储预定义的预处理器定义
    -save-temps:用于比较 *.i 或 *.ii 预处理文件。

ABI 兼容性

默认情况下,ARM Clang 独立工具链将以 armeabi-v7a ABI 为目标。只需传递恰当的 -march 或 -target 选项,便可完成目标的替换。

我们建议使用 -mthumb 编译器标记来强制生成 16 位 Thumb-2 指令。如果已省略此指令,工具链将发出 32 位 ARM 指令。

若要使用 NEON 指令,您必须使用 -mfpu 编译器标记:-mfpu=neon。

请注意,按照 ARM 规范,此设置会强制使用 VFPv3-D32。

另外,请务必向链接器提供以下两个标记:-march=armv7-a -Wl,–fix-cortex-a8。

第一个标记可指示链接器选择为 armv7-a 定制的工具链库。在某些 Cortex-A8 实现中,需要使用第二个标记作为 CPU 错误的解决方法。

如果以其他 ABI 为目标,则不必使用任何特定的编译器标志。

如需详细了解 ABI 支持,请参阅 Android ABI。

警告和限制

Windows 支持

Windows 二进制文件不依赖于 Cygwin。这种独立性让它们的运行速度更快。不过,代价是它们不能像理解 cygdrive/c/foo/bar 一样理解 Cygwin 路径规范,例如 C:/foo/bar。

异常、RTTI 和 STL

默认情况下,工具链二进制文件支持 C++ 异常和 RTTI。如需在构建源代码时停用 C++ 异常和 RTTI(例如,为了生成更轻量的机器代码),请使用 -fno-exceptions 和 -fno-rtti。

C++ STL 支持

独立工具链包含 C++ 标准模板库 (STL) 实现。


    使用 -static-libstdc++ 获取静态库版本的 libc++。这样做可确保将所有必需的 C++ STL 代码添加到您最终的二进制文件。如果您只生成我们建议的单个共享库或可执行文件,那么此方法是理想之选。

    默认情况下,系统将使用共享库版本的 libc++。无需额外的标记即可链接到共享库。您必须打包应用中的 libc++_shared.so,否则代码将无法加载。

在这里插入图片描述

注意:如果您的项目包含多个共享库或可执行文件,那么您必须链接到共享库 STL 实现。否则,这些库中的全局状态将不再唯一,进而导致不可预测的运行时行为。这种行为可能包括崩溃和无法正确捕捉异常。

使用独立工具链构建开源项目

以下面的工具链为例:

# Create an arm64 API 26 libc++ toolchain.
$NDK/build/tools/make_standalone_toolchain.py \
  --arch arm64 \
  --api 26 \
  --install-dir=my-toolchain

以下是您设置环境以将其用于构建传统开源项目的方法:

# 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"
带自定义构建系统的项目

以下示例展示了在执行上述步骤后如何构建 toybox:

git clone https://github.com/landley/toybox.git
cd toybox
make defconfig && make
使用 autoconf 的项目

此外,如果是基于 autoconf 的项目,代码更类似以下内容:

tar zxvf make-4.2.tar.gz
cd make-4.2
./configure --host=$target_host && make

请注意,基于 autoconf 的项目在支持交叉编译方面的差异很大。另请注意,如果您 git clone 基于 autoconf 的项目,它不太可能有已签入的 configure 脚本,因此您必须遵循该项目的文档来了解如何进行引导。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值