NDK, birden fazla C++ çalışma zamanı kitaplığını destekler. Bu belgede hakkında bilgi edindiniz.
C++ çalışma zamanı kitaplıkları
Tablo 1. NDK C++ Çalışma Zamanları ve Özellikleri.
Ad | Özellikler |
---|---|
libc++ | Modern C++ desteği. |
sistem | new ve delete . (Sürüm 18'de kullanımdan kaldırıldı.) |
yok | Üstbilgi yok, sınırlı C++. |
libc++ hem statik hem de paylaşılan bir kitaplık olarak kullanılabilir.
libc++
LLVM'nin libc++, C++ standardıdır Lollipop'tan bu yana ve NDK r18'den itibaren Android OS tarafından kullanılan kitaplık NDK'da kullanılabilen tek STL'dir.
CMake, varsayılan olarak C++ clang'ın varsayılan sürümünü kullanır (şu anda C++14),
Dolayısıyla, standart CMAKE_CXX_STANDARD
için uygun değeri ayarlamanız gerekir.
CMakeLists.txt
dosyanızda C++17 veya sonraki özellikleri kullanmak için. CMake'i görüntüleme
CMAKE_CXX_STANDARD
için dokümanlar
inceleyebilirsiniz.
ndk-build, kararı varsayılan olarak yadırmaya bırakır. Bu yüzden kullanıcıları
-std=c++17
veya istediklerini eklemek için APP_CPPFLAGS
öğesini kullanmalıdır.
libc++ için paylaşılan kitaplık libc++_shared.so
ve statik
kitaplığı libc++_static.a
. Normal durumlarda, derleme sistemi
gerektiği gibi kullanma ve paketlemeye olanak sağlar. Tipik durumlar için
veya kendi derleme sisteminizi uygularken bkz. Sistem Bakımı
Kılavuz veya diğer derleme sistemlerini kullanma rehberi.
LLVM Projesi, LLVM İstisnalarıyla birlikte Apache Lisansı 2.0 sürümü kapsamındadır. Daha fazla bilgileri için lisans dosyasına bakın.
sistem
Sistem çalışma zamanı /system/lib/libstdc++.so
anlamına geliyor. Bu kitaplık
GNU'nun tam özellikli libstdc++ ile karıştırılamaz. Android'de, libstdc++
new
ve delete
. Tam özellikli C++ standart kitaplığı için libc++ kullanın.
Sistem C++ çalışma zamanı, temel C++ Çalışma Zamanı ABI'si için destek sağlar.
Bu kitaplık temel olarak new
ve delete
değerini içerir. Diğerinin aksine
seçenekleri mevcut olduğu halde, istisnai işleme veya
RTTI
C için C++ sarmalayıcıları dışında standart kitaplık desteği yoktur.
kitaplık üstbilgilerini (<cstdio>
gibi) kullanabilirsiniz. STL istiyorsanız
seçenekleri sunar.
yok
STL'siz olma seçeneği de vardır. Bağlantı oluşturma veya lisanslama yok şartları yerine getiriyor. C++ standart üstbilgisi yok.
C++ Çalışma Zamanı Seçme
CMake
CMake için varsayılan değer c++_static
'tir.
Şunu kullanarak c++_shared
, c++_static
, none
veya system
belirtebilirsiniz:
Modül düzeyindeki build.gradle
dosyanızda ANDROID_STL
değişkeni var. Daha fazla bilgi edinmek için
ANDROID_STL ile ilgili dokümanları şurada bulabilirsiniz:
CMake.
ndk-kurum
İndk-build için varsayılan değer none
'tir.
Şunu kullanarak c++_shared
, c++_static
, none
veya system
belirtebilirsiniz:
Application.mk dosyanızdaki APP_STL
değişkeni. Örnek:
APP_STL := c++_shared
ndk-build, uygulamanız için yalnızca bir çalışma zamanı seçmenize olanak tanır ve sadece şu koşullarda yapabilir: Application.mk'yi tıklayın.
Clang'i doğrudan kullanın
clang'ı doğrudan kendi derleme sisteminizde kullanıyorsanız clang++,
Varsayılan olarak c++_shared
. Statik varyantı kullanmak için -static-libstdc++
öğesini şuraya ekleyin:
emin olmanız gerekir. Bu seçenek "libstdc++" adını kullansa da şunun için:
Bu, libc++ için de geçerlidir.
Dikkat edilmesi gerekenler
Statik çalışma zamanları
Uygulamanızın yerel kodunun tamamı tek bir paylaşılan statik çalışma zamanını kullanmanızı öneririz. Bu, bağlayıcının şunları yapmasına olanak tanır: satır içi yapın ve kullanılmayan kodu mümkün olduğunca ayıklayın. Böylece, mümkün olan en optimize ve mümkün olan en küçük uygulamada yapılacaklar. Ayrıca PackageManager ve dinamik Android'in eski sürümlerinde, paylaşılan birden fazla öğenin işlenmesini sağlayan bağlayıcı hataları kolay ve hataya açık kitaplıklardır.
Bununla birlikte, C++'ta aynı sayfanın birden fazla kopyasını tanımlamak güvenli değildir. işlev veya nesneyi tek bir programda toplar. Bu, proje yönetiminin C++ standardında bulunan One Definition Rule.
Statik bir çalışma zamanı (ve genel olarak statik kitaplıklar) kullanırken bu kuralı yanlışlıkla çiğnemek zorunda kalırsınız. Örneğin, aşağıdaki uygulama bu sorunu bozuyor kural:
# 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)
Bu durumda, global verileri ve statik oluşturucuları içeren STL, her iki kitaplıkta da bulunur. Bu uygulamanın çalışma zamanı davranışı: tanımlanmamıştır ve pratikte kilitlenmeler çok yaygındır. Diğer olası sorunlar şunlardır:
- Bellek bir kitaplıkta ayrılıp diğerinde serbest bırakılarak belleğe neden oluyor olabilir.
libfoo.so
bölgesinde toplanan istisnalarlibbar.so
içinde yakalanmayacağından kilitlenmesine neden olabilir.std::cout
arabelleğe alma işlevi düzgün çalışmıyor.
Davranışsal sorunların ötesinde, statik çalışma zamanını birden fazla kitaplıklar, paylaşılan her kitaplıkta kodu kopyalar ve bu sayede en iyi yoludur.
Genel olarak, C++ çalışma zamanının statik varyantını yalnızca varsa kullanabilirsiniz. ve uygulamanızda yalnızca bir paylaşılan kitaplık vardır.
Paylaşılan çalışma zamanları
Uygulamanızda birden çok paylaşılan kitaplık varsa
libc++_shared.so
Android'de, NDK tarafından kullanılan libc++, bölümdekiyle aynı değildir
hale getiriyoruz. Bu, NDK kullanıcılarının en son libc++ özelliklerine ve hatasına erişmesini sağlar
düzeltmelerine yer verir. Bunun karşılığında, siz
ya da kendi başınıza
libc++_shared.so
kullanıyorsanız bunu uygulamanıza eklemeniz gerekir. Bir proje için
otomatik olarak işlenir.
Android'in eski sürümlerinde PackageManager ve dinamik bağlayıcıda hatalar vardı
yerel kitaplıkların yüklenmesini, güncellenmesini ve yüklenmesini sağlayan
güvenilmez. Özellikle, uygulamanız daha eski bir Android sürümünü hedefliyorsa
(Android API düzeyi 18) daha güncel ve libc++_shared.so
kullanıyorsanız
paylaşılan kitaplığı, ona bağlı diğer kitaplıklardan önce yüklemelidir.
ReLinker projesinin sunduğu avantajlar bilinen tüm yerel kitaplık yükleme sorunlarına yönelik geçici çözümler ve genellikle kendi geçici çözümlerinizi yazmaktan daha iyi bir seçimdir.
Uygulama başına bir STL
Geçmişte NDK, libc++'a ek olarak GNU libstdc++ ve STLport'u da destekliyordu. Uygulamanız NDK'ya göre derlenmiş önceden oluşturulmuş kitaplıklar kullanıyorsa uygulamanızı oluşturmak için kullanılandan farklı olması durumunda, uyumlu bir şekilde yapmasını sağlar.
Bir uygulama birden fazla C++ çalışma zamanı kullanmamalıdır. Çeşitli STL'ler
birbiriyle uyumlu değildir. Örneğin, std::string
düzeni
libc++, gnustl'daki ile aynı değildir. Tek bir STL'ye karşı yazılan kod
başka bir aleyhine yazılmış nesneleri kullanamayız. Bu sadece bir örnek.
çok sayıda uyumsuzluk vardır.
Bu kuralın kapsamı, kodunuzun ötesine geçiyor. Tüm bağımlılıklarınız aynı Seçtiğiniz STL. Kapalı kaynak bir üçüncü tarafa kullanıyorsanız STL’yi kullanan ve STL başına bir kitaplık sağlamayan bağımlılığınızı STL'de seçim yapabilirsiniz. Bağımlılığınızla aynı STL'yi kullanmanız gerekir.
Birbiriyle uyumsuz olan iki kitaplıktan yararlanmanız mümkündür. İçinde bu durumda tek çözüm bağımlılıklardan birini bırakmak ya da diğer STL'ye göre oluşturulan bir kitaplık sağlamasıdır.
C++ İstisnaları
C++ istisnaları libc++ tarafından desteklenir, ancak ndk-build. Bunun nedeni, eskiden C++ istisnalarının NDK CMake ve bağımsız araç zincirlerinde varsayılan olarak etkinleştirilmiş C++ istisnaları bulunur.
ndk-build'te uygulamanızın tamamında istisnaları etkinleştirmek için Application.mk dosyanıza aşağıdaki satırı ekleyin:
APP_CPPFLAGS := -fexceptions
Tek bir ndk-build modülünde istisnaları etkinleştirmek için aşağıdaki satırı Android.mk içinde belirtilen modül:
LOCAL_CPP_FEATURES := exceptions
Alternatif olarak şunu da kullanabilirsiniz:
LOCAL_CPPFLAGS := -fexceptions
RTTI
İstisnalarda olduğu gibi, RTTI, libc++ tarafından desteklenir ancak ndk-build. CMake ve bağımsız araç zincirlerinde RTTI varsayılan olarak etkindir.
ndk-build'te uygulamanızın tamamında RTTI'yi etkinleştirmek için aşağıdakileri ekleyin: satırını Application.mk dosyanıza kopyalayın:
APP_CPPFLAGS := -frtti
Tek bir ndk-build modülünde RTTI'yı etkinleştirmek için aşağıdaki satırı Android.mk içinde belirtilen modül:
LOCAL_CPP_FEATURES := rtti
Alternatif olarak şunu da kullanabilirsiniz:
LOCAL_CPPFLAGS := -frtti