In Android 8.1 und höher verfügt das Build-System über integrierte VNDK-Unterstützung. Wenn die VNDK-Unterstützung aktiviert ist, prüft das Build-System die Abhängigkeiten zwischen Modulen, erstellt eine herstellerspezifische Variante für Anbietermodule und installiert diese Module automatisch in bestimmten Verzeichnissen.
Beispiel für VNDK-Build-Unterstützung
In diesem Beispiel definiert die Android.bp
Moduldefinition eine Bibliothek mit dem Namen libexample
. Die Eigenschaft vendor_available
gibt an, dass Framework-Module und Anbietermodule von libexample
abhängen können:
Sowohl die ausführbare Framework-Datei /system/bin/foo
als auch die ausführbare Anbieterdatei /vendor/bin/bar
hängen von libexample
ab und haben libexample
in ihren shared_libs
Eigenschaften.
Wenn libexample
sowohl von Framework-Modulen als auch von Herstellermodulen verwendet wird, werden zwei Varianten von libexample
erstellt. Die Kernvariante (benannt nach libexample
) wird von Framework-Modulen verwendet und die Vendor-Variante (benannt nach libexample.vendor
) wird von Vendor-Modulen verwendet. Die beiden Varianten werden in unterschiedliche Verzeichnisse installiert:
- Die Kernvariante wird in
/system/lib[64]/libexample.so
installiert. - Die Herstellervariante wird in VNDK APEX installiert, da
vndk.enabled
true
ist.
Weitere Einzelheiten finden Sie unter Moduldefinition .
Build-Unterstützung konfigurieren
Um die vollständige Build-System-Unterstützung für ein Produktgerät zu aktivieren, fügen Sie BOARD_VNDK_VERSION
zu BoardConfig.mk
hinzu:
BOARD_VNDK_VERSION := current
Diese Einstellung hat eine globale Wirkung: Bei Definition in BoardConfig.mk
werden alle Module überprüft. Da es keinen Mechanismus gibt, um ein fehlerhaftes Modul auf die Blacklist oder Whitelist zu setzen, sollten Sie alle unnötigen Abhängigkeiten bereinigen, 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 . Diese beinhalten:
-
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
In Android 10 und niedriger wurden Module mit vndk.enabled
in /system/lib[64]/vndk[-sp]-${VER}
installiert. In Android 11 und höher sind VNDK-Bibliotheken in einem APEX-Format gepackt und der Name von VNDK APEX ist com.android.vndk.v${VER}
. Abhängig von der Gerätekonfiguration ist VNDK APEX abgeflacht oder nicht abgeflacht und über den kanonischen Pfad /apex/com.android.vndk.v${VER}
verfügbar.
Moduldefinition
Um Android mit BOARD_VNDK_VERSION
zu erstellen, müssen Sie die Moduldefinition entweder in Android.mk
oder Android.bp
überarbeiten. In diesem Abschnitt werden verschiedene Arten von Moduldefinitionen, verschiedene VNDK-bezogene Moduleigenschaften und im Build-System implementierte Abhängigkeitsprüfungen beschrieben.
Anbietermodule
Anbietermodule sind herstellerspezifische ausführbare Dateien oder gemeinsam genutzte Bibliotheken, die in einer Anbieterpartition installiert werden müssen. In Android.bp
Dateien müssen Herstellermodule die Eigenschaft „vendor“ oder „proprietary“ auf true
setzen. In Android.mk
Dateien müssen Anbietermodule LOCAL_VENDOR_MODULE
oder LOCAL_PROPRIETARY_MODULE
auf true
setzen.
Wenn BOARD_VNDK_VERSION
definiert ist, lässt das Build-System keine Abhängigkeiten zwischen Anbietermodulen und Framework-Modulen zu und gibt Fehler aus, wenn:
- Ein Modul ohne
vendor:true
hängt von einem Modul mitvendor:true
ab, oder - Ein Modul mit
vendor:true
hängt von einem Nicht-llndk_library
Modul ab, 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
Gemeinsam genutzte LL-NDK-Bibliotheken sind gemeinsam genutzte Bibliotheken mit stabilen ABIs. Sowohl das Framework als auch die Anbietermodule verwenden dieselbe und die neueste Implementierung. Für jede gemeinsam genutzte LL-NDK-Bibliothek enthält die cc_library
eine llndk
Eigenschaft mit einer Symboldatei:
cc_library { name: "libvndksupport", llndk: { symbol_file: "libvndksupport.map.txt", }, }
Die Symboldatei beschreibt die Symbole, die für Anbietermodule sichtbar sind. Zum Beispiel:
LIBVNDKSUPPORT { global: android_load_sphal_library; # llndk android_unload_sphal_library; # llndk local: *; };
Basierend auf der Symboldatei generiert das Build-System eine gemeinsam genutzte 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-Shared-Bibliothek enthalten, wenn es:
- Ist nicht am Abschnittsende mit
_PRIVATE
oder_PLATFORM
definiert, - Hat kein
#platform-only
Tag und - Verfügt nicht über
#introduce*
-Tags 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 Herstellermodule von diesem Modul abhängen, wird die Herstellervariante erstellt. Das Build-System erzwingt die folgenden Abhängigkeitsprüfungen:
- Die Kernvariante ist immer nur für das Framework verfügbar und für Anbietermodule nicht zugänglich.
- Die Herstellervariante 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 einellndk_library
oder ein Modul mitvendor_available
odervndk.enabled
sein. - Wenn
vendor_available
dentrue
hat, ist die Vendor-Variante für alle Vendor-Module zugänglich. - Wenn
vendor_available
den Wert „false
hat, ist die Vendor-Variante nur für andere VNDK- oder VNDK-SP-Module zugänglich (d. h. Module mitvendor:true
können keinevendor_available:false
-Module verknüpfen).
Der Standardinstallationspfad für cc_library
oder cc_library_shared
wird durch die folgenden Regeln bestimmt:
- Die Kernvariante wird unter
/system/lib[64]
installiert. - Der Installationspfad der Anbietervariante kann variieren:
- Wenn
vndk.enabled
false
ist, wird die Herstellervariante in/vendor/lib[64]
installiert. - Wenn
vndk.enabled
true
ist, wird die Herstellervariante in VNDK APEX (com.android.vndk.v${VER}
) installiert.
- Wenn
Die folgende Tabelle fasst zusammen, wie das Build-System mit den Herstellervarianten umgeht:
anbieter_verfügbar | vndk ermöglicht | vndk support_same_process | Beschreibungen der Anbietervarianten |
---|---|---|---|
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 Herstellervarianten sind VNDK . Gemeinsam genutzte Bibliotheken werden auf VNDK APEX installiert. | |
true | Die Herstellervarianten sind VNDK-SP . Gemeinsam genutzte Bibliotheken werden auf VNDK APEX installiert. | ||
| | | Keine Herstellervarianten. Dieses Modul ist NUR FWK . |
true | Ungültig (Build-Fehler) | ||
true | false | Die Anbietervarianten sind VNDK-Private . Gemeinsam genutzte Bibliotheken werden auf VNDK APEX installiert. Diese dürfen nicht direkt von Herstellermodulen verwendet werden. | |
true | Die Herstellervarianten sind VNDK-SP-Private . Gemeinsam genutzte Bibliotheken werden auf VNDK APEX installiert. Diese dürfen nicht direkt von Herstellermodulen verwendet werden. |
VNDK-Erweiterungen
VNDK-Erweiterungen sind gemeinsam genutzte VNDK-Bibliotheken mit zusätzlichen APIs. Erweiterungen werden in /vendor/lib[64]/vndk[-sp]
(ohne Versionssuffix) installiert und überschreiben die ursprünglichen gemeinsam genutzten VNDK-Bibliotheken zur Laufzeit.
Definieren von VNDK-Erweiterungen
In Android 9 und höher unterstützt Android.bp
nativ VNDK-Erweiterungen. Um eine VNDK-Erweiterung zu erstellen, definieren Sie ein weiteres Modul mit der Eigenschaft vendor:true
und „ extends
:
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 Eigenschaften vendor:true
, vndk.enabled:true
“ und „ extends
definiert die VNDK-Erweiterung:
- Die Eigenschaft
extends
muss einen Basisnamen der gemeinsam genutzten VNDK-Bibliothek (oder den Namen der gemeinsam genutzten VNDK-SP-Bibliothek) angeben. - VNDK-Erweiterungen (oder VNDK-SP-Erweiterungen) werden nach den Basismodulnamen benannt, von denen sie ausgehen. Beispielsweise lautet die Ausgabebinärdatei von
libvndk_ext
libvndk.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 gemeinsam genutzten Basisbibliotheken müssen sowohl
vndk.enabled:true
als auchvendor_available:true
haben.
Eine VNDK-SP-Erweiterung muss von einer gemeinsam genutzten VNDK-SP-Bibliothek ausgehen ( 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 gemeinsam genutzten Bibliotheken anderer Anbieter 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, }
Verwendung von VNDK-Erweiterungen
Wenn ein Anbietermodul von zusätzlichen APIs abhängt, die durch VNDK-Erweiterungen definiert werden, muss das Modul den Namen der VNDK-Erweiterung in seiner Eigenschaft shared_libs
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 Bereinigungsschritt hinzu, um die gemeinsam genutzte Bibliothek zu entfernen. Zum Beispiel:
$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)
Bedingte Kompilierung
In diesem Abschnitt wird beschrieben, wie mit den subtilen Unterschieden (z. B. Hinzufügen oder Entfernen einer Funktion aus einer der Varianten) zwischen den folgenden drei gemeinsam genutzten VNDK-Bibliotheken umgegangen wird:
- Kernvariante (z. B.
/system/lib[64]/libexample.so
) - Herstellervariante (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-Build-System definiert standardmäßig __ANDROID_VNDK__
für Herstellervarianten und VNDK-Erweiterungen. Sie können den Code mit den C-Präprozessor-Schutzvorrichtungen 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
verschiedene cflags
oder cppflags
angegeben werden. Die in target.vendor
angegebenen cflags
oder cppflags
sind spezifisch für die Anbietervariante.
Beispielsweise definiert die folgende Android.bp
libexample
und libexample_ext
:
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 die Codeauflistung von 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
Basierend auf diesen beiden Dateien generiert das Build-System gemeinsam genutzte 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 den ABI von VNDK-Anbietervarianten und VNDK-Erweiterungen mit den Referenz-ABI-Dumps unter prebuilts/abi-dumps/vndk
.
- Von VNDK-Anbietervarianten exportierte Symbole (z. B.
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) müssen mit den in ABI-Dumps definierten Symbolen identisch sein (nicht deren Obermengen). - Von VNDK-Erweiterungen exportierte Symbole (z. B.
/vendor/lib[64]/vndk/libexample.so
) müssen Obermengen der in ABI-Dumps definierten Symbole sein.
Wenn VNDK-Anbietervarianten oder VNDK-Erweiterungen die oben genannten Anforderungen nicht erfüllen, gibt der VNDK-ABI-Checker Build-Fehler aus und stoppt den Build.
Ausschließen von Quelldateien oder gemeinsam genutzten Bibliotheken aus Anbietervarianten
Um Quelldateien von der Anbietervariante auszuschließen, fügen Sie sie der Eigenschaft exclude_srcs
hinzu. Um sicherzustellen, dass gemeinsam genutzte Bibliotheken nicht mit der Anbietervariante verknüpft sind, fügen Sie diese Bibliotheken ebenfalls der Eigenschaft exclude_shared_libs
hinzu. Zum 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 gemeinsam genutzten Bibliotheken libfwk_only
und libboth
ab. Die Herstellervariante von libexample_cond_exclude
enthält nur den Code von both.c
, da fwk.c
durch die exclude_srcs
ausgeschlossen wird. Ebenso hängt es nur von der gemeinsam genutzten Bibliothek libboth
ab, da libfwk_only
durch die exclude_shared_libs
ausgeschlossen wird.
Exportieren Sie Header aus VNDK-Erweiterungen
Eine VNDK-Erweiterung kann einer gemeinsam genutzten VNDK-Bibliothek neue Klassen oder neue Funktionen hinzufügen. Es wird empfohlen, diese Deklarationen in unabhängigen Headern zu belassen und eine Änderung der vorhandenen Header zu vermeiden.
Beispielsweise wird eine neue Header-Datei include-ext/example/ext/feature_name.h
für die VNDK-Erweiterung libexample_ext
erstellt:
- Android.bp
- include-ext/example/ext/feature_name.h
- include/example/example.h
- src/example.c
- src/ext/feature_name.c
Im folgenden Android.bp
include
die Exporte libexample
nur include , während die Exporte libexample_ext
sowohl include
als auch include-ext
enthalten. Dadurch wird sichergestellt, dass feature_name.h
von den Benutzern von libexample
nicht fälschlicherweise eingefügt 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 Trennung von Erweiterungen in unabhängige Header-Dateien nicht möglich ist, besteht eine Alternative darin, #ifdef
Schutzvorrichtungen hinzuzufügen. Stellen Sie jedoch sicher, dass alle Benutzer der VNDK-Erweiterung die Definitionsflags hinzufügen. Sie können cc_defaults
definieren, um Definitionsflags zu cflags
hinzuzufügen und gemeinsam genutzte Bibliotheken mit shared_libs
zu verknüpfen.
Um beispielsweise eine neue Mitgliedsfunktion Example2::get_b()
zur VNDK-Erweiterung libexample2_ext
hinzuzufügen, müssen Sie die vorhandene Header-Datei ändern und einen #ifdef
Schutz 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 Benutzer von libexample2_ext
ist ein 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 Benutzer von libexample2_ext
können einfach libexample2_ext_defaults
in ihre defaults
aufnehmen:
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, gemeinsam genutzten Bibliotheken oder Pakete an, die auf dem Gerät installiert werden sollen. Auch die transitiven Abhängigkeiten der angegebenen Module werden implizit in das Gerät eingebaut.
Wenn BOARD_VNDK_VERSION
aktiviert ist, erhalten Module mit vendor_available
“ oder vndk.enabled
eine Sonderbehandlung. 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. Allerdings werden Anbietervarianten von Modulen mit vndk.enabled
installiert, unabhängig davon, ob sie von Anbietermodulen verwendet werden oder nicht.
Wenn die Abhängigkeiten für das Build-System unsichtbar sind (z. B. gemeinsam genutzte 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
hat, steht der Modulname für seine Kernvariante. Um die Herstellervariante in PRODUCT_PACKAGES
explizit anzugeben, hängen Sie ein .vendor
Suffix an den Modulnamen an. Zum 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
steht für /vendor/lib[64]/libexample.so
. Um /vendor/lib[64]/libexample.so
zu installieren, fügen Sie libexample.vendor
zu PRODUCT_PACKAGES
hinzu:
PRODUCT_PACKAGES += libexample.vendor