音视频

认识NDK编译

2020-07-28  本文已影响0人  海盗的帽子

一. Android ABI

不同的 Android 设备使用不同的 CPU,而不同的 CPU 支持不同的指令集。CPU 与指令集的每种组合都有专属的应用二进制接口 Application Binary Interface ( ABI ),因此使用 NDK 生成在 Android 运行 .a 或 .so (都是二进制文件)就需要指定 ABI 。 目前 NDK 支持的 ABI 如下:

ABI 支持的指令集 CPU 架构 应用
armeabi-v7a armeabi 等 ARM 32 位 手机
arm64-v8a AArch64 等 ARM 64 位 手机
x86 x86 (IA-32) 等 x86 32 位 PC
x86_64 x86-64 等 x86 64 位 PC

NDK 17 前支持 ARMv5 (armeabi) 以及 32 位和 64 位 MIPS,但 NDK r17 和 17 后不再支持。

1. 指定 ABI
Gradle

默认情况下,Gradle(无论是通过 Android Studio 使用,还是从命令行使用)会针对所有非弃用 ABI 进行构建。要限制应用支持的 ABI 集,可以使用 abiFilters。例如,要仅针对 64 位 ABI 进行构建,可以在 build.gradle 中设置以下配置:

android {
    defaultConfig {
        ndk {
            abiFilters 'arm64-v8a', 'x86_64'
        }
    }
}
ndk-build

默认情况下,ndk-build 会针对所有非弃用 ABI 进行构建。可以通过在 Application.mk 文件中设置 APP_ABI 来定位特定 ABI。如下:

APP_ABI := arm64-v8a  # Target only arm64-v8a
APP_ABI := all  # Target all ABIs, including those that are deprecated.
APP_ABI := armeabi-v7a x86_64  # Target only armeabi-v7a and x86_64.

CMAKE

使用 CMake 时,一次只能针对一个 ABI 进行构建,并且必须明确指定 ABI。为此,如果需要使用 ANDROID_ABI ,则必须在命令行中指定(无法在 CMakeLists.txt 中设置)。例如:

$ cmake -DANDROID_ABI=arm64-v8a ...
$ cmake -DANDROID_ABI=armeabi-v7a ...
$ cmake -DANDROID_ABI=x86 ...
$ cmake -DANDROID_ABI=x86_64 ...
2. 在C/C++处理 CPU 功能区别 ABI

通常,在构建时使用#ifdef 及以下各项确定 ABI 最为方便:

二. 使用 NDK 构建项目

使用 NDK 编译代码主要有三种方式:

1. NDK 主要目录

NDK 编译主要与下面几个目录有关:

platforms

包含不同的 Android 版本目录,每个 Android 版本目录又包含 不同的 ABI 目录,在 ABI 目录里面有 /usr/lib 目录,包含常用的 .a 或 .so 库,在 /usr/include 里包含需要的头文件( ndk 16 后不保留头文件)。

sysroot

包含需要的 .a 或 .so 库和头文件,在 usr/lib 和 usr/include 和目录下(ndk 16 后两者都有,16和16前只有头文件)。

toolchain

包含编译(交叉编译)工具链的目录

build/tools

包含独立编译工具链脚本 make_standalone_toolchain.py 或者 make_standalone_toolchain.sh ,其作用是根据 Android API 和 ABI 集成目标系统库,目标系统头文件和编译器在指定的一个目录。当然使用这个脚本也是可以的,不过需要指定各个库、头文件的目录,通常这些都不再一个目录,比较麻烦。使用 make_standalone_toolchain 的方式是:

--arch 指定 cpu 架构  --api 指定系统版本 --install-dir 生成的编译工具链目录

例如
./make_standalone_toolchain.py \
        --arch arm --api 21 --install-dir /tmp/android-21-toolchain

在 NDK 19 开始就不需要使用独立工具链了, 在 toolchains/llvm/ 下已经提供好了编译工具, 读者自行去下载进入目录看看,和独立工具链编译出来的结构非常类似,不过它比较全的是针对不同平台版本。

2. 用独立工具链编译代码

用独立工具链编译代码的时需要指定下面几个地方

3. 指定 NDK 提供的头文件和库

查找优先级 -I > isystem > isysroot

4. 不同 NDK 版本目标系统库、头文件和编译器的差异

image.png
上一篇下一篇

猜你喜欢

热点阅读