NDK 包含对 ndk-build 和 CMake 的官方支持。大多数用户应该参考其中一个指南来构建应用程序代码。本文档的目的是描述如何构建使用其他构建系统的现有代码。对于非 Android 特定的第三方依赖项(例如 OpenSSL 和 libbzip2),通常会出现这种情况。
希望将其构建系统添加原生 NDK 支持的构建系统维护人员应改读 构建系统维护人员指南。
概述
NDK 中的 Clang 编译器仅需最少的配置即可使用,以定义您的目标环境。
为确保您为正确的架构构建,在调用 Clang 时传递适当的目标,并使用 -target
。例如,要使用 minSdkVersion
21 为 64 位 ARM Android 编译,请执行以下操作
$ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/clang++ \
--target=aarch64-linux-android21 foo.cpp
或者,还有针对 Clang 的目标前缀入口点。根据 NDK 版本和主机操作系统,这些可能是符号链接或脚本,它们会转发到 clang。直接使用 --target
调用 Clang 会更可靠,因为这是测试最多的工作流程,并且脚本中偶尔会出现参数转发错误。在 Windows 上,从脚本转发到真实编译器所需的额外 CreateProcess
可能会对构建速度产生明显的负面影响。
$ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android21-clang++ \
foo.cpp
在这两种情况下,请将 $NDK
替换为 NDK 的路径,并将 $HOST_TAG
替换为根据下表匹配您下载的 NDK
NDK 操作系统变体 | 主机标签 |
---|---|
macOS | darwin-x86_64 |
Linux | linux-x86_64 |
64 位 Windows | windows-x86_64 |
此处的首缀或目标参数的格式是目标三元组,后跟表示 minSdkVersion
的后缀。此后缀仅与 clang/clang++ 一起使用;binutils 工具(例如 ar
和 strip
)不需要后缀,因为它们不受 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
。在这些情况下,您通常可以将 -target
参数包含在编译器定义中(例如 CC="clang -target aarch64-linux-android21
)。在您使用的构建系统无法使用该形式的罕见情况下,请使用三元组前缀的 Clang 二进制文件。
Autoconf
Autoconf 项目允许您使用环境变量指定要使用的工具链。例如,以下示例展示了如何在 Linux 上为 Android x86-64 构建 libpng
,并且 minSdkVersion
为 API 级别 21。
# Check out the source. git clone https://github.com/glennrp/libpng -b v1.6.37 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/llvm-ar export CC="$TOOLCHAIN/bin/clang --target=$TARGET$API" export AS=$CC export CXX="$TOOLCHAIN/bin/clang++ --target=$TARGET$API" export LD=$TOOLCHAIN/bin/ld export RANLIB=$TOOLCHAIN/bin/llvm-ranlib export STRIP=$TOOLCHAIN/bin/llvm-strip ./configure --host $TARGET make
此示例中选择的工具适用于 NDK r22 及更高版本。较旧的 NDK 可能需要不同的工具。
非 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/clang --target=$TARGET$API" \
AR=$TOOLCHAIN/bin/llvm-ar \
RANLIB=$TOOLCHAIN/bin/llvm-ranlib \
bzip2
此示例中选择的工具适用于 NDK r22 及更高版本。较旧的 NDK 可能需要不同的工具。