1. 程式人生 > 其它 >Android so庫檔案對應的ABI (arm64-v8a、armeabi-v7a、x86、x86_64)

Android so庫檔案對應的ABI (arm64-v8a、armeabi-v7a、x86、x86_64)

Android so庫檔案對應的ABI

原文:https://developer.android.com/ndk/guides/abis?hl=id#gradle

ABI Android

Perangkat Android yang berbeda menggunakan CPU yang berbeda pula, sehingga kumpulan petunjuk yang didukungnya juga berbeda. Setiap kombinasi CPU dan kumpulan petunjuk memiliki Antarmuka Biner Aplikasi (ABI)-nya sendiri. ABI mencakup informasi berikut:

  • Kumpulan petunjuk CPU (dan ekstensi) yang dapat digunakan.
  • Endianess penyimpanan dan pemuatan memori saat runtime. Android selalu bersifat little-endian.
  • Konvensi untuk meneruskan data antara aplikasi dan sistem, termasuk batasan perataan, serta cara sistem menggunakan stack dan register saat memanggil fungsi.
  • Format biner yang dapat dieksekusi, seperti program dan library bersama, serta jenis konten yang didukungnya. Android selalu menggunakan ELF. Untuk informasi selengkapnya, lihatAntarmuka Biner Aplikasi System V ELF.
  • Cara nama C++ dimodifikasi. Untuk mengetahui informasi selengkapnya, lihatABI C++ Generik/Itanium
    .

Halaman ini mencantumkan ABI yang didukung NDK, dan memberikan informasi tentang cara kerja masing-masing ABI.

ABI juga dapat merujuk ke API native yang didukung oleh platform. Untuk daftar jenis masalah ABI yang memengaruhi sistem 32-bit, lihatBug ABI 32-bit.

ABI yang Didukung

Tabel 1.ABI dan kumpulan petunjuk yang didukung.

ABIKumpulan Petunjuk yang DidukungCatatan
armeabi-v7a
  • armeabi
  • Thumb-2
  • VFPv3-D16
Tidak kompatibel dengan perangkat ARMv5/v6.
arm64-v8a
  • AArch64
x86
  • x86 (IA-32)
  • MMX
  • SSE/2/3
  • SSSE3
Tidak ada dukungan untuk MOVBE atau SSE4.
x86_64
  • x86-64
  • MMX
  • SSE/2/3
  • SSSE3
  • SSE4.1, 4.2
  • POPCNT

Catatan:Secara historis, NDK mendukung ARMv5 (armeabi) serta MIPS 32-bit dan 64-bit, tetapi dukungan untuk ABI ini telah dihapus pada NDK r17.

armeabi-v7a

ABI ini ditujukan bagi CPU berbasis ARM 32-bit. Varian Android menyertakan petunjuk floating point hardware VFP dan Thumb-2, khususnya VFPv3-D16, yang menyertakan 16 register floating point 64-bit khusus.

Untuk mengetahui informasi tentang bagian ABI yang bukan khusus Android, lihatAntarmuka Biner Aplikasi (ABI) untuk Arsitektur ARM

Sistem build NDK membuat kode Thumb-2 secara default, kecuali jika Anda menggunakanLOCAL_ARM_MODEdalamAndroid.mkuntuk ndk-build atauANDROID_ARM_MODEsaat mengonfigurasiCMake.

Ekstensi lain termasuk Advanced SIMD (Neon) dan VFPv3-D32 bersifat opsional. Untuk mengetahui informasi selengkapnya, lihatDukungan Neon.

ABIarmeabi-v7amenggunakan-mfloat-abi=softfpuntuk menerapkan aturan bahwa, meskipun sistem dapat mengeksekusi kode floating point, compiler harus meneruskan semua nilaifloatdalam register integer dan semua nilaidoubledalam pasangan register integer saat melakukan panggilan fungsi.

arm64-v8a

ABI ini ditujukan bagi CPU berbasis ARMv8-A, yang mendukung arsitektur AArch64 64-bit. ABI ini menyertakan ekstensi arsitektur Advanced SIMD (Neon).

Anda dapat menggunakanintrinsik Neondalam kode C dan C++ untuk memanfaatkan ekstensi Advanced SIMD.Panduan Programmer Neon untuk Armv8-Amemberikan informasi selengkapnya tentang intrinsik dan pemrograman Neon secara umum.

LihatMempelajari ArsitekturArm untuk detail lengkap tentang bagian-bagian ABI yang bukan khusus Android. Arm juga menawarkan beberapa saran porting dalamPengembangan Android 64-bit.

Di Android, register x18 khusus platform disediakan untukShadowCallStackdan tidak boleh disentuh oleh kode. Versi Clang saat ini merupakan default untuk menggunakan opsi-ffixed-x18di Android. Kecuali jika Anda memiliki assembler yang ditulis secara manual (atau versi compiler yang sangat lama), Anda tidak perlu khawatir tentang hal ini.

x86

ABI ini ditujukan bagi CPU yang mendukung kumpulan petunjuk yang umumnya dikenal sebagai "x86", "i386", atau "IA-32". Karakteristik ABI ini antara lain:

  • Petunjuk biasanya dihasilkan oleh GCC dengan flag compiler seperti berikut:
    -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32
    

    Flag ini menargetkan kumpulan petunjuk Pentium Pro, beserta ekstensi kumpulan petunjukMMX,SSE,SSE2,SSE3, danSSSE3. Kode yang dihasilkan adalah pengoptimalan yang diseimbangkan di seluruh CPU 32-bit Intel terbaik.

    Untuk mengetahui informasi selengkapnya tentang flag compiler, khususnya yang terkait dengan pengoptimalan performa, lihatPetunjuk performa GCC x86.

  • Gunakan konvensi pemanggilan Linux x86 32-bit standar, bukan yang ditujukan untuk SVR. Untuk mengetahui informasi selengkapnya, lihat bagian 6, "Penggunaan Register", padaKonvensi pemanggilan untuk berbagai compiler C++ dan sistem operasi.

ABI ini tidak mencakup ekstensi kumpulan petunjuk IA-32 opsional lainnya, seperti:

  • MOVBE
  • Semua varian SSE4.

Anda masih dapat menggunakan ekstensi ini asalkan Anda menggunakan pemeriksaan fitur runtime untuk mengaktifkannya, dan menyediakan fallback untuk perangkat yang tidak mendukungnya.

Toolchain NDK mengasumsikan penyelarasan stack 16 byte sebelum panggilan fungsi. Alat dan opsi default menerapkan aturan ini. Jika menulis kode assembly, Anda harus memastikan untuk mempertahankan keselarasan stack, dan memastikan bahwa compiler lain juga mematuhi aturan ini.

Lihat dokumen berikut untuk detail selengkapnya:

x86_64

ABI ini ditujukan untuk CPU yang mendukung kumpulan petunjuk yang umumnya disebut "x86-64". ABI ini mendukung petunjuk yang biasanya dihasilkan oleh GCC dengan flag compiler berikut:

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

Menurut dokumentasi GCC, flag ini menargetkan kumpulan petunjuk x86-64, beserta ekstensi kumpulan petunjukMMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2, dan POPCNT. Kode yang dihasilkan adalah pengoptimalan yang diseimbangkan di seluruh CPU 64-bit Intel terbaik.

Untuk mengetahui informasi selengkapnya tentang flag compiler, khususnya yang terkait dengan pengoptimalan performa, lihatPetunjuk performa GCC x86.

ABI ini tidak mencakup ekstensi kumpulan petunjuk x86-64 opsional lainnya, seperti:

  • MOVBE
  • SHA
  • AVX
  • AVX2

Anda masih dapat menggunakan ekstensi ini asalkan Anda menggunakan pemeriksaan fitur runtime untuk mengaktifkannya, dan menyediakan fallback untuk perangkat yang tidak mendukungnya.

Lihat dokumen berikut untuk detail selengkapnya:

Membuat kode untuk ABI tertentu

Gradlendk-buildCMake

Gradle (baik digunakan melalui Android Studio maupun dari command line) dibuat untuk semua ABI yang masih digunakan secara default. Untuk membatasi kumpulan ABI yang didukung aplikasi Anda, gunakanabiFilters. Misalnya, untuk membuat build bagi ABI 64-bit saja, tetapkan konfigurasi berikut dalambuild.gradleAnda:

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

Secara default, perilaku sistem build menyertakan biner untuk setiap ABI dalam satu APK, yang juga disebutfat APK. Fat APK secara signifikan berukuran lebih besar dari APK yang hanya memuat biner untuk satu ABI. Kompatibilitas yang lebih luas mengorbankan ukuran APK-nya yang menjadi lebih besar. Sebaiknya Anda memanfaatkanApp BundleatauPembagian APKuntuk mengurangi ukuran APK dengan tetap mempertahankan kompatibilitas perangkat yang optimal.

Pada waktu penginstalan, pengelola paket hanya mengekstrak kode mesin yang paling sesuai untuk perangkat target. Untuk detailnya, lihatEkstraksi otomatis kode native pada waktu penginstalan.

Pengelolaan ABI di platform Android

Bagian ini memberikan detail tentang cara platform Android mengelola kode native dalam APK.

Kode native dalam paket aplikasi

Play Store maupun Pengelola Paket akan selalu berupaya menemukan library yang dihasilkan NDK pada jalur file dalam APK yang sesuai dengan pola berikut:

/lib/<abi>/lib<name>.so

Di sini,<abi>adalah salah satu nama ABI yang tercantum dalamABI yang didukung, dan<name>adalah nama library seperti yang Anda tetapkan untuk variabelLOCAL_MODULEdalam fileAndroid.mk. Karena hanya berupa file zip, file APK mudah dibuka untuk mengonfirmasi bahwa library native bersama berada di tempat yang seharusnya.

Jika sistem tidak menemukan library native bersama di tempat yang seharusnya, maka sistem tidak akan dapat menggunakannya. Dalam kasus semacam ini, aplikasi itu sendiri harus menyalin semua library, lalu menjalankandlopen().

Dalam fat APK, setiap library berada di bagian direktori yang namanya cocok dengan ABI yang terkait. Misalnya, fat APK dapat memuat:

/lib/armeabi/libfoo.so
/lib/armeabi-v7a/libfoo.so
/lib/arm64-v8a/libfoo.so
/lib/x86/libfoo.so
/lib/x86_64/libfoo.so

Catatan:Perangkat Android berbasis ARMv7 yang menjalankan 4.0.3 atau yang lebih lama akan menginstal library native dari direktoriarmeabi, bukanarmeabi-v7a, jika kedua direktori tersebut ada. Hal ini dikarenakan/lib/armeabi/ditempatkan setelah/lib/armeabi-v7a/dalam APK. Masalah ini telah diperbaiki sejak versi 4.0.4.

Dukungan ABI platform Android

Sistem Android mengetahui ABI yang didukungnya pada runtime, karena properti sistem khusus build menunjukkan:

  • ABI primer untuk perangkat, yang sesuai dengan kode mesin yang digunakan dalam image sistem itu sendiri.
  • ABI sekunder (opsional), yang sesuai dengan ABI lain yang juga didukung image sistem.

Mekanisme ini memastikan sistem mengekstrak kode mesin terbaik dari paket pada waktu penginstalan.

Untuk performa terbaik, Anda harus mengompilasi secara langsung untuk ABI primer. Misalnya, perangkat berbasis ARMv5TE umum hanya akan menentukan ABI primer:armeabi. Sebaliknya, perangkat berbasis ARMv7 standar akan menentukan ABI primer sebagaiarmeabi-v7adan ABI sekunder sebagaiarmeabi, karena perangkat ini dapat menjalankan biner native aplikasi yang dihasilkan untuk setiap ABI.

Perangkat 64-bit juga mendukung varian 32-bit. Menggunakan perangkat arm64-v8a sebagai contoh, perangkat ini juga dapat menjalankan kode armeabi dan armeabi-v7a. Namun, perlu diketahui bahwa aplikasi akan berperforma jauh lebih baik di perangkat 64-bit jika menargetkan arm64-v8a daripada mengandalkan perangkat yang menjalankan versi armeabi-v7a aplikasi.

Banyak perangkat berbasis x86 juga dapat menjalankan biner NDKarmeabi-v7adanarmeabi. Untuk perangkat tersebut, ABI primernya adalahx86, dan ABI sekundernya adalaharmeabi-v7a.

Anda dapat menginstal otomatis apk untukABItertentu. Hal ini berguna untuk melakukan pengujian. Gunakan perintah berikut:

adb install --abi abi-identifier path_to_apk

Ekstraksi otomatis kode native pada waktu penginstalan

Saat menginstal aplikasi, layanan pengelola paket memindai APK, dan mencari setiap library bersama yang berformat:

lib/<primary-abi>/lib<name>.so

Jika tidak ada yang ditemukan, dan Anda telah menentukan ABI sekunder, layanan akan memindai library bersama yang berformat:

lib/<secondary-abi>/lib<name>.so

Setelah menemukan library yang dicari, pengelola paket akan menyalinnya ke/lib/lib<name>.sodalam direktori library native aplikasi (<nativeLibraryDir>/). Cuplikan berikut akan mengambilnativeLibraryDir:

KotlinJava
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 );

Jika tidak ada file objek bersama, aplikasi akan membuat dan menginstalnya, tetapi akan mengalami error saat runtime.