Ab Android 8.1 ist im Build-System die VNDK-Unterstützung integriert. Wenn die VNDK-Unterstützung aktiviert ist, prüft das Build-System die Abhängigkeiten zwischen den Modulen, erstellt eine anbieterspezifische Variante für Anbietermodule und installiert diese Module automatisch in den angegebenen Verzeichnissen.
Beispiel für VNDK-Build-Unterstützung
In diesem Beispiel wird in der Moduldefinition Android.bp
eine Bibliothek mit dem Namen libexample
definiert. Das Attribut vendor_available
gibt an, von welchen libexample
-Elementen Framework- und Anbietermodule abhängen können:
Abbildung 1
Sowohl die Framework-Ausführbare /system/bin/foo
als auch die Anbieter-Ausführbare /vendor/bin/bar
hängen von libexample
ab und haben libexample
in ihren shared_libs
-Properties.
Wenn libexample
sowohl von Framework- als auch von Anbietermodulen verwendet wird, werden zwei Varianten von libexample
erstellt. Die Kernvariante (benannt nach libexample
) wird von Framework-Modulen verwendet und die Anbietervariante (benannt nach libexample.vendor
) wird von Anbietermodulen verwendet. Die beiden Varianten werden in verschiedenen Verzeichnissen installiert:
- Die Kernvariante wird in
/system/lib[64]/libexample.so
installiert. - Die Anbietervariante wird in VNDK APEX installiert, da
vndk.enabled
true
ist.
Weitere Informationen finden Sie unter Moduldefinition.
Build-Support konfigurieren
Wenn Sie die Unterstützung für vollständige Build-Systeme für ein Produktgerät aktivieren möchten, fügen Sie BOARD_VNDK_VERSION
zu BoardConfig.mk
hinzu:
BOARD_VNDK_VERSION := current
Diese Einstellung hat eine globale Wirkung: Wenn sie in BoardConfig.mk
definiert ist, werden alle Module geprüft. Da es keinen Mechanismus gibt, ein fehlerhaftes Modul auf die Sperrliste zu setzen oder auf die Zulassungsliste zu setzen, sollten Sie alle nicht erforderlichen Abhängigkeiten entfernen, bevor Sie BOARD_VNDK_VERSION
hinzufügen. Sie können ein Modul testen und kompilieren, indem Sie BOARD_VNDK_VERSION
in Ihren Umgebungsvariablen festlegen:
$ BOARD_VNDK_VERSION=current m module_name.vendor
Wenn BOARD_VNDK_VERSION
aktiviert ist, werden mehrere standardmäßige globale Header-Suchpfade entfernt. Dazu gehören:
frameworks/av/include
frameworks/native/include
frameworks/native/opengl/include
hardware/libhardware/include
hardware/libhardware_legacy/include
hardware/ril/include
libnativehelper/include
libnativehelper/include_deprecated
system/core/include
system/media/audio/include
Wenn ein Modul von den Headern aus diesen Verzeichnissen abhängt, müssen Sie die Abhängigkeiten explizit mit header_libs
, static_libs
und/oder shared_libs
angeben.
VNDK APEX
Unter Android 10 und niedriger wurden Module mit vndk.enabled
in /system/lib[64]/vndk[-sp]-${VER}
installiert. Unter Android 11 und höher werden VNDK-Bibliotheken im APEX-Format verpackt. Der Name der VNDK-APEX-Datei lautet com.android.vndk.v${VER}
. Je nach Gerätekonfiguration ist VNDK APEX zusammengefaltet oder nicht zusammengefaltet und über den kanonischen Pfad /apex/com.android.vndk.v${VER}
verfügbar.
Abbildung 2: VNDK APEX.
Moduldefinition
Wenn Sie Android mit BOARD_VNDK_VERSION
erstellen möchten, müssen Sie die Moduldefinition in Android.mk
oder Android.bp
überarbeiten. In diesem Abschnitt werden verschiedene Arten von Moduldefinitionen, mehrere VNDK-bezogene Moduleigenschaften und Abhängigkeitsprüfungen beschrieben, die im Build-System implementiert sind.
Anbietermodule
Anbietermodule sind anbieterspezifische ausführbare Dateien oder freigegebene Bibliotheken, die in einer Anbieterpartition installiert werden müssen. In Android.bp
-Dateien müssen Anbietermodule die Anbieter- oder proprietäre Property auf true
festlegen.
In Android.mk
-Dateien müssen Anbietermodule LOCAL_VENDOR_MODULE
oder LOCAL_PROPRIETARY_MODULE
auf true
setzen.
Wenn BOARD_VNDK_VERSION
definiert ist, erlaubt das Build-System keine Abhängigkeiten zwischen Anbietermodulen und Framework-Modulen und gibt Fehler aus, wenn:
- ein Modul ohne
vendor:true
von einem Modul mitvendor:true
abhängt oder - ein Modul mit
vendor:true
von einem Nicht-llndk_library
-Modul abhängt, das wedervendor:true
nochvendor_available:true
hat.
Die Abhängigkeitsprüfung gilt für header_libs
, static_libs
und shared_libs
in Android.bp
sowie für LOCAL_HEADER_LIBRARIES
, LOCAL_STATIC_LIBRARIES
und LOCAL_SHARED_LIBRARIES
in Android.mk
.
LL-NDK
LL-NDK-Bibliotheken sind gemeinsam genutzte Bibliotheken mit stabilen ABIs. Sowohl Framework- als auch Anbietermodule verwenden dieselbe und die neueste Implementierung. Für jede freigegebene LL-NDK-Bibliothek enthält die cc_library
eine llndk
-Property mit einer Symboldatei:
cc_library { name: "libvndksupport", llndk: { symbol_file: "libvndksupport.map.txt", }, }
Die Symboldatei beschreibt die Symbole, die für Anbietermodule sichtbar sind. Beispiel:
LIBVNDKSUPPORT { global: android_load_sphal_library; # llndk android_unload_sphal_library; # llndk local: *; };
Basierend auf der Symboldatei generiert das Build-System eine Stub-Bibliothek für Anbietermodule, die mit diesen Bibliotheken verknüpft wird, wenn BOARD_VNDK_VERSION
aktiviert ist. Ein Symbol ist nur dann in der Stub-Bibliothek enthalten, wenn
- nicht im Abschnitt definiert ist und auf
_PRIVATE
oder_PLATFORM
endet, - Hat kein
#platform-only
-Tag und - Es sind keine
#introduce*
-Tags vorhanden oder das Tag stimmt mit dem Ziel überein.
VNDK
In Android.bp
-Dateien unterstützen die Moduldefinitionen cc_library
, cc_library_static
, cc_library_shared
und cc_library_headers
drei VNDK-bezogene Eigenschaften: vendor_available
, vndk.enabled
und vndk.support_system_process
.
Wenn vendor_available
oder vndk.enabled
true
ist, können zwei Varianten (core und vendor) erstellt werden. Die Kernvariante sollte als Framework-Modul und die Anbietervariante als Anbietermodul behandelt werden. Wenn einige Framework-Module von diesem Modul abhängen, wird die Kernvariante erstellt. Wenn einige Anbietermodule von diesem Modul abhängen, wird die Anbietervariante erstellt. Das Build-System erzwingt die folgenden Abhängigkeitsprüfungen:
- Die Kernvariante ist immer nur für das Framework verfügbar und kann nicht von Anbietermodulen verwendet werden.
- Die Anbietervariante ist für Framework-Module immer nicht zugänglich.
- Alle Abhängigkeiten der Anbietervariante, die in
header_libs
,static_libs
und/odershared_libs
angegeben sind, müssen entweder einllndk_library
oder ein Modul mitvendor_available
odervndk.enabled
sein. - Wenn
vendor_available
=true
ist, ist die Anbietervariante für alle Anbietermodule zugänglich. - Wenn
vendor_available
false
ist, ist die Anbietervariante nur für andere VNDK- oder VNDK-SP-Module zugänglich. Das bedeutet, dass Module mitvendor:true
keinevendor_available:false
-Module verknüpfen können.
Der Standardinstallationspfad für cc_library
oder cc_library_shared
wird anhand der folgenden Regeln bestimmt:
- Die Kernvariante ist unter
/system/lib[64]
installiert. - Der Installationspfad der Anbietervariante kann variieren:
- Wenn
vndk.enabled
false
ist, wird die Anbietervariante in/vendor/lib[64]
installiert. - Wenn
vndk.enabled
true
ist, wird die Anbietervariante in VNDK APEX(com.android.vndk.v${VER}
) installiert.
- Wenn
In der folgenden Tabelle wird zusammengefasst, wie das Buildsystem mit den Anbietervarianten umgeht:
vendor_available | vndk enabled |
vndk support_same_process |
Variantenbeschreibungen des Anbieters |
---|---|---|---|
true |
false |
false |
Die Anbietervarianten sind VND-ONLY. Gemeinsam genutzte Bibliotheken werden in /vendor/lib[64] installiert. |
true |
Ungültig (Build-Fehler) | ||
true |
false |
Die Anbietervarianten sind VNDK. Gemeinsam genutzte Bibliotheken werden in VNDK APEX installiert. | |
true |
Die Anbietervarianten sind VNDK-SP. Gemeinsam genutzte Bibliotheken werden in VNDK APEX installiert. | ||
|
|
|
Keine Anbietervarianten. Dieses Modul ist NUR FÜR DAS FREIHANDKONTO. |
true |
Ungültig (Build-Fehler) | ||
true |
false |
Die Anbietervarianten sind VNDK-Private. Gemeinsam genutzte Bibliotheken werden in VNDK APEX installiert. Diese dürfen nicht direkt von Anbietermodulen verwendet werden. | |
true |
Die Anbietervarianten sind VNDK-SP-Private. Gemeinsam genutzte Bibliotheken werden in VNDK APEX installiert. Diese dürfen nicht direkt von Anbietermodulen verwendet werden. |
VNDK-Erweiterungen
VNDK-Erweiterungen sind gemeinsam genutzte VNDK-Bibliotheken mit zusätzlichen APIs. Erweiterungen werden unter /vendor/lib[64]/vndk[-sp]
(ohne Versionssuffix) installiert und überschreiben die ursprünglichen VNDK-gemeinsam genutzten Bibliotheken zur Laufzeit.
VNDK-Erweiterungen definieren
Unter Android 9 und höher unterstützt Android.bp
nativ VNDK-Erweiterungen. Wenn Sie eine VNDK-Erweiterung erstellen möchten, definieren Sie ein weiteres Modul mit einer vendor:true
- und einer extends
-Eigenschaft:
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, }
Ein Modul mit den Properties vendor:true
, vndk.enabled:true
und extends
definiert die VNDK-Erweiterung:
- Für die Property
extends
muss der Name einer Basis-VNDK-gemeinsam genutzten Bibliothek (oder einer VNDK-SP-gemeinsam genutzten Bibliothek) angegeben werden. - VNDK-Erweiterungen (oder VNDK-SP-Erweiterungen) werden nach den Namen der Basismodule benannt, die sie erweitern. Beispiel: Die Binärausgabe von
libvndk_ext
istlibvndk.so
anstelle vonlibvndk_ext.so
. - VNDK-Erweiterungen werden in
/vendor/lib[64]/vndk
installiert. - VNDK-SP-Erweiterungen werden in
/vendor/lib[64]/vndk-sp
installiert. - Die Basisbibliotheken müssen sowohl
vndk.enabled:true
als auchvendor_available:true
enthalten.
Eine VNDK-SP-Erweiterung muss von einer VNDK-SP-gemeinsam genutzten Bibliothek stammen (vndk.support_system_process
muss gleich sein):
cc_library { name: "libvndk_sp", vendor_available: true, vndk: { enabled: true, support_system_process: true, }, } cc_library { name: "libvndk_sp_ext", vendor: true, vndk: { enabled: true, extends: "libvndk_sp", support_system_process: true, }, }
VNDK-Erweiterungen (oder VNDK-SP-Erweiterungen) können von anderen gemeinsam genutzten Bibliotheken des Anbieters abhängen:
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, shared_libs: [ "libvendor", ], } cc_library { name: "libvendor", vendor: true, }
VNDK-Erweiterungen verwenden
Wenn ein Anbietermodul von zusätzlichen APIs abhängig ist, die durch VNDK-Erweiterungen definiert sind, muss das Modul den Namen der VNDK-Erweiterung in der shared_libs
-Eigenschaft angeben:
// A vendor shared library example cc_library { name: "libvendor", vendor: true, shared_libs: [ "libvndk_ext", ], } // A vendor executable example cc_binary { name: "vendor-example", vendor: true, shared_libs: [ "libvndk_ext", ], }
Wenn ein Anbietermodul von VNDK-Erweiterungen abhängt, werden diese VNDK-Erweiterungen automatisch in /vendor/lib[64]/vndk[-sp]
installiert. Wenn ein Modul nicht mehr von einer VNDK-Erweiterung abhängt, fügen Sie CleanSpec.mk
einen Schritt zum Bereinigen hinzu, um die freigegebene Bibliothek zu entfernen. Beispiel:
$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)
Bedingte Kompilierung
In diesem Abschnitt wird beschrieben, wie Sie mit den geringen Unterschieden zwischen den folgenden drei VNDK-Freigabebibliotheken umgehen (z.B. Hinzufügen oder Entfernen einer Funktion in einer der Varianten):
- Hauptvariante (z.B.
/system/lib[64]/libexample.so
) - Anbietervariante (z.B.
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) - VNDK-Erweiterung (z.B.
/vendor/lib[64]/vndk[-sp]/libexample.so
)
Bedingte Compiler-Flags
Das Android-Buildsystem definiert __ANDROID_VNDK__
standardmäßig für Anbietervarianten und VNDK-Erweiterungen. Sie können den Code mit den C-Preprocessor-Guards schützen:
void all() { } #if !defined(__ANDROID_VNDK__) void framework_only() { } #endif #if defined(__ANDROID_VNDK__) void vndk_only() { } #endif
Zusätzlich zu __ANDROID_VNDK__
können in Android.bp
unterschiedliche cflags
oder cppflags
angegeben werden. Die in target.vendor
angegebene cflags
oder cppflags
ist spezifisch für die Anbietervariante.
Im folgenden Beispiel wird Android.bp
verwendet, um libexample
und libexample_ext
zu definieren:
cc_library { name: "libexample", srcs: ["src/example.c"], vendor_available: true, vndk: { enabled: true, }, target: { vendor: { cflags: ["-DLIBEXAMPLE_ENABLE_VNDK=1"], }, }, } cc_library { name: "libexample_ext", srcs: ["src/example.c"], vendor: true, vndk: { enabled: true, extends: "libexample", }, cflags: [ "-DLIBEXAMPLE_ENABLE_VNDK=1", "-DLIBEXAMPLE_ENABLE_VNDK_EXT=1", ], }
Und das ist der Code-Eintrag für src/example.c
:
void all() { } #if !defined(LIBEXAMPLE_ENABLE_VNDK) void framework_only() { } #endif #if defined(LIBEXAMPLE_ENABLE_VNDK) void vndk() { } #endif #if defined(LIBEXAMPLE_ENABLE_VNDK_EXT) void vndk_ext() { } #endif
Anhand dieser beiden Dateien generiert das Build-System freigegebene Bibliotheken mit den folgenden exportierten Symbolen:
Installationspfad | Exportierte Symbole |
---|---|
/system/lib[64]/libexample.so |
all , framework_only |
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so |
all , vndk |
/vendor/lib[64]/vndk/libexample.so |
all , vndk , vndk_ext |
Anforderungen an die exportierten Symbole
Der VNDK ABI-Checker vergleicht das ABI von VNDK-Anbietervarianten und VNDK-Erweiterungen mit den Referenz-ABI-Dumps unter prebuilts/abi-dumps/vndk
.
- Symbole, die von VNDK-Anbietervarianten (z.B.
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) exportiert werden, müssen mit den in ABI-Dumps definierten Symbolen identisch sein (nicht deren Supermengen). - Symbole, die von VNDK-Erweiterungen exportiert werden (z.B.
/vendor/lib[64]/vndk/libexample.so
), müssen Supermengen der in ABI-Dumps definierten Symbole sein.
Wenn VNDK-Anbietervarianten oder VNDK-Erweiterungen nicht den oben genannten Anforderungen entsprechen, gibt der VNDK-ABI-Checker Build-Fehler aus und beendet den Build.
Quelldateien oder freigegebene Bibliotheken von Anbietervarianten ausschließen
Wenn Sie Quelldateien aus der Anbietervariante ausschließen möchten, fügen Sie sie der Property exclude_srcs
hinzu. Damit gemeinsam genutzte Bibliotheken nicht mit der Anbietervariante verknüpft werden, fügen Sie diese Bibliotheken der Property exclude_shared_libs
hinzu. Beispiel:
cc_library { name: "libexample_cond_exclude", srcs: ["fwk.c", "both.c"], shared_libs: ["libfwk_only", "libboth"], vendor_available: true, target: { vendor: { exclude_srcs: ["fwk.c"], exclude_shared_libs: ["libfwk_only"], }, }, }
In diesem Beispiel enthält die Kernvariante von libexample_cond_exclude
den Code von fwk.c
und both.c
und hängt von den freigegebenen Bibliotheken libfwk_only
und libboth
ab. Die Anbietervariante von libexample_cond_exclude
enthält nur den Code von both.c
, da fwk.c
durch die Property exclude_srcs
ausgeschlossen wird. Außerdem hängt sie nur von der freigegebenen Bibliothek libboth
ab, da libfwk_only
durch die Property exclude_shared_libs
ausgeschlossen wird.
Header aus VNDK-Erweiterungen exportieren
Eine VNDK-Erweiterung kann einer VNDK-Bibliothek neue Klassen oder Funktionen hinzufügen. Wir empfehlen, diese Deklarationen in separaten Headern zu platzieren und die vorhandenen Header nicht zu ändern.
Beispiel: Für die VNDK-Erweiterung libexample_ext
wird eine neue Headerdatei include-ext/example/ext/feature_name.h
erstellt:
- Android.bp
- include-ext/example/ext/feature_name.h
- include/beispiel/beispiel.h
- src/beispiel.c
- src/ext/feature_name.c
Im folgenden Beispiel exportiert libexample
nur include
, während libexample_ext
sowohl include
als auch include-ext
exportiert.Android.bp
So wird sichergestellt, dass feature_name.h
von den Nutzern von libexample
nicht fälschlicherweise in folgende Listen aufgenommen wird:
cc_library { name: "libexample", srcs: ["src/example.c"], export_include_dirs: ["include"], vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libexample_ext", srcs: [ "src/example.c", "src/ext/feature_name.c", ], export_include_dirs: [ "include", "include-ext", ], vendor: true, vndk: { enabled: true, extends: "libexample", }, }
Wenn die Erweiterungen nicht in separate Headerdateien aufgeteilt werden können, können Sie stattdessen #ifdef
-Guards hinzufügen. Achten Sie jedoch darauf, dass alle VNDK-Erweiterungsnutzer die Flags definieren. Sie können cc_defaults
definieren, um cflags
Flags hinzuzufügen und gemeinsam genutzte Bibliotheken mit shared_libs
zu verknüpfen.
Wenn Sie beispielsweise der VNDK-Erweiterung libexample2_ext
eine neue Mitgliedsfunktion Example2::get_b()
hinzufügen möchten, müssen Sie die vorhandene Headerdatei ändern und eine #ifdef
-Guard hinzufügen:
#ifndef LIBEXAMPLE2_EXAMPLE_H_ #define LIBEXAMPLE2_EXAMPLE_H_ class Example2 { public: Example2(); void get_a(); #ifdef LIBEXAMPLE2_ENABLE_VNDK_EXT void get_b(); #endif private: void *impl_; }; #endif // LIBEXAMPLE2_EXAMPLE_H_
Für die Nutzer von libexample2_ext
ist eine cc_defaults
mit dem Namen libexample2_ext_defaults
definiert:
cc_library { name: "libexample2", srcs: ["src/example2.cpp"], export_include_dirs: ["include"], vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libexample2_ext", srcs: ["src/example2.cpp"], export_include_dirs: ["include"], vendor: true, vndk: { enabled: true, extends: "libexample2", }, cflags: [ "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1", ], } cc_defaults { name: "libexample2_ext_defaults", shared_libs: [ "libexample2_ext", ], cflags: [ "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1", ], }
Die Nutzer von libexample2_ext
können libexample2_ext_defaults
einfach in ihre defaults
-Property einschließen:
cc_binary { name: "example2_user_executable", defaults: ["libexample2_ext_defaults"], vendor: true, }
Produktpakete
Im Android-Build-System gibt die Variable PRODUCT_PACKAGES
die ausführbaren Dateien, freigegebenen Bibliotheken oder Pakete an, die auf dem Gerät installiert werden sollen. Die transitiven Abhängigkeiten der angegebenen Module werden ebenfalls implizit auf dem Gerät installiert.
Wenn BOARD_VNDK_VERSION
aktiviert ist, werden Module mit vendor_available
oder vndk.enabled
besonders behandelt. Wenn ein Framework-Modul von einem Modul mit vendor_available
oder vndk.enabled
abhängt, ist die Kernvariante im transitiven Installationssatz enthalten. Wenn ein Anbietermodul von einem Modul mit vendor_available
abhängt, ist die Anbietervariante im transitiven Installationssatz enthalten. Anbietervarianten von Modulen mit vndk.enabled
werden jedoch installiert, unabhängig davon, ob sie von Anbietermodulen verwendet werden oder nicht.
Wenn die Abhängigkeiten für das Buildsystem nicht sichtbar sind (z.B. freigegebene Bibliotheken, die zur Laufzeit mit dlopen()
geöffnet werden können), sollten Sie die Modulnamen in PRODUCT_PACKAGES
angeben, um diese Module explizit zu installieren.
Wenn ein Modul vendor_available
oder vndk.enabled
enthält, steht der Modulname für die Kernvariante. Wenn Sie die Anbietervariante in PRODUCT_PACKAGES
explizit angeben möchten, hängen Sie dem Modulnamen das Suffix .vendor
an. Beispiel:
cc_library { name: "libexample", srcs: ["example.c"], vendor_available: true, }
In diesem Beispiel steht libexample
für /system/lib[64]/libexample.so
und libexample.vendor
für /vendor/lib[64]/libexample.so
. Wenn Sie /vendor/lib[64]/libexample.so
installieren möchten, fügen Sie libexample.vendor
zu PRODUCT_PACKAGES
hinzu:
PRODUCT_PACKAGES += libexample.vendor