In Android 8.1 e versioni successive, il sistema di compilazione supporta VNDK integrato. Quando il supporto VNDK è abilitato, il sistema di build controlla le dipendenze tra i moduli, crea una variante specifica del fornitore per i moduli del fornitore e installa automaticamente questi moduli nelle directory designate.
Esempio di supporto alla compilazione di VNDK
  In questo esempio, la definizione del modulo Android.bp definisce una
  libreria denominata libexample. La proprietà vendor_available
  indica che i moduli del framework e i moduli del fornitore possono dipendere da
  libexample:
   
Figura 1. supporto abilitato.
  Sia l'eseguibile del framework /system/bin/foo sia l'eseguibile del fornitore /vendor/bin/bar dipendono da libexample e hanno libexample nelle proprietà shared_libs.
  Se libexample viene utilizzato sia dai moduli del framework sia dai moduli del fornitore, vengono create due varianti di libexample. La variante principale
  (denominata libexample) viene utilizzata dai moduli del framework e la
  variante del fornitore (denominata libexample.vendor) viene utilizzata dai moduli
  del fornitore. Le due varianti vengono installate in directory diverse:
- La variante principale è installata in
  /system/lib[64]/libexample.so.
- La variante del fornitore è installata in VNDK APEX perché
  vndk.enabledètrue.
Per maggiori dettagli, vedi Definizione del modulo.
Configurare il supporto delle build
  Per attivare il supporto completo del sistema di compilazione per un dispositivo prodotto, aggiungi
  BOARD_VNDK_VERSION a BoardConfig.mk:
BOARD_VNDK_VERSION := current
  Questa impostazione ha un effetto globale: se definita in
  BoardConfig.mk, tutti i moduli vengono controllati. Poiché non esiste un meccanismo
  per inserire un modulo offensivo in una lista bloccata o consentita, devi eliminare tutte
  le dipendenze non necessarie prima di aggiungere BOARD_VNDK_VERSION. Puoi
  testare e compilare un modulo impostando BOARD_VNDK_VERSION nelle
  variabili di ambiente:
$ BOARD_VNDK_VERSION=current m module_name.vendor
Quando BOARD_VNDK_VERSION è attivato, diversi percorsi di ricerca
  dell'intestazione globale predefiniti vengono rimossi. come le seguenti.
- 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
  Se un modulo dipende dalle intestazioni di queste directory, devi specificare
  (in modo esplicito) le dipendenze con header_libs,
  static_libs e/o shared_libs.
VNDK APEX
  In Android 10 e versioni precedenti, i moduli con vndk.enabled sono stati installati in
  /system/lib[64]/vndk[-sp]-${VER}. In Android 11 e versioni successive,
  le librerie VNDK sono pacchettizzate in formato APEX e il nome dell'APEX VNDK è
  com.android.vndk.v${VER}. A seconda della configurazione del dispositivo,
  VNDK APEX è appiattito o non appiattito ed è disponibile dal percorso canonico
  /apex/com.android.vndk.v${VER}.

Figura 2. VNDK APEX.
Definizione del modulo
  Per creare Android con BOARD_VNDK_VERSION, devi rivedere la
  definizione del modulo in Android.mk o
  Android.bp. Questa sezione descrive diversi tipi di definizioni di moduli, diverse proprietà dei moduli correlate a VNDK e i controlli delle dipendenze implementati nel sistema di build.
Moduli del fornitore
  I moduli del fornitore sono eseguibili o librerie condivise specifici del fornitore che
  devono essere installati in una partizione del fornitore. Nei file Android.bp,
  i moduli fornitore devono impostare la proprietà fornitore o proprietaria su true.
  Nei file Android.mk, i moduli del fornitore devono impostare
  LOCAL_VENDOR_MODULE o LOCAL_PROPRIETARY_MODULE su
  true.
  Se BOARD_VNDK_VERSION è definito, il sistema di compilazione non consente
  dipendenze tra i moduli del fornitore e i moduli del framework ed emette errori se:
- un modulo senza vendor:truedipende da un modulo convendor:trueoppure
- un modulo con vendor:truedipende da un modulo nonllndk_libraryche non ha névendor:truenévendor_available:true.
  Il controllo delle dipendenze si applica a header_libs,
  static_libs e shared_libs in
  Android.bp e a LOCAL_HEADER_LIBRARIES,
  LOCAL_STATIC_LIBRARIES e LOCAL_SHARED_LIBRARIES in
  Android.mk.
LL-NDK
  Le librerie condivise LL-NDK sono librerie condivise con ABI stabili. Sia i moduli del framework
  sia quelli del fornitore condividono la stessa implementazione più recente. Per ogni
  libreria condivisa LL-NDK, cc_library contiene una
  proprietà llndk con un file di simboli:
cc_library { name: "libvndksupport", llndk: { symbol_file: "libvndksupport.map.txt", }, }
Il file dei simboli descrive i simboli visibili ai moduli del fornitore. Ad esempio:
LIBVNDKSUPPORT { global: android_load_sphal_library; # llndk android_unload_sphal_library; # llndk local: *; };
  In base al file dei simboli, il sistema di compilazione genera una libreria condivisa stub per
  i moduli del fornitore, che si collegano a queste librerie quando
  BOARD_VNDK_VERSION è abilitato. Un simbolo è incluso nella libreria condivisa stub solo se:
- Non è definito nella sezione che termina con _PRIVATEo_PLATFORM,
- Non ha il tag #platform-onlye
- Non ha tag #introduce*o il tag corrisponde al target.
VNDK
  Nei file Android.bp, le definizioni dei moduli cc_library,
  cc_library_static, cc_library_shared e
  cc_library_headers supportano tre proprietà correlate a VNDK: vendor_available, vndk.enabled e
  vndk.support_system_process.
  Se vendor_available o vndk.enabled è
  true, possono essere
  create due varianti (core e vendor). La variante principale deve essere considerata come un modulo framework e la variante fornitore
  deve essere considerata come un modulo fornitore. Se alcuni moduli del framework dipendono
  da questo modulo, viene creata la variante principale. Se alcuni moduli del fornitore
  dipendono da questo modulo, viene creata la variante del fornitore. Il sistema di build applica
  i seguenti controlli delle dipendenze:
- La variante principale è sempre solo framework e inaccessibile ai moduli del fornitore.
- La variante del fornitore è sempre inaccessibile ai moduli del framework.
- Tutte le dipendenze della variante del fornitore, specificate in
 header_libs,static_libse/oshared_libs, devono essere unllndk_libraryo un modulo convendor_availableovndk.enabled.
- Se vendor_availableètrue, la variante del fornitore è accessibile a tutti i moduli del fornitore.
- Se vendor_availableèfalse, la variante del fornitore è accessibile solo ad altri moduli VNDK o VNDK-SP (ovvero i moduli convendor:truenon possono collegarsi ai modulivendor_available:false).
  Il percorso di installazione predefinito per cc_library o
  cc_library_shared è determinato dalle seguenti regole:
- La variante principale è installata in /system/lib[64].
- Il percorso di installazione della variante del fornitore può variare:
  - Se vndk.enabledèfalse, la variante del fornitore viene installata in/vendor/lib[64].
- Se vndk.enabledètrue, la variante del fornitore viene installata in VNDK APEX(com.android.vndk.v${VER}).
 
- Se 
La tabella seguente riepiloga il modo in cui il sistema di compilazione gestisce le varianti del fornitore:
| vendor_available | vndk enabled | vndk support_system_process | Descrizioni delle varianti del fornitore | 
|---|---|---|---|
| true | false | false | Le varianti del fornitore sono SOLO VND. Le librerie condivise vengono installate in /vendor/lib[64]. | 
| true | Non valido (errore di compilazione) | ||
| true | false | Le varianti del fornitore sono VNDK. Le librerie condivise vengono installate in VNDK APEX. | |
| true | Le varianti del fornitore sono VNDK-SP. Le librerie condivise vengono installate in VNDK APEX. | ||
| 
 | 
 | 
 | Nessuna variante del fornitore. Questo modulo è FWK-ONLY. | 
| true | Non valido (errore di compilazione) | ||
| true | false | Le varianti del fornitore sono VNDK-Private. Le librerie condivise vengono installate in VNDK APEX. Questi non devono essere utilizzati direttamente dai moduli del fornitore. | |
| true | Le varianti del fornitore sono VNDK-SP-Private. Le librerie condivise vengono installate in VNDK APEX. Questi non devono essere utilizzati direttamente dai moduli del fornitore. | 
Estensioni VNDK
  Le estensioni VNDK sono librerie condivise VNDK con API aggiuntive. Le estensioni vengono installate in /vendor/lib[64]/vndk[-sp] (senza suffisso di versione) ed eseguono l'override delle librerie condivise VNDK originali in fase di runtime.
Definisci le estensioni VNDK
  In Android 9 e versioni successive, Android.bp supporta in modo nativo le estensioni VNDK. Per creare un'estensione VNDK, definisci un altro modulo con una proprietà
  vendor:true e una proprietà extends:
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, }
  Un modulo con le proprietà vendor:true, vndk.enabled:true e
  extends definisce l'estensione VNDK:
- La proprietà extendsdeve specificare un nome di libreria condivisa VNDK di base (o un nome di libreria condivisa VNDK-SP).
- Le estensioni VNDK (o VNDK-SP) prendono il nome dai moduli di base
  da cui si estendono. Ad esempio, il binario di output di
  libvndk_extèlibvndk.soanzichélibvndk_ext.so.
- Le estensioni VNDK vengono installate in /vendor/lib[64]/vndk.
- Le estensioni VNDK-SP vengono installate in
  /vendor/lib[64]/vndk-sp.
- Le librerie condivise di base devono avere sia vndk.enabled:truechevendor_available:true.
  Un'estensione VNDK-SP deve estendersi da una libreria condivisa VNDK-SP
  (vndk.support_system_process deve essere uguale):
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, }, }
Le estensioni VNDK (o VNDK-SP) possono dipendere da altre librerie condivise del fornitore:
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, }
Utilizzare le estensioni VNDK
  Se un modulo fornitore dipende da API aggiuntive definite dalle estensioni VNDK, il
  modulo deve specificare il nome dell'estensione VNDK nella relativa proprietà
  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", ], }
  Se un modulo fornitore dipende dalle estensioni VNDK, queste vengono
  installate automaticamente in /vendor/lib[64]/vndk[-sp]. Se un modulo
  non dipende più da un'estensione VNDK, aggiungi un passaggio di pulizia a
  CleanSpec.mk per rimuovere la libreria condivisa. Ad esempio:
$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)
Compilazione condizionale
Questa sezione descrive come gestire le sottili differenze (ad es. aggiunta o rimozione di una funzionalità da una delle varianti) tra le seguenti tre librerie condivise VNDK:
- Variante principale (ad es. /system/lib[64]/libexample.so)
- Variante del fornitore (ad es.
  /apex/com.android.vndk.v${VER}/lib[64]/libexample.so)
- Estensione VNDK (ad es. /vendor/lib[64]/vndk[-sp]/libexample.so)
Flag del compilatore condizionali
  Il sistema di build di Android definisce __ANDROID_VNDK__ per le varianti del fornitore
  e le estensioni VNDK per impostazione predefinita. Puoi proteggere il codice
  con le protezioni del preprocessor C:
void all() { }
#if !defined(__ANDROID_VNDK__)
void framework_only() { }
#endif
#if defined(__ANDROID_VNDK__)
void vndk_only() { }
#endif
  Oltre a __ANDROID_VNDK__, in Android.bp possono essere specificati cflags o
  cppflags diversi. L'elemento
  cflags o cppflags specificato in
  target.vendor è specifico della variante del fornitore.
  Ad esempio, il seguente Android.bp definisce
  libexample e 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", ], }
  Ecco l'elenco dei codici di 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() { }
#endifSecondo questi due file, il sistema di build genera librerie condivise con i seguenti simboli esportati:
| Percorso di installazione | Simboli esportati | 
|---|---|
| /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,vndkevndk_ext | 
Requisiti per i simboli esportati
  Lo strumento di controllo ABI VNDK
  confronta l'ABI delle varianti fornitore VNDK e delle
  estensioni VNDK con i dump ABI di riferimento in
  prebuilts/abi-dumps/vndk.
- I simboli esportati dalle varianti del fornitore VNDK (ad es.
  /apex/com.android.vndk.v${VER}/lib[64]/libexample.so) devono essere identici ai simboli definiti nei dump ABI (non i superset).
- I simboli esportati dalle estensioni VNDK (ad es.
  /vendor/lib[64]/vndk/libexample.so) devono essere superset dei simboli definiti nei dump ABI.
Se le varianti fornitore VNDK o le estensioni VNDK non rispettano i requisiti sopra indicati, il controllo ABI VNDK genera errori di build e interrompe la build.
Escludere i file di origine o le librerie condivise dalle varianti del fornitore
  Per escludere i file di origine dalla variante del fornitore, aggiungili alla proprietà
  exclude_srcs. Allo stesso modo, per assicurarti che le librerie condivise non siano collegate alla variante del fornitore, aggiungile alla proprietà exclude_shared_libs. Ad esempio:
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 questo esempio, la variante principale di libexample_cond_exclude
  include il codice di fwk.c e both.c e dipende
  dalle librerie condivise libfwk_only e libboth. La
  variante fornitore di libexample_cond_exclude include solo il codice
  di both.c perché fwk.c è escluso dalla
  proprietà exclude_srcs. Analogamente, dipende solo dalla raccolta condivisa
  libboth perché libfwk_only è esclusa dalla proprietà
  exclude_shared_libs.
Esportare le intestazioni dalle estensioni VNDK
Un'estensione VNDK può aggiungere nuove classi o nuove funzioni a una libreria condivisa VNDK. Ti consigliamo di mantenere queste dichiarazioni in intestazioni indipendenti ed evitare di modificare le intestazioni esistenti.
  Ad esempio, viene creato un nuovo file di intestazione
  include-ext/example/ext/feature_name.h per l'estensione
  VNDK libexample_ext:
- Android.bp
- include-ext/example/ext/feature_name.h
- include/example/example.h
- src/example.c
- src/ext/feature_name.c
  Nel seguente Android.bp, le esportazioni libexample
  solo include, mentre libexample_ext esporta sia
  include che include-ext. In questo modo, gli utenti di
  libexample non includeranno
  feature_name.h per errore:
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", }, }
  Se la separazione delle estensioni in file di intestazione indipendenti non è fattibile, un'alternativa è aggiungere protezioni #ifdef. Tuttavia, assicurati che tutti
  gli utenti dell'estensione VNDK aggiungano i flag di definizione. Puoi definire
  cc_defaults per aggiungere flag di definizione a cflags e collegare
  le librerie condivise con shared_libs.
  Ad esempio, per aggiungere una nuova funzione membro Example2::get_b() all'estensione VNDK libexample2_ext, devi modificare il file di intestazione esistente e aggiungere una protezione #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 cc_defaults denominato libexample2_ext_defaults è
  definito per gli utenti di 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", ], }
  Gli utenti di libexample2_ext possono semplicemente includere
  libexample2_ext_defaults nella proprietà defaults:
cc_binary {
    name: "example2_user_executable",
    defaults: ["libexample2_ext_defaults"],
    vendor: true,
}Pacchetti prodotto
  Nel sistema di build di Android, la variabile PRODUCT_PACKAGES
  specifica gli eseguibili, le librerie condivise o i pacchetti che devono essere
  installati nel dispositivo. Anche le dipendenze transitive dei moduli specificati vengono installate implicitamente nel dispositivo.
  Se BOARD_VNDK_VERSION è attivato, i moduli con
  vendor_available o vndk.enabled ricevono un trattamento
  speciale. Se un modulo framework dipende da un modulo con
  vendor_available o vndk.enabled, la variante core
  è inclusa nel set di installazione transitiva. Se un modulo fornitore
  dipende da un modulo con vendor_available, la variante fornitore è
  inclusa nel set di installazione transitivo. Tuttavia, le varianti dei moduli del fornitore
  con vndk.enabled vengono installate indipendentemente dal fatto che vengano utilizzate o meno dai moduli del fornitore.
  Quando le dipendenze sono invisibili al sistema di compilazione (ad es. librerie condivise
  che possono essere aperte con dlopen() in fase di runtime), devi specificare
  i nomi dei moduli in PRODUCT_PACKAGES per installarli
  in modo esplicito.
  Se un modulo ha vendor_available o vndk.enabled,
  il nome del modulo indica la sua variante principale. Per specificare esplicitamente la
  variante del fornitore in PRODUCT_PACKAGES, aggiungi un suffisso .vendor
  al nome del modulo. Ad esempio:
cc_library { name: "libexample", srcs: ["example.c"], vendor_available: true, }
  In questo esempio, libexample sta per
  /system/lib[64]/libexample.so e libexample.vendor
  sta per /vendor/lib[64]/libexample.so. Per installare
  /vendor/lib[64]/libexample.so, aggiungi libexample.vendor
  a PRODUCT_PACKAGES:
PRODUCT_PACKAGES += libexample.vendor
