将 NDK 与其他构建系统配合使用

NDK 提供对 ndk-buildCMake 的官方支持。大多数用户应参考其中一个指南来构建应用代码。本文旨在介绍如何构建使用其他构建系统的现有代码。对于不是特定于 Android 的第三方依赖项,例如 OpenSSL 和 libbzip2,通常会出现这种情况。

如果构建系统维护者希望为构建系统增加原生 NDK 支持,应阅读构建系统维护者指南

概览

从 NDK r19 开始,NDK 默认安装的工具链可供使用。与任意构建系统进行交互时不再需要使用 make_standalone_toolchain.py 脚本。

为了确保使用正确的架构进行构建,请在调用 Clang 时使用 -target 传递适当的目标,或调用具有目标前缀的 Clang。例如,若要为 64 位 ARM Android 编译值为 21 的 minSdkVersion,可使用以下两种方法,您可以选择使用其中最方便的方法:

$ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/clang++ \
    -target aarch64-linux-android21 foo.cpp
$ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/aarch64-linux-android21-clang++ \
    foo.cpp

在这两种情况下,请将 $NDK 替换为指向 NDK 的路径,将 $HOST_TAG 替换为指向根据下表所下载的 NDK 的路径:

NDK 操作系统变体 主机标记
macOS darwin-x86_64
Linux linux-x86_64
32 位 Windows windows
64 位 Windows windows-x86_64

这里的前缀或目标参数的格式是目标三元组,带有表示 minSdkVersion 的后缀。该后缀仅与 clang/clang++ 一起使用;binutils 工具(例如 arstrip)不需要后缀,因为它们不受 minSdkVersion 影响。Android 支持的目标三元组如下:

ABI 三元组
armeabi-v7a armv7a-linux-androideabi
arm64-v8a aarch64-linux-android
x86 i686-linux-android
x86-64 x86_64-linux-android

许多项目的构建脚本都预计使用 GCC 风格的交叉编译器,其中每个编译器仅针对一种操作系统/架构组合,因此可能无法正常处理 -target。在这些情况下,最好使用三元组前缀的 Clang 二进制文件。

Autoconf

Autoconf 项目允许您指定与环境变量一起使用的工具链。例如,以下示例展示了如何在 Linux 上使用 API 级别 21 的 minSdkVersion 为 Android x86-64 构建 libpng

# Check out the source.
git clone https://github.com/glennrp/libpng
cd libpng
# Only choose one of these, depending on your build machine...
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
# Only choose one of these, depending on your device...
export TARGET=aarch64-linux-android
export TARGET=armv7a-linux-androideabi
export TARGET=i686-linux-android
export TARGET=x86_64-linux-android
# Set this to your minSdkVersion.
export API=21
# Configure and build.
export AR=$TOOLCHAIN/bin/$TARGET-ar
export AS=$TOOLCHAIN/bin/$TARGET-as
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
export LD=$TOOLCHAIN/bin/$TARGET-ld
export RANLIB=$TOOLCHAIN/bin/$TARGET-ranlib
export STRIP=$TOOLCHAIN/bin/$TARGET-strip
./configure --host $TARGET
make

非 Autoconf make 项目

一些 makefile 项目允许通过覆盖与 autoconf 项目相同的变量进行交叉编译。以下示例展示了如何为 Android x86-64 构建 libbzip2,其中 minSdkVersion 为 21。

# Check out the source.
git clone https://gitlab.com/bzip/bzip2.git
cd bzip2

# Only choose one of these, depending on your build machine...
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64

# Only choose one of these, depending on your device...
export TARGET=aarch64-linux-android
export TARGET=armv7a-linux-androideabi
export TARGET=i686-linux-android
export TARGET=x86_64-linux-android

# Set this to your minSdkVersion.
export API=21

# Build.
make \
    CC=$TOOLCHAIN/bin/$TARGET$API-clang \
    AR=$TOOLCHAIN/bin/$TARGET-ar \
    RANLIB=$TOOLCHAIN/bin/$TARGET-ranlib \
    bzip2