Compatibilité avec le système de compilation VNDK

Dans Android 8.1 et versions ultérieures, le système de compilation est compatible avec le VNDK intégré. Quand ? la compatibilité avec VNDK est activée, le système de compilation vérifie les dépendances modules, crée une variante spécifique au fournisseur pour les modules du fournisseur et installe automatiquement ces modules dans les répertoires désignés.

Exemple d'assistance pour la compilation VNDK

Dans cet exemple, la définition du module Android.bp définit un nommée libexample. vendor_available indique que les modules de framework et de fournisseur peuvent dépendre libexample:

libexample provider_available:true et vndk.enabled:true

Figure 1.Compatibilité activée.

L'exécutable /system/bin/foo du framework et le fournisseur l'exécutable /vendor/bin/bar dépendent de libexample et contiennent libexample dans leurs propriétés shared_libs.

Si libexample est utilisé à la fois par les modules du framework et par le fournisseur modules, deux variantes de libexample sont créées. La variante principale (nommée d'après libexample) est utilisée par les modules de framework et Une variante de fournisseur (nommée d'après libexample.vendor) est utilisée par le fournisseur modules. Les deux variantes sont installées dans des répertoires différents:

  • La variante principale est installée /system/lib[64]/libexample.so
  • La variante du fournisseur est installée dans VNDK APEX, car vndk.enabled est true.

Pour en savoir plus, consultez Définition du module.

Configurer la compatibilité avec la compilation

Pour activer la compatibilité complète du système de compilation pour un appareil produit, ajoutez BOARD_VNDK_VERSION à BoardConfig.mk:

BOARD_VNDK_VERSION := current

Ce paramètre a un effet global: lorsqu'il est défini dans BoardConfig.mk, tous les modules sont cochés. Comme il n'y a pas de mécanisme pour ajouter un module incriminé à la liste noire ou blanche, vous devez supprimer dépendances inutiles avant d'ajouter BOARD_VNDK_VERSION. Toi pouvez tester et compiler un module en définissant BOARD_VNDK_VERSION dans vos variables d'environnement:

$ BOARD_VNDK_VERSION=current m module_name.vendor

Lorsque BOARD_VNDK_VERSION est activé, plusieurs paramètres globaux par défaut les chemins de recherche d'en-tête sont supprimés. En voici quelques exemples :

  • 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

Si un module dépend des en-têtes de ces répertoires, vous devez spécifier (explicitement) les dépendances avec header_libs, static_libs et/ou shared_libs.

APRÈS DU VNDK

Sous Android 10 et versions antérieures, les modules avec vndk.enabled étaient installés dans /system/lib[64]/vndk[-sp]-${VER} Sur Android 11 et versions ultérieures, Les bibliothèques VNDK sont empaquetées au format APEX et le nom de VNDK APEX est com.android.vndk.v${VER} Selon la configuration de l'appareil, Le VNDK APEX est aplati ou non aplati, et disponible via le chemin canonique /apex/com.android.vndk.v${VER}

APRÈS DU VNDK

Figure 2. VNDK APEX.

Définition du module

Pour compiler Android avec BOARD_VNDK_VERSION, vous devez modifier le la définition du module dans Android.mk ou Android.bp Cette section décrit différents types de modules définitions, plusieurs propriétés de module liées au VNDK et vérifications des dépendances implémentés dans le système de compilation.

Modules du fournisseur

Les modules fournisseurs sont des exécutables spécifiques au fournisseur ou des bibliothèques partagées qui doit être installé dans une partition de fournisseur. Dans Android.bp fichiers, les modules fournisseur doivent définir la propriété du fournisseur ou du propriétaire sur true. Dans les fichiers Android.mk, les modules du fournisseur doivent définir LOCAL_VENDOR_MODULE ou LOCAL_PROPRIETARY_MODULE pour true

Si BOARD_VNDK_VERSION est défini, le système de compilation interdit les dépendances entre les modules du fournisseur et les modules du framework, et génère des erreurs dans les cas suivants:

  • un module sans vendor:true dépend d'un module avec vendor:true ou
  • un module avec vendor:true dépend un module non-llndk_library qui ne contient vendor:true ni vendor_available:true.

La vérification des dépendances s'applique à header_libs, static_libs et shared_libs dans Android.bp et à LOCAL_HEADER_LIBRARIES, LOCAL_STATIC_LIBRARIES et LOCAL_SHARED_LIBRARIES dans Android.mk

LL-NDK

Les bibliothèques partagées LL-NDK sont des bibliothèques partagées avec des ABI stables. Les deux frameworks et les modules fournisseurs partagent la même implémentation que la dernière. Pour chaque Bibliothèque partagée LL-NDK, le cc_library contient un llndk avec un fichier de symboles:

cc_library {
    name: "libvndksupport",
    llndk: {
        symbol_file: "libvndksupport.map.txt",
    },
}

Le fichier de symboles décrit les symboles visibles par les modules du fournisseur. Exemple :

LIBVNDKSUPPORT {
  global:
    android_load_sphal_library; # llndk
    android_unload_sphal_library; # llndk
  local:
    *;
};

En se basant sur le fichier de symboles, le système de compilation génère une bibliothèque partagée de bouchon pour modules fournisseurs, qui sont associés à ces bibliothèques BOARD_VNDK_VERSION est activé. Un symbole est inclus dans le bouchon bibliothèque partagée uniquement si elle:

  • n'est pas défini dans la section qui se termine par _PRIVATE ou ; _PLATFORM,
  • ne comporte pas le tag #platform-only ; et
  • Ne comporte pas de balises #introduce* ou correspond à la balise cible.
<ph type="x-smartling-placeholder">

VNDK

Dans Android.bp fichiers, cc_library, cc_library_static, cc_library_shared et Les définitions de module cc_library_headers prennent en charge trois types du VNDK : vendor_available, vndk.enabled et vndk.support_system_process

Si vendor_available ou vndk.enabled est true, deux variantes (principale et fournisseur) peuvent être conçue. La variante principale doit être considérée comme un module de framework et le fournisseur la variante doit être traitée comme un module du fournisseur. Si certains modules du framework dépendent dans ce module, la variante principale est créée. Si certains modules du fournisseur dépend de ce module, la variante du fournisseur est créée. Le système de compilation applique les vérifications de dépendance suivantes:

  • La variante principale est toujours basée sur le framework uniquement et le fournisseur ne peut pas y accéder. modules.
  • La variante de fournisseur est toujours inaccessible aux modules du framework.
  • Toutes les dépendances de la variante de fournisseur, spécifiées dans header_libs, static_libs et/ou shared_libs, doit être de type llndk_library ou avec vendor_available ou vndk.enabled.
  • Si vendor_available est défini sur true, la variante du fournisseur est accessible à tous les modules du fournisseur.
  • Si vendor_available est défini sur false, la variante du fournisseur est accessible uniquement aux autres modules VNDK ou VNDK-SP (c'est-à-dire aux modules avec vendor:true ne peut pas associer vendor_available:false modules).

Le chemin d'installation par défaut de cc_library ou cc_library_shared est déterminé par les règles suivantes:

  • La variante principale est installée dans /system/lib[64].
  • Le chemin d'installation de la variante du fournisseur peut varier: <ph type="x-smartling-placeholder">
      </ph>
    • Si vndk.enabled est défini sur false, la variante du fournisseur est installé dans /vendor/lib[64].
    • Si vndk.enabled est défini sur true, la variante du fournisseur est installé dans VNDK APEX(com.android.vndk.v${VER}).

Le tableau ci-dessous récapitule la façon dont le système de compilation gère les variantes du fournisseur:

fournisseur_disponible vndk
activé
vndk
support_same_process
Descriptions des variantes du fournisseur
true false false Les variantes de fournisseurs sont VND UNIQUEMENT. Les bibliothèques partagées sont installé dans /vendor/lib[64].
true Non valide (erreur de compilation)
true false Les variantes de fournisseurs sont VNDK. Les bibliothèques partagées sont installées au VNDK APEX.
true Les variantes de fournisseurs sont VNDK-SP. Les bibliothèques partagées sont installé dans VNDK APEX.

false

false

false

Aucune variante de fournisseur. Ce module est UNIQUEMENT FWK.

true Non valide (erreur de compilation)
true false Les variantes de fournisseurs sont VNDK-Private. Les bibliothèques partagées sont installé dans VNDK APEX. Il ne doit pas s'agir directement utilisé par les modules des fournisseurs.
true Les variantes de fournisseurs sont VNDK-SP-Private. Les bibliothèques partagées sont installé dans VNDK APEX. Il ne doit pas s'agir directement utilisé par les modules des fournisseurs.
<ph type="x-smartling-placeholder">

Extensions VNDK

Les extensions VNDK sont des bibliothèques partagées avec des API supplémentaires. Les extensions sont installé dans /vendor/lib[64]/vndk[-sp] (sans suffixe de version) et ignorer les bibliothèques partagées VNDK d'origine au moment de l'exécution.

Définir les extensions VNDK

Sous Android 9 ou version ultérieure, Android.bp est compatible de manière native avec le VNDK. . Pour créer une extension VNDK, définissez un autre module avec un vendor:true et une propriété extends:

cc_library {
    name: "libvndk",
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libvndk_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk",
    },
}

Un module avec vendor:true, vndk.enabled:true et Les propriétés extends définissent l'extension VNDK:

  • La propriété extends doit spécifier une bibliothèque partagée VNDK de base (ou nom de bibliothèque partagée VNDK-SP).
  • Les extensions VNDK (ou VNDK-SP) portent le nom du module de base. dont ils s'étendent. Par exemple, le binaire de sortie de libvndk_ext est libvndk.so au lieu de libvndk_ext.so
  • Les extensions VNDK sont installées dans /vendor/lib[64]/vndk.
  • Les extensions VNDK-SP sont installées /vendor/lib[64]/vndk-sp
  • Les bibliothèques partagées de base doivent comporter vndk.enabled:true et vendor_available:true.

Une extension VNDK-SP doit s'étendre à partir d'une bibliothèque partagée VNDK-SP (vndk.support_system_process doit être égal à):

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,
    },
}

Les extensions VNDK (ou VNDK-SP) peuvent dépendre d'un partage d'autres fournisseurs bibliothèques:

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,
}
<ph type="x-smartling-placeholder">

Utiliser les extensions VNDK

Si un module de fournisseur dépend d'API supplémentaires définies par les extensions VNDK, le doit spécifier le nom de l'extension VNDK dans son Propriété shared_libs:

// 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",
    ],
}

Si un module de fournisseur dépend d'extensions VNDK, celles-ci sont installé dans /vendor/lib[64]/vndk[-sp] automatiquement. Si un module ne dépend plus d'une extension VNDK, ajoutez une étape propre CleanSpec.mk pour supprimer la bibliothèque partagée. Exemple :

$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)

Compilation conditionnelle

Cette section explique comment gérer les différences subtiles (par exemple, l'ajout ou la suppression d'une caractéristique dans l'une des variantes) entre les trois bibliothèques partagées du VNDK:

  • Variante principale (ex. : /system/lib[64]/libexample.so)
  • Variante du fournisseur (par exemple, /apex/com.android.vndk.v${VER}/lib[64]/libexample.so)
  • Extension VNDK (par exemple, /vendor/lib[64]/vndk[-sp]/libexample.so)

Indicateurs de compilation conditionnels

Le système de compilation Android définit __ANDROID_VNDK__ pour le fournisseur et les extensions VNDK par défaut. Vous pouvez protéger ce code avec les protections du préprocesseur C:

void all() { }

#if !defined(__ANDROID_VNDK__)
void framework_only() { }
#endif

#if defined(__ANDROID_VNDK__)
void vndk_only() { }
#endif

En plus de __ANDROID_VNDK__, différentes cflags ou cppflags peut être spécifié dans Android.bp. La cflags ou cppflags spécifié dans target.vendor est spécifique à la variante du fournisseur.

Par exemple, l'élément Android.bp suivant définit libexample et 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",
    ],
}

Voici la liste de code de 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

Selon ces deux fichiers, le système de compilation génère des bibliothèques partagées avec les symboles exportés suivants:

Chemin d'installation Symboles exportés
/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

Exigences concernant les symboles exportés

L'outil de vérification d'ABI VNDK compare l'ABI des variantes de fournisseur VNDK et Extensions VNDK vers les fichiers de dump de l'ABI de référence sous prebuilts/abi-dumps/vndk

  • Symboles exportés par des variantes de fournisseur VNDK (par exemple, /apex/com.android.vndk.v${VER}/lib[64]/libexample.so) doivent être identiques. (et non les sur-ensembles) des symboles définis dans les fichiers de vidage d'ABI.
  • Symboles exportés par les extensions VNDK (par exemple, /vendor/lib[64]/vndk/libexample.so) doivent être des sur-ensembles de définis dans les vidages d'ABI.

Si les variantes de fournisseurs VNDK ou les extensions VNDK ne respectent pas les règles les conditions requises ci-dessus, le vérificateur d'ABI VNDK émet des erreurs de compilation et arrête créer.

Exclure les fichiers sources ou les bibliothèques partagées des variantes de fournisseurs

Pour exclure des fichiers sources de la variante du fournisseur, ajoutez-les à la exclude_srcs. De même, pour s'assurer que les bibliothèques partagées sont n'est pas associée à la variante du fournisseur, ajoutez ces bibliothèques à la exclude_shared_libs. Exemple :

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"],
        },
    },
}

Dans cet exemple, la variante principale de libexample_cond_exclude inclut le code de fwk.c et both.c, et dépend sur les bibliothèques partagées libfwk_only et libboth. La La variante de fournisseur de libexample_cond_exclude n'inclut que le code de both.c, car fwk.c est exclu par le exclude_srcs. De même, cela dépend uniquement de la bibliothèque partagée libboth, car libfwk_only est exclu par le exclude_shared_libs.

Exporter des en-têtes à partir d'extensions VNDK

Une extension VNDK peut ajouter de nouvelles classes ou de nouvelles fonctions à un VNDK partagé bibliothèque. Nous suggérons de conserver ces déclarations dans des en-têtes indépendants. et d'éviter de modifier les en-têtes existants.

Par exemple, un nouveau fichier d'en-tête include-ext/example/ext/feature_name.h est créé pour le VNDK extension libexample_ext:

  • Android.bp
  • ext-inclusion/exemple/ext/nom_fonctionnalité.h
  • inclure/exemple/exemple.h
  • src/exemple.c
  • src/ext/feature_name.c

Dans les Android.bp suivants, libexample exporte include uniquement, alors que libexample_ext exporte les deux include et include-ext. Cela garantit feature_name.h ne sera pas inclus à tort par les utilisateurs de libexample:

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",
    },
}

S'il n'est pas possible de séparer les extensions en fichiers d'en-tête indépendants, une l'alternative consiste à ajouter des Guards #ifdef. Cependant, assurez-vous que tous les Les utilisateurs de l'extension VNDK ajoutent les indicateurs de définition. Vous pouvez définir cc_defaults pour ajouter des indicateurs de définition à cflags et associer bibliothèques partagées avec shared_libs.

Par exemple, pour ajouter une fonction membre Example2::get_b() à l'extension VNDK libexample2_ext, vous devez modifier le fichier existant fichier d'en-tête et ajoutez un Guard #ifdef:

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

Un élément cc_defaults nommé libexample2_ext_defaults est défini pour les utilisateurs de libexample2_ext:

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",
    ],
}

Les utilisateurs de libexample2_ext peuvent simplement inclure libexample2_ext_defaults dans son defaults :

cc_binary {
    name: "example2_user_executable",
    defaults: ["libexample2_ext_defaults"],
    vendor: true,
}

Packages de produits

Dans le système de compilation Android, la variable PRODUCT_PACKAGES spécifie les exécutables, les bibliothèques partagées ou les packages qui doivent être installés sur l'appareil. Les dépendances transitives des objets modules sont également implicitement installés sur l'appareil.

Si BOARD_VNDK_VERSION est activé, les modules avec Offre spéciale pour vendor_available ou vndk.enabled de traitement. Si un module de framework dépend d'un module avec vendor_available ou vndk.enabled, la variante principale est inclus dans l’ensemble d’installation transitive. Si un module fournisseur dépend d'un module avec vendor_available, la variante du fournisseur est inclus dans le jeu d’installation transitive. Toutefois, les variantes de fournisseurs de modules avec vndk.enabled sont installés, qu'ils soient utilisés ou non par les modules des fournisseurs.

Lorsque les dépendances ne sont pas visibles par le système de compilation (par exemple, les bibliothèques partagées pouvant être ouvert avec dlopen() en cours d'exécution), vous devez spécifier les noms de modules dans PRODUCT_PACKAGES pour installer ces modules ; explicitement.

Si un module contient vendor_available ou vndk.enabled, le nom du module correspond à sa variante principale. Pour spécifier explicitement variante de fournisseur dans PRODUCT_PACKAGES, ajoutez un .vendor au nom du module. Exemple :

cc_library {
    name: "libexample",
    srcs: ["example.c"],
    vendor_available: true,
}

Dans cet exemple, libexample signifie /system/lib[64]/libexample.so et libexample.vendor signifie /vendor/lib[64]/libexample.so. Pour installer /vendor/lib[64]/libexample.so, ajouter libexample.vendor à PRODUCT_PACKAGES:

PRODUCT_PACKAGES += libexample.vendor