资讯详情

Android ABI

不同的 Android 不同的设备使用 CPU,而不同的 CPU 支持不同的指令集。CPU 与指令集的每个组合都有独家的应用二进制接口 (ABI)。ABI 包括以下信息:

可使用的 CPU 指令集(和扩展指令集)。

存储和加载在运行过程中的字节顺序。Android 始终是 little-endian。

在应用和系统之间传递数据的规范(包括对齐限制),以及系统调用函数时如何使用堆栈和寄存器。

可执行二进制文件(如程序和共享库)的格式,以及它们支持的内容类型。Android 始终使用 ELF。如需了解详情,请参考 ELF System V 应用二进制接口。

如何重整 C 名称。详情请参考 Generic/Itanium C ABI。

本页列举了 NDK 支持的 ABI,并介绍了每一个 ABI 操作原理。

ABI 也可以指平台支持的原生 API。如需影响 32 这种位系统 ABI 请参考问题列表 32 位 ABI 错误。

支持的 ABI

表 1. ABI 支持指令集。

ABI

支持指令集

备注

armeabi

Thumb-2

VFPv3-D16

与 ARMv5/v6 设备不兼容。

x86 (IA-32)

MMX

SSE/2/3

SSSE3

不支持 MOVBE 或 SSE4。

x86-64

MMX

SSE/2/3

SSSE3

SSE4.1、4.2

POPCNT

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

armeabi-v7a

此 ABI 适用于基于 32 位 ARM 的 CPU。Android 变体包含 Thumb-2 和 VFP 硬件浮点指令(具体来说, VFPv3-D其中包含16) 16 个专用 64 浮点寄存器。

如需详细了解 ABI 不具体 Android 请参考部分 ARM 二进制接口架构的应用 (ABI)

默认情况下,NDK 构建系统会生成 Thumb-2 代码,除非你在 Android.mk 中针对 ndk-build 使用 LOCAL_ARM_MODE,或在配置 CMake 时使用 ANDROID_ARM_MODE。

包括高级 SIMD (Neon) 和 VFPv3-D32 其他扩展程序都是可选的。详情请参考 Neon 支持。

armeabi-v7a ABI 使用 -mfloat-abi=softfp 强制执行以下规则:虽然系统可以执行浮点代码,但编译器必须在调用函数时传输整数寄存器中的所有信息 float 整数寄存器对中的所有值和 double 值。

arm64-v8a

此 ABI 适用于基于 ARMv8-A 的 CPU,支持 64 位 AArch64 结构。它包含高级 SIMD (Neon) 架构扩展指令集。

您可以在 C 和 C 代码中使用 Neon 充分利用高级内建函数 SIMD 扩展指令集 Armv8-A 的 Neon 详细介绍了程序员指南 Neon 内建函数和 Neon 编程概况。

如需了解 ABI 不具体 Android 请参考部分的完整细节 Arm 理解架构。Arm 还针对64 位 Android 在移植方面提供了一些建议。

在 Android 特定于平台 x18 寄存器寄存器 ShadowCallStack,您的代码不应使用。 Clang 默认使用版本 Android 中的 -ffixed-x18 因此,除非你使用手写编译器(或非常旧的编译器),否则不必担心这一点。

x86

此 ABI 适用于支持通常称为x86”、“i386”或“IA-32指令集 CPU。此 ABI 其特点包括:

指令通常由具有编译器标志的指令组成 GCC 生成如下:

-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32

指向这些标志 Pentium Pro 指令集,以及 MMX、SSE、SSE2、SSE3 和 SSSE3 扩展指令集。顶层生成的代码 Intel 32 位 CPU 均衡优化。

更多关于编译器标志的信息,特别是与性能优化相关的信息,请参考 GCC x86 性能提示。

使用标准 Linux x86 32 位调用规范,和 SVR 使用规范相反。详情请参考不同的内容 C 编译器和操作系统的调用规范 6 部分使用寄存器。

ABI 没有其他选择 IA-32 例如:

MOVBE

SSE4 的任何变体。

您仍然可以使用这些扩展指令集,只要您使用功能探测来启用它们,并为不支持它们的设备提供退货机制。

NDK 函数调用前假设工具链 16 字节堆栈对齐。默认工具和选项将强制执行此规则。如果编写汇编码,则必须确保堆栈对齐,其他编译器也遵守此规则。

详情请参考以下文件:

x86_64

此 ABI 适用于支持通常称为x86-64指令集 CPU。它支持 GCC 通常使用以下编译器标志生成的指令:

-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel

指向这些标志 x86-64 指令集(根据 GCC 文档)和 MMX、SSE、SSE2、SSE3、SSSE3、SSE4.1、SSE4.2 和 POPCNT 扩展指令集。顶层生成的代码 Intel 64 位 CPU 均衡优化。

更多关于编译器标志的信息,特别是与性能优化相关的信息,请参考 GCC x86 性能提示。

此 ABI 没有其他可选的 x86-64 例如:

MOVBE

SHA

AVX

AVX2

您仍然可以使用这些扩展指令集,只要您使用功能探测来启用它们,并为不支持它们的设备提供退货机制。

详情请参考以下文件:

为特定 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 几个例子:

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.

如果你需要详细了解,你可以认为你可以 APP_ABI 请参考指定值 Android.mk。

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

必须传递 CMake 以使用 NDK 其他建造的标志请参考 CMake 指南。

构建系统的默认行为是构建每个系统 ABI 二进制文件包括单个 APK(也称为胖 APK)内。只包括单个 ABI 二进制文件 APK 相比,胖 APK 要大得多;要权衡的是兼容性更广,但是 APK 更大。强烈建议您使用 app bundle 和 APK 拆分减小 APK 的大小,同时仍保持最大限度的设备兼容性。

软件包管理器,软件包管理器只解决最适合目标设备的机器代码。详情请参考安装过程中自动解压原始代码。

Android 平台上的 ABI 管理

本部分详细说明 Android 如何管理平台? APK 本地代码在中间。

应用软件包中的原始代码

Play 商店和软件包管理器都希望 APK 找到符合下列格式的文件路径 NDK 生成的库:

/lib//lib.so

其中, 是支持的 ABI 下列出的 ABI 名称之一, 是您为 Android.mk 文件中的 LOCAL_MODULE 用于变量定义库的库名。 APK 文件只是 zip 文件,因此打开它们并确认共享原生库位于该位于的位置很简单。

如果系统在预期位置找不到原生共享库,便无法使用它们。在这种情况下,应用本身必须复制这些库,然后执行 dlopen()。

在胖 APK 中,每个库位于名称与相应 ABI 匹配的目录下。例如,胖 APK 可能包含:

/lib/armeabi/libfoo.so

/lib/armeabi-v7a/libfoo.so

/lib/arm64-v8a/libfoo.so

/lib/x86/libfoo.so

/lib/x86_64/libfoo.so

注意:搭载 4.0.3 或更早版本、基于 ARMv7 的 Android 设备从 armeabi 目录(而非 armeabi-v7a 目录,如果两个目录都存在)安装原生库。这是因为在 APK 中,/lib/armeabi/ 在 /lib/armeabi-v7a/ 后面。从 4.0.4 开始,此问题已修复。

Android 平台 ABI 支持

Android 系统在运行时知道它支持哪些 ABI,因为 build 特定的系统属性会指示:

设备的主要 ABI,与系统映像本身使用的机器代码对应。

(可选)与系统映像也支持的其他 ABI 对应的辅助 ABI。

此机制确保系统在安装时从软件包提取最佳机器代码。

为实现最佳性能,应直接针对主要 ABI 进行编译。例如,基于 ARMv5TE 的典型设备只会定义主 ABI:armeabi。相反,基于 ARMv7 的典型设备将主 ABI 定义为 armeabi-v7a,并将辅助 ABI 定义为 armeabi,因为它可以运行为每个 ABI 生成的应用原生二进制文件。

64 位设备也支持其 32 位变体。以 arm64-v8a 设备为例,该设备也可以运行 armeabi 和 armeabi-v7a 代码。但请注意,如果应用以 arm64-v8a 为目标,而非依赖于运行 armeabi-v7a 版应用的设备,则应用在 64 位设备上的性能要好得多。

许多基于 x86 的设备也可运行 armeabi-v7a 和 armeabi NDK 二进制文件。对于这些设备,主 ABI 将是 x86,辅助 ABI 是 armeabi-v7a。

您可以为特定 ABI 强制安装 apk。这在测试时非常有用。请使用以下命令:adb install --abi abi-identifier path_to_apk

安装时自动解压缩原生代码

安装应用时,软件包管理器服务将扫描 APK,并查找以下形式的任何共享库:

lib//lib.so

如果未找到,并且您已定义辅助 ABI,该服务将扫描以下形式的共享库:

lib//lib.so

找到所需的库时,软件包管理器会将它们复制到应用的原生库目录 (/) 下的 /lib/lib.so。以下代码段会收到 nativeLibraryDir:

Kotlin

import android.content.pm.PackageInfo

import android.content.pm.ApplicationInfo

import android.content.pm.PackageManager

...

val ainfo = this.applicationContext.packageManager.getApplicationInfo(

"com.domain.app",

PackageManager.GET_SHARED_LIBRARY_FILES

)

Log.v(TAG, "native library dir ${ainfo.nativeLibraryDir}")Java

import android.content.pm.PackageInfo;

import android.content.pm.ApplicationInfo;

import android.content.pm.PackageManager;

...

ApplicationInfo ainfo = this.getApplicationContext().getPackageManager().getApplicationInfo

(

"com.domain.app",

PackageManager.GET_SHARED_LIBRARY_FILES

);

Log.v( TAG, "native library dir " + ainfo.nativeLibraryDir );

如果根本没有共享对象文件,应用也会构建并安装,但在运行时会崩溃。

标签: p20k3aqj圆形连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台