En Android 8.1 y versiones posteriores, el sistema de compilación tiene compatibilidad con VNDK integrada. Cuando la compatibilidad con VNDK está habilitada, el sistema de compilación verifica las dependencias entre los módulos, crea una variante específica del proveedor para los módulos del proveedor e instala automáticamente esos módulos en los directorios designados.
Ejemplo de soporte de compilación de VNDK
En este ejemplo, la definición del módulo Android.bp
define una biblioteca denominada libexample
. La propiedad del proveedor_disponible indica que los módulos del marco y los módulos del proveedor pueden depender libexample
vendor_available
Tanto el ejecutable del marco /system/bin/foo
como el ejecutable del proveedor /vendor/bin/bar
dependen de libexample
y tienen libexample
en sus propiedades shared_libs
.
Si libexample
es utilizado tanto por módulos de marco como por módulos de proveedores, se construyen dos variantes de libexample
. La variante principal (llamada así por libexample
) es utilizada por los módulos de marco y la variante de proveedor (llamada así por libexample.vendor
) es utilizada por los módulos de proveedor. Las dos variantes se instalan en directorios diferentes:
- La variante principal se instala en
/system/lib[64]/libexample.so
. - La variante del proveedor se instala en VNDK APEX porque
vndk.enabled
estrue
.
Para obtener más detalles, consulte Definición del módulo .
Configuración del soporte de compilación
Para habilitar la compatibilidad completa del sistema de compilación para un dispositivo de producto, agregue BOARD_VNDK_VERSION
a BoardConfig.mk
:
BOARD_VNDK_VERSION := current
Esta configuración tiene un efecto global : cuando se define en BoardConfig.mk
, se comprueban todos los módulos. Como no existe un mecanismo para incluir en la lista negra o en la lista blanca un módulo ofensivo, debe limpiar todas las dependencias innecesarias antes de agregar BOARD_VNDK_VERSION
. Puede probar y compilar un módulo configurando BOARD_VNDK_VERSION
en sus variables de entorno:
$ BOARD_VNDK_VERSION=current m module_name.vendor
Cuando BOARD_VNDK_VERSION
está habilitado, se eliminan varias rutas de búsqueda de encabezado global predeterminadas. Éstos incluyen:
-
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 módulo depende de los encabezados de estos directorios, debe especificar (explícitamente) las dependencias con header_libs
, static_libs
y/o shared_libs
.
ÁPICE VNDK
En Android 10 y versiones anteriores, los módulos con vndk.enabled
se instalaron en /system/lib[64]/vndk[-sp]-${VER}
. En Android 11 y versiones posteriores, las bibliotecas VNDK están empaquetadas en formato APEX y el nombre de VNDK APEX es com.android.vndk.v${VER}
. Según la configuración del dispositivo, VNDK APEX se aplana o no y está disponible desde la ruta canónica /apex/com.android.vndk.v${VER}
.
Definición de módulo
Para compilar Android con BOARD_VNDK_VERSION
, debe revisar la definición del módulo en Android.mk
o Android.bp
. Esta sección describe diferentes tipos de definiciones de módulos, varias propiedades de módulos relacionadas con VNDK y comprobaciones de dependencia implementadas en el sistema de compilación.
Módulos de proveedores
Los módulos de proveedor son ejecutables específicos del proveedor o bibliotecas compartidas que deben instalarse en una partición del proveedor. En los archivos Android.bp
, los módulos de proveedor deben establecer la propiedad de propietario o proveedor en true
. En los archivos Android.mk
, los módulos de proveedores deben establecer LOCAL_VENDOR_MODULE
o LOCAL_PROPRIETARY_MODULE
en true
.
Si se define BOARD_VNDK_VERSION
, el sistema de compilación no permite las dependencias entre los módulos del proveedor y los módulos del marco y emite errores si:
- un módulo sin
vendor:true
depende de un módulo convendor:true
, o - un módulo con
vendor:true
depende de un módulo que no esllndk_library
que no tienevendor:true
nivendor_available:true
.
La verificación de dependencia se aplica a header_libs
, static_libs
y shared_libs
en Android.bp
, y a LOCAL_HEADER_LIBRARIES
, LOCAL_STATIC_LIBRARIES
y LOCAL_SHARED_LIBRARIES
en Android.mk
.
LL-NDK
Las bibliotecas compartidas LL-NDK son bibliotecas compartidas con ABI estables. Tanto el marco como los módulos del proveedor comparten la misma y la última implementación. Para cada biblioteca compartida LL-NDK, Android.bp
contiene una definición de módulo llndk_library
:
llndk_library { name: "libvndksupport", symbol_file: "libvndksupport.map.txt", }
Esta definición de módulo especifica un nombre de módulo y un archivo de símbolos que describe los símbolos visibles para los módulos del proveedor. Por ejemplo:
LIBVNDKSUPPORT { global: android_load_sphal_library; # llndk android_unload_sphal_library; # llndk local: *; };
Según el archivo de símbolos, el sistema de compilación genera una biblioteca compartida de código auxiliar para los módulos del proveedor, que se vinculan con estas bibliotecas cuando BOARD_VNDK_VERSION
está habilitado. Un símbolo se incluye en la biblioteca compartida de código auxiliar solo si:
- No está definido en la sección final con
_PRIVATE
o_PLATFORM
, - No tiene la etiqueta
#platform-only
y - No tiene etiquetas
#introduce*
o la etiqueta coincide con el objetivo.
VNDK
En los archivos Android.bp
, las definiciones de los módulos cc_library
, cc_library_static
, cc_library_shared
y cc_library_headers
admiten tres propiedades relacionadas con VNDK: vendor_available
, vndk.enabled
y vndk.support_system_process
.
Si vendor_available
o vndk.enabled
es true
, se pueden crear dos variantes ( núcleo y proveedor ). La variante principal debe tratarse como un módulo de marco y la variante de proveedor debe tratarse como un módulo de proveedor. Si algunos módulos del marco dependen de este módulo, se crea la variante principal. Si algunos módulos de proveedor dependen de este módulo, se crea la variante de proveedor. El sistema de compilación impone las siguientes comprobaciones de dependencia:
- La variante principal siempre es solo de marco e inaccesible para los módulos del proveedor.
- La variante del proveedor siempre es inaccesible para los módulos del marco.
- Todas las dependencias de la variante del proveedor, que se especifican en
header_libs
,static_libs
y/oshared_libs
, deben ser unallndk_library
o un módulo convendor_available
ovndk.enabled
. - Si el
vendor_available
estrue
, la variante del proveedor es accesible para todos los módulos del proveedor. - Si
vendor_available
esfalse
, la variante de proveedor solo es accesible para otros módulos VNDK o VNDK-SP (es decir, los módulos convendor:true
no pueden vincular módulos proveedor_disponiblevendor_available:false
).
La ruta de instalación predeterminada para cc_library
o cc_library_shared
está determinada por las siguientes reglas:
- La variante principal se instala en
/system/lib[64]
. - La ruta de instalación de la variante del proveedor puede variar:
- Si
vndk.enabled
esfalse
, la variante del proveedor se instala en/vendor/lib[64]
. - Si
vndk.enabled
estrue
, la variante del proveedor se instala en VNDK APEX (com.android.vndk.v${VER}
).
- Si
La siguiente tabla resume cómo el sistema de compilación maneja las variantes del proveedor:
vendedor_disponible | vndk activado | vndk soporte_mismo_proceso | Descripciones de variantes de proveedores |
---|---|---|---|
true | false | false | Las variantes de proveedor son VND-ONLY . Las bibliotecas compartidas se instalan en /vendor/lib[64] . |
true | No válido (error de compilación) | ||
true | false | Las variantes de proveedor son VNDK . Las bibliotecas compartidas se instalan en VNDK APEX. | |
true | Las variantes de proveedor son VNDK-SP . Las bibliotecas compartidas se instalan en VNDK APEX. | ||
| | | Sin variantes de proveedor. Este módulo es FWK-ONLY . |
true | No válido (error de compilación) | ||
true | false | Las variantes de proveedor son VNDK-Private . Las bibliotecas compartidas se instalan en VNDK APEX. Estos no deben ser utilizados directamente por módulos de proveedores. | |
true | Las variantes de proveedor son VNDK-SP-Private . Las bibliotecas compartidas se instalan en VNDK APEX. Estos no deben ser utilizados directamente por módulos de proveedores. |
extensiones VNDK
Las extensiones de VNDK son bibliotecas compartidas de VNDK con API adicionales. Las extensiones se instalan en /vendor/lib[64]/vndk[-sp]
(sin sufijo de versión) y anulan las bibliotecas compartidas originales de VNDK en tiempo de ejecución.
Definición de extensiones VNDK
En Android 9 y versiones posteriores, Android.bp
admite de forma nativa las extensiones VNDK. Para construir una extensión VNDK, defina otro módulo con un vendor:true
y una propiedad extends
:
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, }
Un módulo con las propiedades vendor:true
, vndk.enabled:true
y extends
define la extensión VNDK:
- La propiedad
extends
debe especificar un nombre de biblioteca compartida de VNDK base (o un nombre de biblioteca compartida de VNDK-SP). - Las extensiones VNDK (o extensiones VNDK-SP) reciben el nombre de los nombres del módulo base desde el que se extienden. Por ejemplo, el binario de salida de
libvndk_ext
eslibvndk.so
en lugar delibvndk_ext.so
. - Las extensiones de VNDK se instalan en
/vendor/lib[64]/vndk
. - Las extensiones de VNDK-SP se instalan en
/vendor/lib[64]/vndk-sp
. - Las bibliotecas compartidas base deben tener tanto
vndk.enabled:true
comovendor_available:true
.
Una extensión VNDK-SP debe extenderse desde una biblioteca compartida VNDK-SP ( vndk.support_system_process
debe ser igual):
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, }, }
Las extensiones VNDK (o extensiones VNDK-SP) pueden depender de bibliotecas compartidas de otros proveedores:
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, }
Uso de extensiones VNDK
Si un módulo de proveedor depende de API adicionales definidas por extensiones de VNDK, el módulo debe especificar el nombre de la extensión de VNDK en su propiedad 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 módulo de proveedor depende de extensiones VNDK, esas extensiones VNDK se instalan en /vendor/lib[64]/vndk[-sp]
automáticamente. Si un módulo ya no depende de una extensión VNDK, agregue un paso limpio a CleanSpec.mk
para eliminar la biblioteca compartida. Por ejemplo:
$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)
compilación condicional
Esta sección describe cómo lidiar con las diferencias sutiles (por ejemplo, agregar o eliminar una función de una de las variantes) entre las siguientes tres bibliotecas compartidas de VNDK:
- Variante principal (por ejemplo
/system/lib[64]/libexample.so
) - Variante de proveedor (por ejemplo
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) - Extensión VNDK (por ejemplo
/vendor/lib[64]/vndk[-sp]/libexample.so
)
Indicadores del compilador condicional
El sistema de compilación de Android define __ANDROID_VNDK__
para variantes de proveedores y extensiones de VNDK de forma predeterminada. Puede proteger el código con los protectores del preprocesador C:
void all() { } #if !defined(__ANDROID_VNDK__) void framework_only() { } #endif #if defined(__ANDROID_VNDK__) void vndk_only() { } #endif
Además de __ANDROID_VNDK__
, se pueden especificar diferentes cflags
o cppflags
en Android.bp
. Los cflags
o cppflags
especificados en target.vendor
son específicos de la variante del proveedor.
Por ejemplo, el siguiente Android.bp
define libexample
y 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", ], }
Y esta es la lista de códigos 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
De acuerdo con estos dos archivos, el sistema de compilación genera bibliotecas compartidas con los siguientes símbolos exportados:
Ruta de instalación | Símbolos exportados |
---|---|
/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 |
Requisitos sobre los símbolos exportados
El comprobador de ABI de VNDK compara el ABI de las variantes de proveedores de VNDK y las extensiones de VNDK con los volcados de ABI de referencia en prebuilts/abi-dumps/vndk
.
- Los símbolos exportados por las variantes de proveedores de VNDK (p. ej.
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) deben ser idénticos (no los superconjuntos) de los símbolos definidos en los volcados de ABI. - Los símbolos exportados por las extensiones de VNDK (p. ej.
/vendor/lib[64]/vndk/libexample.so
) deben ser superconjuntos de los símbolos definidos en los volcados de ABI.
Si las variantes del proveedor de VNDK o las extensiones de VNDK no cumplen con los requisitos anteriores, el verificador de ABI de VNDK emite errores de compilación y detiene la compilación.
Exclusión de archivos de origen o bibliotecas compartidas de variantes de proveedores
Para excluir archivos de origen de la variante del proveedor, agréguelos a la propiedad exclude_srcs
. Del mismo modo, para asegurarse de que las bibliotecas compartidas no estén vinculadas con la variante del proveedor, agregue esas bibliotecas a la propiedad exclude_shared_libs
. Por ejemplo:
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"], }, }, }
En este ejemplo, la variante principal de libexample_cond_exclude
incluye el código de fwk.c
y both.c
y depende de las bibliotecas compartidas libfwk_only
y libboth
. La variante de proveedor de libexample_cond_exclude
incluye solo el código de both.c
porque fwk.c
está excluido por la propiedad exclude_srcs
. De manera similar, depende solo de la biblioteca compartida libboth
porque libfwk_only
está excluido por la propiedad exclude_shared_libs
.
Exportar encabezados desde extensiones VNDK
Una extensión de VNDK puede agregar nuevas clases o nuevas funciones a una biblioteca compartida de VNDK. Se sugiere mantener esas declaraciones en encabezados independientes y evitar cambiar los encabezados existentes.
Por ejemplo, se crea un nuevo archivo de encabezado include-ext/example/ext/feature_name.h
para la extensión libexample_ext
:
- Android.bp
- include-ext/example/ext/feature_name.h
- incluir/ejemplo/ejemplo.h
- src/ejemplo.c
- src/ext/feature_name.c
En el siguiente Android.bp
, las exportaciones de libexample
solo include
, mientras que las exportaciones de libexample_ext
include
e include-ext
. Esto garantiza que los usuarios de feature_name.h
no incluyan incorrectamente 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", }, }
Si no es factible separar las extensiones en archivos de encabezado independientes, una alternativa es agregar #ifdef
. Sin embargo, asegúrese de que todos los usuarios de la extensión VNDK agreguen los indicadores definidos. Puede definir cc_defaults
para agregar indicadores definidos a cflags
y vincular bibliotecas compartidas con shared_libs
.
Por ejemplo, para agregar una nueva función miembro Example2::get_b()
a la extensión libexample2_ext
, debe modificar el archivo de encabezado existente y agregar una protección #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_
Se define un cc_defaults
llamado libexample2_ext_defaults
para los usuarios 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", ], }
Los usuarios de libexample2_ext
pueden simplemente incluir libexample2_ext_defaults
en su propiedad por defaults
:
cc_binary { name: "example2_user_executable", defaults: ["libexample2_ext_defaults"], vendor: true, }
Paquetes de productos
En el sistema de compilación de Android, la variable PRODUCT_PACKAGES
especifica los ejecutables, las bibliotecas compartidas o los paquetes que deben instalarse en el dispositivo. Las dependencias transitivas de los módulos especificados también se instalan implícitamente en el dispositivo.
Si BOARD_VNDK_VERSION
está habilitado, los módulos con vendor_available
o vndk.enabled
reciben un tratamiento especial. Si un módulo de marco depende de un módulo con vendor_available
o vndk.enabled
, la variante principal se incluye en el conjunto de instalación transitiva. Si un módulo de proveedor depende de un módulo con vendor_available
, la variante de proveedor se incluye en el conjunto de instalación transitiva. Sin embargo, las variantes de los proveedores de los módulos con vndk.enabled
se instalan independientemente de si los utilizan o no los módulos del proveedor.
Cuando las dependencias son invisibles para el sistema de compilación (por ejemplo, bibliotecas compartidas que pueden abrirse con dlopen()
en tiempo de ejecución), debe especificar los nombres de los módulos en PRODUCT_PACKAGES
para instalar esos módulos explícitamente.
Si un módulo tiene vendor_available
o vndk.enabled
, el nombre del módulo representa su variante principal. Para especificar explícitamente la variante del proveedor en PRODUCT_PACKAGES
, agregue un sufijo .vendor
al nombre del módulo. Por ejemplo:
cc_library { name: "libexample", srcs: ["example.c"], vendor_available: true, }
En este ejemplo, libexample
significa /system/lib[64]/libexample.so
y libexample.vendor
significa /vendor/lib[64]/libexample.so
. Para instalar /vendor/lib[64]/libexample.so
, agregue libexample.vendor
a PRODUCT_PACKAGES
:
PRODUCT_PACKAGES += libexample.vendor