Unterstützung von C++-Bibliotheken

Das NDK unterstützt mehrere C++-Laufzeitbibliotheken. Dieses Dokument enthält Informationen zu diesen Bibliotheken, den jeweiligen Vor- und Nachteilen und ihrer Verwendung.

C++-Laufzeitbibliotheken

Tabelle 1 NDK C++ Laufzeiten und Features.

Name Funktionen
libc++ Moderne C++-Unterstützung.
system new und delete. (in r18 eingestellt.)
Keine Keine Header, eingeschränkte C++.

libc++ ist sowohl als statische als auch als gemeinsam genutzte Bibliothek verfügbar.

libc++

libc++ von LLVM ist der C++-Standard. Bibliothek, die seit Lollipop im Android-Betriebssystem und seit NDK r18 verwendet wird. ist die einzige im NDK verfügbare STL-Datei.

CMake verwendet standardmäßig die Version des C++ Clang, die standardmäßig verwendet wird (derzeit C++14), Sie müssen also den standardmäßigen CMAKE_CXX_STANDARD auf den entsprechenden Wert in der Datei CMakeLists.txt, um Funktionen in C++17 oder höher zu verwenden. CMake ansehen Dokumentation für CMAKE_CXX_STANDARD .

ndk-build lässt die Entscheidung auch standardmäßig über Clang, sodass ndk-build-Nutzer sollte APP_CPPFLAGS verwenden, um stattdessen -std=c++17 oder einen beliebigen anderen Ort hinzuzufügen.

Die gemeinsam genutzte Bibliothek für libc++ ist libc++_shared.so und die statische Bibliothek ist libc++_static.a. In der Regel übernimmt das Build-System und verpacken diese Bibliotheken nach Bedarf für den Nutzer. Atypische Fälle oder wenn Sie Ihr eigenes Build-System implementieren, lesen Sie den Artikel Build System Verwalter Leitfaden oder die Anleitung zur Verwendung anderer Build-Systeme

Das LLVM-Projekt unterliegt der Apache-Lizenz v2.0 mit LLVM-Ausnahmen. Weitere Informationen finden Sie in der Lizenzdatei.

Infotainmentsystem

Die Systemlaufzeit bezieht sich auf /system/lib/libstdc++.so. Diese Bibliothek sollte mit dem voll funktionsfähigen libstdc++ von GNU verwechselt werden. Unter Android ist libstdc++ einfach new und delete. Verwenden Sie libc++ für eine voll funktionsfähige C++-Standardbibliothek.

Die Systemlaufzeit von C++ bietet Unterstützung für die grundlegende C++-Laufzeit-ABI. Im Wesentlichen stellt diese Bibliothek new und delete bereit. Im Gegensatz zu den anderen Optionen im NDK verfügbar sind, wird die Ausnahmebehandlung oder RTTI.

Abgesehen von den C++-Wrappern für das C++-Format wird keine Standardbibliothek unterstützt. Bibliotheksheader wie <cstdio>. Wenn Sie STL verwenden möchten, sollten Sie eine der die anderen Optionen auf dieser Seite.

Keine

Es gibt auch die Option, keine STL-Dateien zu verwenden. Es gibt keine Verknüpfungen oder Lizenzierungen Anforderungen erfüllt. Es sind keine C++-Standardheader verfügbar.

C++-Laufzeit auswählen

CMake

Der Standardwert für CMake ist c++_static.

Sie können c++_shared, c++_static, none oder system mithilfe der ANDROID_STL in die Datei build.gradle auf Modulebene ein. Weitere Informationen finden Sie in der Dokumentation zu ANDROID_STL unter CMake.

NK-Build

Der Standardwert für ndk-build ist none.

Sie können c++_shared, c++_static, none oder system mithilfe der APP_STL in die Datei Application.mk ein. Beispiel:

APP_STL := c++_shared

Mit „ndk-build“ können Sie nur eine Laufzeit für Ihre App auswählen. Dies funktioniert nur in Application.mk aus.

Clang direkt verwenden

Wenn Sie Clang direkt in Ihrem eigenen Build-System verwenden, verwendet clang++ Standardmäßig c++_shared. Wenn Sie die statische Variante verwenden möchten, fügen Sie -static-libstdc++ zu Ihre Verknüpfungs-Flags. Beachten Sie, dass die Option zwar den Namen "libstdc++" für aus historischen Gründen gilt, gilt dies auch für libc++.

Wichtige Hinweise

Statische Laufzeiten

Wenn der gesamte native Code Ihrer Anwendung in einem einzigen freigegebenen empfehlen wir die Verwendung der statischen Laufzeit. Dadurch kann die Verknüpfung und entfernen Sie möglichst viel ungenutzten Code. Dies führt zu einem optimierten und der kleinsten Anwendung. Außerdem werden PackageManager und dynamische Verknüpfungsfehler in alten Android-Versionen, die die Handhabung mehrerer gemeinsam genutzter schwierig und fehleranfällig.

In C++ ist es jedoch nicht sicher, mehr als eine Kopie derselben oder Objekt in einem einzelnen Programm verwenden. Dies ist ein Aspekt des Eine Definitionsregel, die im C++-Standard enthalten ist.

Wenn Sie eine statische Laufzeit (und statische Bibliotheken im Allgemeinen) verwenden, ist es einfach, gegen diese Regel verstoßen. Die folgende Anwendung unterbricht beispielsweise Regel:

# 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)

In dieser Situation hat die STL-Datei einschließlich der globalen Daten und statischen Konstruktoren in beiden Bibliotheken vorhanden ist. Das Laufzeitverhalten dieser Anwendung ist nicht definiert, und in der Praxis treten Abstürze sehr häufig auf. Andere mögliche Probleme umfassen:

  • Arbeitsspeicher, der in einer Bibliothek zugewiesen und in der anderen freigegeben wurde, was zu Arbeitsspeicher führt oder Heap-Beschädigungen.
  • In libfoo.so ausgelöste Ausnahmen, die in libbar.so nicht abgefangen werden, verursachen App abgestürzt.
  • Die Zwischenspeicherung von std::cout funktioniert nicht richtig.

Abgesehen von den damit verbundenen Verhaltensproblemen kann die Verknüpfung der statischen Laufzeit mit mehreren wird der Code in jeder gemeinsam genutzten Bibliothek dupliziert, wodurch die Größe der Ihre Anwendung.

Im Allgemeinen können Sie nur dann eine statische Variante der C++-Laufzeit verwenden, wenn Sie eine haben und nur eine gemeinsam genutzte Bibliothek in Ihrer Anwendung.

Freigegebene Laufzeiten

Wenn Ihre Anwendung mehrere gemeinsam genutzte Bibliotheken enthält, sollten Sie libc++_shared.so

Unter Android ist die vom NDK verwendete libc++ nicht dieselbe wie die, die Teil der Datei ist. des Betriebssystems. Dadurch erhalten NDK-Nutzer Zugriff auf die neuesten libc++-Funktionen und Fehler auch bei älteren Android-Versionen behoben werden. Wenn Sie jedoch libc++_shared.so verwenden, müssen Sie es in Ihre App aufnehmen. Wenn Sie Ihre eigene Mit Gradle erfolgt dies automatisch.

Bei alten Android-Versionen traten Fehler im PackageManager und im Dynamic Linker auf führten dazu, dass die Installation, Aktualisierung und das Laden nativer Bibliotheken unzuverlässig werden. Wenn Ihre App auf eine frühere Android-Version als Android 4.3 (Android API-Level 18) und Sie libc++_shared.so verwenden, muss die gemeinsam genutzte Bibliothek vor jeder anderen davon abhängigen Bibliothek geladen werden.

Das Projekt ReLinker bietet Behelfslösungen für alle bekannten Probleme beim Laden nativer Bibliotheken. eine bessere Wahl, als eigene Behelfslösungen zu schreiben.

Eine STL pro App

In der Vergangenheit unterstützte das NDK neben libc++ auch GNU libstdc++ und STLport. Wenn Ihre Anwendung von vordefinierten Bibliotheken abhängt, die für ein NDK erstellt wurden als die, mit der Ihre App erstellt wurde, müssen Sie sicherstellen, dass dies auf kompatible Weise geschieht.

Eine Anwendung sollte nicht mehr als eine C++-Laufzeit verwenden. Die verschiedenen STLs sind nicht miteinander kompatibel. Beispiel: Das Layout von std::string in libc++ ist nicht dasselbe wie in gnustl. Bei Code, der für ein STL geschrieben wird, keine Objekte verwenden können, die gegen ein anderes geschrieben wurden. Dies ist nur ein Beispiel: Es gibt zahlreiche Inkompatibilitäten.

Diese Regel geht über Ihren Code hinaus. Alle Abhängigkeiten müssen die gleiche die ausgewählte STL-Datei. Wenn Sie von einem Closed-Source-Drittanbieter abhängig sind die STL verwendet und keine Bibliothek pro STL zur Verfügung stellt, haben die Wahl in STL. Sie müssen dieselbe STL-Datei wie Ihre Abhängigkeit verwenden.

Es ist möglich, dass Sie von zwei sich gegenseitig inkompatiblen Bibliotheken abhängig sind. In In dieser Situation besteht die einzige Lösung darin, eine der Abhängigkeiten zu entfernen oder für die Bereitstellung einer Bibliothek, die parallel zur anderen STL-Datei erstellt wurde.

C++ Ausnahmen

C++-Ausnahmen werden von libc++ unterstützt, sind aber in „ndk-build“. Das liegt daran, dass in der Vergangenheit keine C++-Ausnahmen in der NDK Für CMake- und eigenständige Toolchains sind C++-Ausnahmen standardmäßig aktiviert.

Um Ausnahmen für Ihre gesamte Anwendung in "ndk-build" zu aktivieren, fügen Sie den Parameter folgende Zeile in die Datei Application.mk ein:

APP_CPPFLAGS := -fexceptions

Um Ausnahmen für ein einzelnes ndk-build-Modul zu aktivieren, fügen Sie folgende Zeile zu Modul in seiner Android.mk-Datei:

LOCAL_CPP_FEATURES := exceptions

Alternativ können Sie auch Folgendes verwenden:

LOCAL_CPPFLAGS := -fexceptions

RTTI

Wie mit Ausnahmen wird RTTI von libc++ unterstützt, ist aber in „ndk-build“. Für CMake- und eigenständige Toolchains ist RTTI standardmäßig aktiviert.

Um RTTI in Ihrer gesamten Anwendung in ndk-build zu aktivieren, fügen Sie Folgendes hinzu: in die Datei Application.mk ein:

APP_CPPFLAGS := -frtti

Um RTTI für ein einzelnes ndk-build-Modul zu aktivieren, fügen Sie die folgende Zeile zur Modul in seiner Android.mk-Datei enthält:

LOCAL_CPP_FEATURES := rtti

Alternativ können Sie auch Folgendes verwenden:

LOCAL_CPPFLAGS := -frtti