官網(wǎng)?鏈接
ABI 管理
不同 Android 手機(jī)使用不同的 CPU,因此支持不同的指令集。CPU 與指令集的每種組合都有其自己的應(yīng)用二進(jìn)制界面(或?ABI)。 ABI 可以非常精確地定義應(yīng)用的機(jī)器代碼在運(yùn)行時(shí)如何與系統(tǒng)交互。 您必須為應(yīng)用要使用的每個(gè) CPU 架構(gòu)指定 ABI紊浩。
典型的 ABI 包含以下信息:
機(jī)器代碼應(yīng)使用的 CPU 指令集。
運(yùn)行時(shí)內(nèi)存存儲(chǔ)和加載的字節(jié)順序疗锐。
可執(zhí)行二進(jìn)制文件(例如程序和共享庫(kù))的格式坊谁,以及它們支持的內(nèi)容類型。
用于解析內(nèi)容與系統(tǒng)之間數(shù)據(jù)的各種約定滑臊。這些約定包括對(duì)齊限制口芍,以及系統(tǒng)如何使用堆棧和在調(diào)用函數(shù)時(shí)注冊(cè)。
運(yùn)行時(shí)可用于機(jī)器代碼的函數(shù)符號(hào)列表 - 通常來(lái)自非常具體的庫(kù)集雇卷。
本頁(yè)枚舉了 NDK 支持的 ABI鬓椭,并且提供每個(gè) ABI 如何運(yùn)行的信息颠猴。
支持的 ABI
每個(gè) ABI 支持一個(gè)或多個(gè)指令集。表 1 提供每個(gè) ABI 支持的指令集概覽。
表 1.?ABI 和支持的指令集。
ABI支持的指令集說(shuō)明
armeabiARMV5TE 和更高版本
Thumb-1
無(wú)硬浮點(diǎn)歼狼。
armeabi-v7aarmeabi
Thumb-2
VFPv3-D16
其他(可選)
與 ARMv5、v6 設(shè)備不兼容资盅。
arm64-v8aAArch-64
x86x86 (IA-32)
MMX
SSE/2/3
SSSE3
不支持 MOVBE 或 SSE4。
x86_64x86-64
MMX
SSE/2/3
SSSE3
SSE4.1踊赠、4.2
POPCNT
mipsMIPS32r1 及更高版本使用硬浮點(diǎn)呵扛,并且假設(shè) CPU:FPU 時(shí)鐘比率為 2:1 以獲取最大兼容性。 不提供 micromips 或 MIPS16筐带。
mips64MIPS64r6
有關(guān)下面每個(gè) ABI 的更多詳細(xì)信息今穿。
armeabi
此 ABI 適用于基于 ARM、至少支持 ARMv5TE 指令集的 CPU伦籍。 請(qǐng)參閱以下文檔了解詳情:
ARM 架構(gòu)的過(guò)程調(diào)用標(biāo)準(zhǔn)
ARM 架構(gòu)的應(yīng)用二進(jìn)制界面 (ABI)
ELF System V 應(yīng)用二進(jìn)制界面
AAPCS 標(biāo)準(zhǔn)將 EABI 定義為類似但不同 ABI 的系列蓝晒。 此外,Android 還采用小字節(jié)序?ARM GNU/Linux ABI帖鸦。
此 ABI 不支持硬件輔助的浮點(diǎn)計(jì)算芝薇。 相反,所有浮點(diǎn)運(yùn)算都使用編譯器?libgcc.a?靜態(tài)庫(kù)中的軟件幫助程序函數(shù)富蓄。
armeabi ABI 支持 ARM 的?Thumb(亦稱 Thumb-1)指令集。NDK 默認(rèn)生成 Thumb 代碼慢逾,除非您在?Android.mk?文件中使用?LOCAL_ARM_MODE?變量指定不同的行為立倍。
armeabi-v7a
此 ABI 可擴(kuò)展 armeabi 以包含多個(gè)?CPU 指令集擴(kuò)展。 此 Android 特定 ABI 支持的指令擴(kuò)展包括:
Thumb-2 指令集擴(kuò)展侣滩,其性能堪比 32 位 ARM 指令口注,簡(jiǎn)潔性類似于 Thumb-1。
VFP 硬件 FPU 指令君珠。更具體一點(diǎn)寝志,包括 VFPv3-D16,它除了 ARM 核心中的 16 個(gè) 32 位寄存器之外策添,還包含 16 個(gè)專用 64 位浮點(diǎn)寄存器材部。
v7-a ARM 規(guī)格描述的其他擴(kuò)展,包括?高級(jí) SIMD(亦稱 NEON)唯竹、VFPv3-D32 和 ThumbEE乐导,都是此 ABI 可選的。 由于不能保證它們存在浸颓,因此系統(tǒng)在運(yùn)行時(shí)應(yīng)檢查擴(kuò)展是否可用物臂。 如果不可用旺拉,則必須使用替代代碼路徑。此檢查類似于系統(tǒng)在檢查或使用?MMX棵磷、SSE2?及 x86 CPU 上其他專用指令集時(shí)所執(zhí)行的檢查蛾狗。
如需了解有關(guān)如何執(zhí)行這些運(yùn)行時(shí)檢查的信息,請(qǐng)參閱?cpufeatures?庫(kù)仪媒。另外沉桌,有關(guān) NDK 支持為 NEON 構(gòu)建機(jī)器代碼的信息,請(qǐng)參閱?NEON 支持规丽。
armeabi-v7a?ABI 使用?-mfloat-abi=softfp?開關(guān)強(qiáng)制實(shí)施規(guī)則蒲牧,要求編譯器在函數(shù)調(diào)用時(shí)必須傳遞核心寄存器對(duì)中的所有雙精度值,而不是專用浮點(diǎn)值赌莺。 系統(tǒng)可以使用 FP 寄存器執(zhí)行所有內(nèi)部計(jì)算冰抢。 這樣可極大地加速計(jì)算。
arm64-v8a
此 ABI 適用于基于 ARMv8艘狭、支持 AArch64 的 CPU挎扰。它還包含 NEON 和 VFPv4 指令集。
如需了解詳細(xì)信息巢音,請(qǐng)參閱?ARMv8 技術(shù)預(yù)覽遵倦,并聯(lián)系 ARM 了解進(jìn)一步的詳細(xì)信息。
x86
此 ABI 適用于支持通常稱為“x86”或“IA-32”的指令集的 CPU官撼。 此 ABI 的特性包括:
指令一般由具有編譯器標(biāo)志的 GCC 生成梧躺,如下所示:
-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32
這些標(biāo)志指向 Pentium Pro 指令集,伴隨?MMX傲绣、SSE掠哥、SSE2、SSE3?及?SSSE3?指令集擴(kuò)展秃诵。生成的代碼在頂層 Intel 32 位 CPU 之間進(jìn)行了均衡優(yōu)化续搀。
如需了解有關(guān)編譯器標(biāo)志的詳細(xì)信息,特別是與性能優(yōu)化相關(guān)的信息菠净,請(qǐng)參閱?GCC x86 性能提示禁舷。
使用標(biāo)準(zhǔn) Linux x86 32 位調(diào)用約定,與 SVR 使用的約定相反毅往。如需了解詳細(xì)信息牵咙,請(qǐng)參閱不同 C++ 編譯器和操作系統(tǒng)的調(diào)用約定的第 6 節(jié)“寄存器的使用”。
ABI 不含任何其他可選的 IA-32 指令集擴(kuò)展攀唯,例如:
MOVBE
SSE4 的任何變體霜大。
您仍可使用這些擴(kuò)展,只要您使用運(yùn)行時(shí)功能探測(cè)來(lái)啟用它們革答,并且為不支持它們的設(shè)備提供備用方法战坤。
NDK 工具鏈假設(shè)在函數(shù)調(diào)用之前進(jìn)行 16 位棧對(duì)齊曙强。默認(rèn)工具和選項(xiàng)強(qiáng)制執(zhí)行此規(guī)則。 如果編寫的是匯編代碼途茫,必須確保棧對(duì)齊碟嘴,而且其他編譯器也遵守此規(guī)則。
請(qǐng)參閱以下文檔了解詳情:
GCC 在線文檔: Intel 386 和 AMD x86-64 選項(xiàng)
不同 C++ 編譯器和操作系統(tǒng)的調(diào)用約定
Intel IA-32 Intel 架構(gòu)軟件開發(fā)者手冊(cè)第 2 卷:指令集參考
Intel IA-32 Intel 架構(gòu)軟件開發(fā)者手冊(cè)第 3 卷:系統(tǒng)編程指南
System V 應(yīng)用二進(jìn)制界面: Intel386 處理器架構(gòu)補(bǔ)充
x86_64
此 ABI 適用于支持通常稱為“x86-64”的指令集的 CPU囊卜。 它支持 GCC 通常使用以下編譯器標(biāo)志生成的指令:
-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel
這些標(biāo)志指向 x86-64 指令集(根據(jù) GCC 文檔)娜扇,伴隨?MMX、SSE栅组、SSE2雀瓢、SSE3、SSSE3玉掸、SSE4.1刃麸、SSE4.2?和?POPCNT?指令集擴(kuò)展。 生成的代碼在頂層 Intel 64 位 CPU 之間進(jìn)行了均衡優(yōu)化司浪。
如需了解有關(guān)編譯器標(biāo)志的詳細(xì)信息泊业,特別是與性能優(yōu)化相關(guān)的信息,請(qǐng)參閱?GCC x86 性能啊易。
此 ABI 不含任何其他可選的 x86-64 指令集擴(kuò)展吁伺,例如:
MOVBE
SHA
AVX
AVX2
您仍可使用這些擴(kuò)展,只要您使用運(yùn)行時(shí)功能探測(cè)來(lái)啟用它們租谈,并且為不支持它們的設(shè)備提供備用方法篮奄。
請(qǐng)參閱以下文檔了解詳情:
不同 C++ 編譯器和操作系統(tǒng)的調(diào)用約定
Intel64 和 IA-32 架構(gòu)軟件開發(fā)者手冊(cè)第 2 卷:指令集參考
Intel64 和 IA-32 架構(gòu)軟件開發(fā)者手冊(cè)第 3 卷:系統(tǒng)編程
mips
此 ABI 適用于基于 MIPS、至少支持 MIPS32r1 指令集的 CPU割去。它包含以下功能:
MIPS32 修訂版 1 ISA
小字節(jié)序
O32
硬浮點(diǎn)
無(wú) DSP 應(yīng)用特定的擴(kuò)展
如需了解詳細(xì)信息窟却,請(qǐng)參閱以下文檔:
編程者的架構(gòu) ("MIPSARCH")
ELF System V 應(yīng)用二進(jìn)制界面
如需了解更具體的詳細(xì)信息,請(qǐng)參閱?MIPS32 架構(gòu)劫拗。常見問(wèn)答請(qǐng)參閱?MIPS FAQ间校。
mips64
此 ABI 適用于 MIPS64 R6矾克。如需了解詳細(xì)信息页慷,請(qǐng)參閱?MIPS64 架構(gòu)。
為特定 ABI 生成代碼
默認(rèn)情況下胁附,NDK 為 armeabi ABI 生成機(jī)器代碼酒繁。但您可以通過(guò)向?Application.mk?文件添加以下行生成 ARMv7-a 兼容的機(jī)器代碼。
APP_ABI := armeabi-v7a
要為兩個(gè)或更多不同的 ABI 構(gòu)建機(jī)器代碼控妻,請(qǐng)使用空格作為分隔符州袒。例如:
APP_ABI := armeabi armeabi-v7a
此設(shè)置指示 NDK 為機(jī)器代碼構(gòu)建兩個(gè)版本:此行中所列的每個(gè) ABI 一個(gè)。 如需了解有關(guān)可以為?APP_ABI?變量指定的值的詳細(xì)信息弓候,請(qǐng)參閱?Android.mk郎哭。
構(gòu)建多個(gè)機(jī)器代碼版本時(shí)他匪,構(gòu)建系統(tǒng)會(huì)將庫(kù)復(fù)制到應(yīng)用項(xiàng)目路徑夸研,并最終將它們封裝到 APK 中邦蜜,從而創(chuàng)建一個(gè)胖二進(jìn)制文件。 胖二進(jìn)制文件大于只包含一個(gè)系統(tǒng)的機(jī)器代碼的二進(jìn)制文件亥至;權(quán)衡方式是兼容性更廣悼沈,但 APK 更大。
在安裝時(shí)姐扮,軟件包管理器只解包最適合目標(biāo)設(shè)備的機(jī)器代碼絮供。 如需了解詳細(xì)信息,請(qǐng)參閱安裝時(shí)自動(dòng)解壓縮原生代碼茶敏。
Android 平臺(tái)上的 ABI 管理
本節(jié)詳細(xì)說(shuō)明 Android 平臺(tái)如何管理 APK 中的原生代碼壤靶。
應(yīng)用包中的原生代碼
Play 商店和軟件包管理器專家預(yù)期在 APK 中符合以下模式的文件路徑上查找 NDK 生成的庫(kù):
/lib//lib.so
這里的??是支持的 ABI?下面列出的 ABI 名稱之一,?是您為?Android.mk?文件中的?LOCAL_MODULE?變量定義庫(kù)時(shí)使用的庫(kù)名稱睡榆。 由于 APK 文件只是 zip 文件萍肆,因此打開它們并確認(rèn)它們屬于哪些共享原生庫(kù)很簡(jiǎn)單。
如果系統(tǒng)在預(yù)期位置找不到原生共享庫(kù)胀屿,便無(wú)法使用它們塘揣。 在這種情況下,應(yīng)用本身必須復(fù)制這些庫(kù)宿崭,然后執(zhí)行?dlopen()亲铡。
在胖二進(jìn)制文件中,每個(gè)庫(kù)位于其名稱與相應(yīng) ABI 匹配的目錄下葡兑。例如奖蔓,胖二進(jìn)制文件可能包含:
/lib/armeabi/libfoo.so/lib/armeabi-v7a/libfoo.so/lib/arm64-v8a/libfoo.so/lib/x86/libfoo.so/lib/x86_64/libfoo.so/lib/mips/libfoo.so/lib/mips64/libfoo.so
注:運(yùn)行 4.0.3 或更早版本、基于 ARMv7 的 Android 設(shè)備從?armeabi?目錄(而非?armeabi-v7a?目錄讹堤,如果兩個(gè)目錄都存在)安裝原生庫(kù)吆鹤。 這是因?yàn)樵?APK 中,/lib/armeabi/?在?/lib/armeabi-v7a/?后面洲守。 從 4.0.4 開始疑务,此問(wèn)題已修復(fù)。
Android 平臺(tái) ABI 支持
Android 系統(tǒng)在運(yùn)行時(shí)知道它支持哪些 ABI梗醇,因?yàn)榘姹咎囟ǖ南到y(tǒng)屬性會(huì)指示:
設(shè)備的主要 ABI知允,與系統(tǒng)映像本身使用的機(jī)器代碼對(duì)應(yīng)。
可選的輔助 ABI叙谨,與系統(tǒng)映像也支持的另一個(gè) ABI 對(duì)應(yīng)温鸽。
此機(jī)制確保系統(tǒng)在安裝時(shí)從軟件包提取最佳機(jī)器代碼。
為實(shí)現(xiàn)最佳性能手负,應(yīng)直接針對(duì)主要 ABI 進(jìn)行編譯涤垫。例如姑尺,基于 ARMv5TE 的典型設(shè)備只會(huì)定義主要 ABI:armeabi。 相反蝠猬,基于 ARMv7 的典型設(shè)備將主要 ABI 定義為?armeabi-v7a股缸,而將輔助 ABI 定義為?armeabi,因?yàn)樗梢赃\(yùn)行為每個(gè) ABI 生成的應(yīng)用原生二進(jìn)制文件吱雏。
許多基于 x86 的設(shè)備也可運(yùn)行?armeabi-v7a?和?armeabi?NDK 二進(jìn)制文件敦姻。對(duì)于這些設(shè)備,主要 ABI 將是?x86歧杏,輔助 ABI 是?armeabi-v7a镰惦。
基于 MIPS 的典型設(shè)備只定義主要 ABI:mips。
安裝時(shí)自動(dòng)解壓縮原生代碼
安裝應(yīng)用時(shí)犬绒,軟件包管理器服務(wù)將掃描 APK旺入,查找以下形式的任何共享庫(kù):
lib//lib.so
如果未找到,并且您已定義輔助 ABI凯力,該服務(wù)將掃描以下形式的共享庫(kù):
lib//lib.so
找到所需的庫(kù)時(shí)茵瘾,軟件包管理器會(huì)將它們復(fù)制到應(yīng)用的?data?目錄 (data/data//lib/) 下的?/lib/lib.so。
如果根本沒有共享對(duì)象文件咐鹤,應(yīng)用也會(huì)構(gòu)建并安裝拗秘,但在運(yùn)行時(shí)會(huì)崩潰。