NDK mendukung beberapa library runtime C++. Dokumen ini memberikan informasi tentang library ini, konsekuensi yang terlibat, dan cara menggunakannya.
Library runtime C++
Tabel 1. Runtime dan Fitur C++ NDK.
Nama | Fitur |
---|---|
libc++ | Dukungan C ++ modern. |
system | new dan delete . (Tidak digunakan lagi di r18.) |
none | Tanpa header, C++ terbatas. |
libc++ tersedia sebagai library statis dan bersama.
libc++
libc++ LLVM adalah library standar C++ yang telah digunakan oleh Android OS sejak versi Lollipop. Mulai dari NDK r18, library ini merupakan satu-satunya STL yang tersedia di NDK.
CMake secara default disetel ke versi C++ apa pun yang menjadi default untuk clang (saat ini C++ 14),
jadi Anda harus menyetel CMAKE_CXX_STANDARD
standar ke nilai yang sesuai
dalam file CMakeLists.txt
untuk menggunakan fitur C++ 17 atau yang lebih baru. Lihat
dokumentasi CMAKE_CXX_STANDARD
CMake
untuk melihat detail selengkapnya.
ndk-build juga menyerahkan keputusan kepada clang secara default, sehingga pengguna ndk-build
harus menggunakan APP_CPPFLAGS
untuk menambahkan -std=c++17
atau apa pun yang mereka inginkan.
Library bersama untuk libc++ adalah libc++_shared.so
, dan library
statisnya adalah libc++_static.a
. Biasanya, sistem build akan menangani
penggunaan dan pemaketan library ini sesuai kebutuhan pengguna. Untuk kasus yang tidak biasa
atau saat mengimplementasikan sistem build Anda sendiri, lihat Panduan Pengelola
Sistem Build atau panduan untuk menggunakan sistem build lainnya.
Project LLVM berada di bawah Lisensi Apache v2.0 dengan Pengecualian LLVM. Untuk mengetahui informasi selengkapnya, lihat file lisensi.
sistem
Runtime sistem mengacu pada /system/lib/libstdc++.so
. Library ini tidak sama
dengan libstdc++ GNU yang berfitur lengkap. Di Android, libstdc++ hanyalah
new
dan delete
. Gunakan libc++ untuk library standar C++ berfitur lengkap.
Runtime C++ sistem memberikan dukungan untuk ABI Runtime C++ dasar.
Pada dasarnya, library ini menyediakan new
dan delete
. Tidak seperti opsi lain
yang tersedia di NDK, tidak ada dukungan untuk penanganan pengecualian atau
RTTI.
Tidak ada dukungan library standar selain wrapper C++ untuk header library C
seperti <cstdio>
. Jika menginginkan STL, Anda harus menggunakan salah satu opsi lain
yang ditampilkan di halaman ini.
none
Anda juga diperbolehkan untuk tidak memiliki STL. Tidak ada persyaratan penautan atau pemberian lisensi dalam situasi tersebut. Tidak ada header C++ standar yang tersedia.
Memilih Runtime C++
CMake
Default untuk CMake adalah c++_static
.
Anda dapat menentukan c++_shared
, c++_static
, none
, atau system
menggunakan
variabel ANDROID_STL
dalam file build.gradle
level modul. Untuk mempelajari lebih lanjut,
lihat dokumentasi ANDROID_STL di
CMake.
ndk-build
Default untuk ndk-build adalah none
.
Anda dapat menentukan c++_shared
, c++_static
, none
, atau system
menggunakan
variabel APP_STL
dalam file Application.mk. Contoh:
APP_STL := c++_shared
ndk-build hanya memungkinkan Anda memilih satu runtime untuk aplikasi, dan hanya dapat dilakukan di Application.mk.
Menggunakan clang secara langsung
Jika Anda menggunakan clang secara langsung di sistem build sendiri, clang++ akan menggunakan
c++_shared
secara default. Untuk menggunakan varian statis, tambahkan -static-libstdc++
ke
flag linker. Perlu diketahui bahwa meskipun opsi tersebut menggunakan nama "libstdc++" untuk
alasan historis, ini juga berlaku untuk libc++.
Pertimbangan penting
Runtime statis
Jika semua kode native aplikasi Anda termuat dalam satu library bersama, kami merekomendasikan penggunaan runtime statis. Hal ini memungkinkan linker untuk menyejajarkan dan memangkas sebanyak mungkin kode yang tidak terpakai, sehingga menghasilkan aplikasi yang paling optimal dan paling kecil. Hal ini juga menghindari bug linker dinamis dan PackageManager di Android versi lama yang mengakibatkan penanganan beberapa library bersama menjadi sulit dan rentan error.
Meskipun demikian, dalam C++, sebaiknya jangan tentukan lebih dari satu salinan fungsi atau objek yang sama ke dalam satu program. Ini adalah salah satu aspek dari Satu Aturan Definisi yang ada dalam standar C++.
Saat menggunakan runtime statis (dan library statis secara umum), aturan ini rentan dilanggar secara tidak sengaja. Misalnya, aplikasi berikut melanggar aturan ini:
# Application.mk
APP_STL := c++_static
# Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.cpp
LOCAL_SHARED_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)
Dalam situasi ini, data STL, include, dan global serta konstruktor statis, akan ada di kedua library. Perilaku runtime aplikasi ini tidak ditentukan dan, pada praktiknya, error sangat biasa terjadi. Masalah lain yang mungkin terjadi termasuk:
- Memori dialokasikan di satu library dan dibebaskan di library lainnya sehingga mengakibatkan kebocoran memori atau kerusakan heap.
- Pengecualian yang muncul di
libfoo.so
tidak terdeteksi dilibbar.so
sehingga akan menyebabkan aplikasi Anda berhenti bekerja. - Buffering
std::cout
tidak berfungsi sebagaimana mestinya.
Di luar masalah perilaku yang terkait, menautkan runtime statis ke beberapa library akan menduplikatkan kode di setiap library bersama sehingga ukuran aplikasi akan bertambah.
Secara umum, Anda hanya dapat menggunakan varian statis runtime C++ jika Anda hanya memiliki satu library bersama di aplikasi Anda.
Runtime bersama
Jika aplikasi Anda menyertakan beberapa library bersama, Anda harus menggunakan
libc++_shared.so
.
Di Android, libc++ yang digunakan oleh NDK tidak sama dengan libc++ yang merupakan bagian
dari OS. Hal ini memungkinkan pengguna NDK mengakses fitur dan perbaikan
bug libc++ terbaru, meskipun menargetkan versi lama Android. Sebagai konsekuensinya, jika Anda
menggunakan libc++_shared.so
, Anda harus menyertakannya dalam aplikasi Anda. Jika Anda mem-build aplikasi
dengan Gradle, library ini akan ditangani secara otomatis.
Versi lama Android memiliki bug dalam PackageManager dan linker dinamis
yang menyebabkan penginstalan, update, dan pemuatan library native menjadi
tidak berfungsi sebagaimana mestinya. Secara khusus, jika aplikasi menargetkan versi Android yang lebih lama
dari Android 4.3 (Android API level 18), dan Anda menggunakan libc++_shared.so
, library
bersama harus dimuat terlebih dahulu sebelum library lain yang bergantung padanya.
Project ReLinker menawarkan solusi untuk semua masalah umum pemuatan library native, dan biasanya merupakan pilihan yang lebih baik daripada menulis solusi sendiri.
Satu STL per aplikasi
Secara historis, selain mendukung libc++, NDK juga mendukung STLport dan libstdc++ GNU. Jika aplikasi Anda bergantung pada library bawaan yang dibangun berdasarkan NDK berbeda dengan yang digunakan untuk membangun aplikasi, Anda harus memastikan bahwa aplikasi dapat melakukannya dalam cara yang kompatibel.
Sebuah aplikasi tidak boleh menggunakan lebih dari satu runtime C++. Beberapa STL
tidak kompatibel satu sama lain. Sebagai contoh, tata letak std::string
dalam libc++ tidak sama dengan tata letak di gnustl. Kode yang ditulis berdasarkan satu STL tidak akan
dapat menggunakan objek yang ditulis berdasarkan STL lain. Contoh ini hanyalah satu dari
banyak ketidakcocokan lainnya.
Aturan ini melampaui kode Anda. Semua dependensi Anda harus menggunakan STL yang sama dengan yang Anda pilih. Jika bergantung pada dependensi closed source pihak ketiga yang menggunakan STL dan Anda tidak menyediakan satu library per STL, Anda tidak memiliki pilihan dalam STL. Anda harus menggunakan STL yang sama dengan dependensi Anda.
Anda mungkin akan bergantung pada dua library yang tidak kompatibel satu sama lain. Dalam situasi ini, satu-satunya solusi adalah dengan melepaskan salah satu dependensi atau meminta pengelola untuk menyediakan library yang dibuat berdasarkan STL lainnya.
Pengecualian C++
Pengecualian C++ didukung oleh libc++, tetapi dinonaktifkan secara default di ndk-build. Hal ini dikarenakan pengecualian C++ biasanya tidak tersedia di NDK. Pengecualian C++ diaktifkan secara default untuk CMake dan toolchain mandiri.
Untuk mengaktifkan pengecualian di seluruh aplikasi di ndk-build, tambahkan baris berikut ke file Application.mk:
APP_CPPFLAGS := -fexceptions
Untuk mengaktifkan pengecualian bagi satu modul ndk-build, tambahkan baris berikut ke Android.mk modul yang dimaksud:
LOCAL_CPP_FEATURES := exceptions
Atau, Anda dapat menggunakan:
LOCAL_CPPFLAGS := -fexceptions
RTTI
Seperti halnya pengecualian, RTTI didukung oleh libc++, tetapi dinonaktifkan secara default di ndk-build. CMake dan toolchain mandiri mengaktifkan RTTI secara default.
Untuk mengaktifkan RTTI di seluruh aplikasi di ndk-build, tambahkan baris berikut ke file Application.mk:
APP_CPPFLAGS := -frtti
Untuk mengaktifkan RTTI bagi satu modul ndk-build, tambahkan baris berikut ke Android.mk modul yang dimaksud:
LOCAL_CPP_FEATURES := rtti
Atau, Anda dapat menggunakan:
LOCAL_CPPFLAGS := -frtti