Manajemen ABI

Handset Android berbeda menggunakan CPU berbeda, yang pada gilirannya mendukung set petunjuk berbeda. Setiap kombinasi set CPU dan petunjuk memiliki Application Binary Interface, atau ABI. ABI mendefinisikan, dengan akurasi sangat bagus, bagaimana seharusnya kode mesin aplikasi berinteraksi dengan sistem pada waktu proses. Anda harus menetapkan ABI untuk setiap arsitektur CPU yang ingin digunakan bersama aplikasi Anda.

Umumnya ABI menyertakan informasi berikut:

  • Set instruksi CPU yang harus digunakan oleh kode mesin.
  • Tingkat endian memori menyimpan dan memuat pada waktu proses.
  • Format biner yang dapat dieksekusi, misalnya program dan pustaka bersama, tipe konten yang didukung.
  • Berbagai konvensi untuk meneruskan data antara kode dan sistem. Konvensi ini berisi batasan penyejajaran, serta bagaimana sistem menggunakan tumpukan dan register saat memanggil fungsi.
  • Daftar simbol fungsi yang tersedia untuk kode mesin Anda pada waktu proses, umumnya dari set pustaka yang sangat spesifik.

Halaman ini menyebutkan ABI yang didukung NDK, dan menyediakan informasi tentang cara kerja setiap ABI. Untuk daftar masalah ABI sistem 32-bit, lihat Bug ABI 32-bit.

ABI yang Didukung

Setiap ABI mendukung satu atau beberapa set petunjuk. Tabel 1 menyediakan ringkasan sekilas dari set petunjuk yang didukung setiap ABI.

Tabel 1. ABI dan set petunjuk yang didukungnya.

ABI Set Petunjuk yang Didukung Catatan
armeabi
  • ARMV5TE dan yang lebih baru
  • Thumb-1
  • Tidak digunakan lagi dalam r16. Dihapus dalam r17. Bukan hard float.
    armeabi-v7a
  • armeabi
  • Thumb-2
  • VFPv3-D16
  • Lainnya, opsional
  • Tidak kompatibel dengan perangkat ARMv5 dan 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 MIPS 32-bit dan 64-bit, tetapi dukungan telah dihapus dalam NDK r17.

    Informasi lebih detail tentang setiap ABI muncul di bawah ini.

    armeabi

    Catatan: ABI ini telah dihapus dalam NDK r17.

    ABI ini adalah untuk CPU berbasis ARM yang setidaknya mendukung set petunjuk ARMv5TE. Lihat dokumentasi berikut untuk detail selengkapnya:

    Standar AAPCS mendefinisikan EABI sebagai keluarga ABI yang serupa tetapi tidak sama. Selain itu, Android mengikuti little-endian ARM GNU/Linux ABI.

    ABI ini tidak mendukung komputasi titik-mengambang yang dibantu perangkat keras. Sebagai gantinya, semua operasi titik-mengambang menggunakan fungsi pembantu perangkat lunak dari pustaka statis libgcc.a pengompilasi.

    ABI armeabi mendukung set petunjuk Thumb ARM (a.k.a. Thumb-1). NDK menghasilkan kode Thumb secara default kecuali Anda menetapkan perilaku yang berbeda menggunakan variabel LOCAL_ARM_MODE dalam file Android.mk Anda.

    armeabi-v7a

    ABI ini memperluas armeabi untuk menyertakan sejumlah Ekstensi set petunjuk CPU. Ekstensi petunjuk yang didukung ABI khusus Android ini adalah:

    • Ekstensi set petunjuk Thumb-2, yang memberikan kinerja yang sebanding dengan petunjuk ARM 32-bit dengan kekompakan serupa dengan Thumb-1.
    • Petunjuk FPU perangkat keras VFP. Lebih spesifik, VFPv3-D16, yang menyertakan 16 register khusus titik-mengambang 64-bit, sebagai tambahan untuk 16 register 32-bit dari inti ARM.

    Ekstensi lainnya yang dijelaskan spesifikasi v7-a ARM, termasuk SIMD Lanjutan (a.k.a. NEON), VFPv3-D32, dan ThumbEE, bersifat opsional pada ABI ini. Karena kehadirannya tidak dijamin, sistem harus memeriksa pada waktu proses apakah ekstensi tersedia. Jika tidak ada, Anda harus menggunakan jalur kode alternatif. Pemeriksaan ini serupa dengan yang biasanya dilakukan sistem untuk memeriksa atau menggunakan set petunjuk MMX, SSE2, dan set petunjuk khusus lainnya di CPU x86.

    Untuk informasi tentang cara melakukan pemeriksaan waktu proses ini, lihat cpufeatures Pustaka. Selain itu, untuk informasi tentang dukungan NDK untuk membangun kode mesin untuk NEON, lihat Dukungan NEON.

    ABI armeabi-v7a menggunakan switch -mfloat-abi=softfp untuk untuk memberlakukan aturan bahwa compiler harus meneruskan semua nilai ganda dalam pasangan register inti selama panggilan fungsi, sebagai ganti register titik-mengambang yang dikhususkan. Sistem bisa melakukan semua komputasi internal menggunakan register titik-mengambang. Hal itu akan sangat mempercepat komputasi.

    arm64-v8a

    ABI ini adalah untuk CPU berbasis ARMv8 yang mendukung AArch64. Juga menyertakan set petunjuk NEON dan VFPv4.

    Untuk informasi selengkapnya, lihat ARMv8 Technology Preview, dan hubungi ARM untuk detail lebih lanjut.

    x86

    ABI ini adalah untuk CPU yang mendukung set petunjuk yang biasanya disebut dengan "x86" atau "IA-32". Karakteristik ABI ini antara lain:

    • Petunjuk biasanya dihasilkan oleh GCC dengan bendera pengompilasi misalnya seperti berikut ini:
      -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32
      

      Semua bendera ini menargetkan set petunjuk Pentium Pro, bersama ekstensi set petunjuk MMX, SSE, SSE2, SSE3, dan SSSE3. Kode yang dihasilkan adalah optimalisasi yang diseimbangkan ke seluruh CPU 32-bit Intel teratas.

      Untuk informasi selengkapnya mengenai bendera pengompilasi, terutama yang berkaitan dengan optimalisasi kinerja, lihat petunjuk kinerja x86.

    • Gunakan konvensi pemanggilan x86 32-bit Linux standar, sebagai lawan dari konvensi untuk SVR. Untuk informasi selengkapnya, lihat bagian 6, "Penggunaan Register", pada Konvensi pemanggilan untuk pengompilasi C++ dan sistem operasi yang berbeda.

    ABI tidak menyertakan ekstensi set petunjuk IA-32 opsional lainnya, misalnya:

    • MOVBE
    • Semua varian SSE4.

    Anda tetap bisa menggunakan semua ekstensi ini, asal menggunakan pendeteksian fitur waktu proses untuk mengaktifkannya, dan menyediakan fallback bagi perangkat yang tidak mendukungnya.

    Rantai alat NDK mengasumsikan penyelarasan tumpukan 16-byte sebelum panggilan fungsi. Alat dan opsi default akan memberlakukan aturan ini. Jika Anda sedang menulis kode assembly, Anda harus memastikan menjaga keselarasan tumpukan, dan memastikan bahwa pengompilasi lain juga mematuhi aturan ini.

    Lihat dokumen berikut untuk detail selengkapnya:

    x86_64

    ABI ini adalah untuk CPU yang mendukung set petunjuk yang biasanya disebut dengan "x86-64". ABI ini mendukung petunjuk yang biasanya dihasilkan GCC dengan bendera pengompilasi berikut:

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

    Bendera ini menargetkan set petunjuk x86-64, menurut dokumentasi GCC. bersama dengan ekstensi set petunjuk MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, dan POPCNT . Kode yang dihasilkan adalah optimalisasi yang diseimbangkan ke seluruh CPU 64-bit Intel teratas.

    Untuk informasi selengkapnya mengenai bendera pengompilasi, terutama yang berkaitan dengan optimalisasi kinerja, lihat Kinerja GCC x86.

    ABI ini tidak menyertakan ekstensi set petunjuk x86-64 opsional lainnya, misalnya:

    • MOVBE
    • SHA
    • AVX
    • AVX2

    Anda tetap bisa menggunakan semua ekstensi ini, asal menggunakan pendeteksian fitur waktu proses untuk mengaktifkannya, dan menyediakan fallback bagi perangkat yang tidak mendukungnya.

    Lihat dokumen berikut untuk detail selengkapnya:

    Menghasilkan Kode untuk ABI Tertentu

    Secara default, NDK menargetkan untuk semua ABI tidak usang. Anda dapat menargetkan ABI tunggal dengan menetapkan APP_ABI dalam file Application.mk. Cuplikan berikut memperlihatkan beberapa contoh penggunaan 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.
    

    Untuk informasi selengkapnya mengenai nilai yang bisa Anda tetapkan untuk APP_ABI, lihat Application.mk.

    Perilaku default dari sistem build adalah menyertakan biner untuk setiap ABI dalam APK tunggal, juga dikenal sebagai APK gemuk. APK gemuk lebih besar dari biner yang hanya berisi kode mesin untuk sistem tunggal; konsekuensinya adalah menghasilkan kompatibilitas lebih luas, tetapi mengakibatkan APK jadi lebih besar. Sebaiknya Anda memanfaatkan APK terpisah untuk mengurangi ukuran APKs sambil tetap mempertahankan kompatibilitas perangkat maksimum.

    Pada waktu penginstalan, manajer paket hanya membongkar kode mesin paling tepat untuk perangkat target. Untuk detailnya, lihat Ekstraksi otomatis kode asli pada waktu penginstalan.

    Manajemen ABI di Platform Android

    Bagian ini menyediakan detail tentang cara platform Android mengelola kode asli dalam APK.

    Kode asli dalam paket aplikasi

    Baik Play Store maupun Package Manager berharap menemukan pustaka yang dihasilkan NDK pada jalur file di dalam APK yang cocok dengan pola berikut:

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

    Di sini, <abi> adalah salah satu nama ABI yang dicantumkan di ABI yang didukung, dan <name> adalah nama pustaka yang Anda definisikan untuk LOCAL_MODULE variabel dalam file Android.mk. Karena file APK cuma file zip, maka merupakan hal sepele membukanya dan memastikannya berada di pustaka asli bersama.

    Jika sistem tidak menemukan pustaka bersama asli di tempat ia diharapkan berada, maka ia tidak bisa digunakan. Dalam hal demikian, aplikasi itu sendiri harus menyalin pustaka berkali-kali, kemudian melakukan dlopen().

    Dalam APK gemuk, setiap pustaka berada di direktori yang namanya cocok dengan ABI yang sesuai. Misalnya, APK gemuk dapat berisi:

    /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 sebelumnya akan menginstal pustaka asli dari direktori armeabi sebagai ganti direktori armeabi-v7a jika kedua direktori ada. Ini karena /lib/armeabi/ mengikuti /lib/armeabi-v7a/ di APK. Masalah ini telah diperbaiki dari 4.0.4.

    Dukungan ABI Platform Android

    Sistem Android mengetahui pada waktu proses ABI mana yang didukungnya, karena properti sistem khusus pembangunan akan menunjukkan:

    • ABI utama untuk perangkat, sesuai dengan kode mesin yang digunakan dalam citra sistem itu sendiri.
    • Secara opsional, ABI kedua, sesuai dengan ABI lain yang juga didukung citra sistem.

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

    Untuk mendapatkan kinerja terbaik, Anda harus mengompilasi langsung untuk ABI utama. Misalnya, perangkat berbasis ARMv5TE umumnya hanya akan mendefinisikan ABI utama: armeabi. Sebaliknya, perangkat berbasis ARMv7 umumnya akan mendefinisikan ABI utama sebagai armeabi-v7a dan ABI sekunder sebagai armeabi, karena ini bisa menjalankan biner asli aplikasi yang dihasilkan untuk masing-masing perangkat.

    Perangkat 64-bit juga mendukung varian 32-bit. Menggunakan perangkat arm64-v8a sebagai contoh, perangkat juga bisa menjalankan kode armeabi dan armeabi-v7a. Catatan, tetapi, aplikasi Anda akan berjalan jauh lebih baik di perangkat 64-bit jika menargetkan arm64-v8a daripada mengandalkan perangkat yang menjalankan versi armeabi-v7a dari aplikasi.

    Banyak perangkat keras berbasis x86 yang juga bisa menjalankan biner NDK armeabi-v7a dan armeabi. Untuk perangkat tersebut, ABI utama akan menjadi x86, dan yang kedua, armeabi-v7a.

    Ekstraksi otomatis kode asli pada waktu penginstalan

    Saat menginstal aplikasi, layanan manajer paket akan memindai APK, dan mencari pustaka bersama yang berbentuk:

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

    Jika tidak ada yang ditemukan, dan Anda telah mendefinisikan ABI sekunder, layanan tersebut akan memindai pustaka bersama yang berbentuk:

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

    Bila menemukan pustaka yang dicarinya, Package Manager akan menyalinnya ke /lib/lib<name>.so, pada direktori data aplikasi (data/data/<package_name>/lib/).

    Jika sama sekali tidak ada file objek bersama, aplikasi pembangunan akan terbuat dan terinstal, tetapi akan mogok pada waktu proses.