C++ kitaplığı desteği

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 istisnalar libbar.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