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:true
dipende da un modulo convendor:true
oppure - un modulo con
vendor:true
dipende da un modulo nonllndk_library
che non ha névendor:true
né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
_PRIVATE
o_PLATFORM
, - Non ha il tag
#platform-only
e - 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_libs
e/oshared_libs
, devono essere unllndk_library
o un modulo convendor_available
ovndk.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:true
non 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à
extends
deve 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.so
anziché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:true
chevendor_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() { } #endif
Secondo 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 , vndk e vndk_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