VNDK-Build-Systemunterstützung

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 festgelegten 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:

libexample vendor_available:true and vndk.enabled:true

Abbildung 1: Unterstützung aktiviert.

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-Unterstützung 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 Suchpfade für Header 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ängig ist, 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 abgeflacht oder nicht vereinfacht und ist über den kanonischen Pfad /apex/com.android.vndk.v${VER} verfügbar.

VNDK APEX

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 gemeinsam genutzte Bibliotheken, die in einer Anbieterpartition installiert werden müssen. In Android.bp-Dateien müssen Anbietermodule die Anbieter- oder proprietären Eigenschaft 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, erlaubt das Build-System keine Abhängigkeiten zwischen Anbietermodulen und Framework-Modulen und gibt Fehler aus, wenn:

  • Ein Modul ohne vendor:true hängt von einem Modul mit vendor:true ab.
  • Ein Modul mit vendor:true hängt von einem Nicht-llndk_library-Modul ab, das weder vendor:true noch vendor_available:true enthält.

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 gemeinsam genutzte LL-NDK-Bibliothek enthält cc_library ein llndk-Attribut 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 gemeinsam genutzte Stub-Bibliothek für Anbietermodule, die mit diesen Bibliotheken verknüpft werden, wenn BOARD_VNDK_VERSION aktiviert ist. Ein Symbol ist nur in den folgenden Fällen in der gemeinsam genutzten Stub-Bibliothek enthalten:

  • 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 für Anbietermodule nicht zugänglich.
  • Auf die Anbietervariante kann immer nicht auf Framework-Module zugegriffen werden.
  • Alle Abhängigkeiten der Anbietervariante, die in header_libs, static_libs und/oder shared_libs angegeben sind, müssen entweder eine llndk_library oder ein Modul mit vendor_available oder vndk.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 mit vendor:true keine vendor_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.

In der folgenden Tabelle ist zusammengefasst, wie das Build-System die Anbietervarianten verarbeitet:

vendor_available vndk
enabled
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 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.

false

false

false

Keine Anbietervarianten. Dieses Modul ist NUR FWK-spezifisch.

true Ungültig (Build-Fehler)
true false Die Anbietervarianten sind VNDK-Private. Gemeinsam genutzte Bibliotheken werden in VNDK APEX installiert. Sie dürfen nicht direkt von Anbietermodulen verwendet werden.
true Die Anbietervarianten sind VNDK-SP-Private. Gemeinsam genutzte Bibliotheken werden in VNDK APEX installiert. Sie 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 ist libvndk.so anstelle von libvndk_ext.so.
  • VNDK-Erweiterungen werden in /vendor/lib[64]/vndk installiert.
  • VNDK-SP-Erweiterungen sind in /vendor/lib[64]/vndk-sp installiert.
  • Die gemeinsam genutzten Basisbibliotheken müssen sowohl vndk.enabled:true als auch vendor_available:true haben.

Eine VNDK-SP-Erweiterung muss aus einer gemeinsam genutzten Bibliothek gemäß VNDK-SP 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 von Anbietern 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ängig ist, werden diese VNDK-Erweiterungen automatisch für /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 der Umgang mit den kleinen Unterschieden zwischen den folgenden drei gemeinsam genutzten VNDK-Bibliotheken beschrieben, z.B. durch Hinzufügen oder Entfernen eines Features zu 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.

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 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 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 die oben genannten Anforderungen nicht erfüllen, gibt die VNDK ABI-Prüfung Build-Fehler aus und stoppt 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. Ebenso kannst du dies dem Attribut exclude_shared_libs hinzufügen, damit gemeinsam genutzte Bibliotheken nicht mit der Anbietervariante verknüpft sind. 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. Ebenso ist es nur von der gemeinsam genutzten Bibliothek libboth abhängig, 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. Es wird empfohlen, diese Deklarationen in unabhängigen Headern zu belassen 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/example.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 es nicht möglich ist, Erweiterungen von unabhängigen Headerdateien zu trennen, können Sie alternativ #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 Mitgliederfunktion Example2::get_b() hinzufügen möchten, müssen Sie die vorhandene Headerdatei ändern und einen #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 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. 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. Allerdings werden Anbietervarianten von Modulen mit vndk.enabled unabhängig davon installiert, 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