Google is committed to advancing racial equity for Black communities. See how.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Compatibilidad con el sistema de compilación VNDK

En Android 8.1 y superior, el sistema de compilación tiene soporte VNDK integrado. 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 llamada libexample . La propiedad vendor_available indica que los módulos del marco y los módulos del proveedor pueden depender de libexample :

libexample vendor_available: true y vndk.enabled: true

Figura 1. Compatibilidad con VNDK habilitada

Tanto el ejecutable del framework /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 por los dos módulos de marco y de los módulos de proveedores, dos variantes de libexample se construyen. La variante principal (llamada así por libexample ) es utilizada por los módulos de marco y la variante del proveedor (llamada por libexample.vendor ) es utilizada por los módulos del proveedor. Las dos variantes se instalan en diferentes directorios:

  • La variante principal se instala en /system/lib[64]/libexample.so .
  • La variante del proveedor se instala en VNDK APEX porque vndk.enabled es true .

Para obtener más detalles, consulte Definición del módulo .

Configurar el soporte de compilación

Para habilitar el soporte completo 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 ningún mecanismo para incluir en la lista negra o blanca un módulo infractor, 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 .

VNDK APEX

En Android 10 y vndk.enabled , 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} . Dependiendo de la configuración del dispositivo, VNDK APEX es aplanada o sin aplanar y está disponible de la ruta canónica /apex/com.android.vndk.v${VER} .

VNDK APEX

Figura 2. VNDK APEX

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ódulo, varias propiedades de módulo relacionadas con VNDK y verificaciones de dependencia implementadas en el sistema de compilación.

Módulos de proveedores

Los módulos del proveedor son archivos ejecutables o bibliotecas compartidas específicos del proveedor que deben instalarse en una partición de proveedor. En los archivos Android.bp , los módulos de proveedor deben establecer la propiedad de proveedor o propietaria en true . En los archivos Android.mk , los módulos del proveedor 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 con vendor:true , o
  • un módulo con vendor:true depende de un módulo no llndk_library que no tiene vendor:true ni vendor_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 implementación y la más reciente. 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ímbolo que describe los símbolos visibles para los módulos del proveedor. Por ejemplo:

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

Basado en el archivo de símbolo, el sistema de compilación genera una biblioteca compartida de stub 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 stub solo si:

  • No está definido en la sección que termina con _PRIVATE o _PLATFORM ,
  • No tiene etiqueta #platform-only y
  • No tiene etiquetas #introduce* o la etiqueta coincide con el objetivo.

VNDK

En Android.bp archivos, cc_library , cc_library_static , cc_library_shared y cc_library_headers módulo de definiciones apoyan tres propiedades relacionadas con VNDK: vendor_available , vndk.enabled y vndk.support_system_process .

Si vendor_available o vndk.enabled es true , se pueden construir dos variantes ( core y vendor ). 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 construye 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 aplica las siguientes comprobaciones de dependencia:

  • La variante principal siempre es solo marco y es inaccesible para los módulos de los proveedores.
  • 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 / o shared_libs , deben ser una llndk_library o un módulo con vendor_available o vndk.enabled .
  • Si vendor_available es true , la variante del proveedor es accesible para todos los módulos del proveedor.
  • Si vendor_available es false , la variante del proveedor es accesible solo para otros módulos VNDK o VNDK-SP (es decir, los módulos con vendor:true no pueden vincular los módulos vendor_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 es false , la variante del proveedor se instala en /vendor/lib[64] .
    • Si vndk.enabled es true , la variante del proveedor se instala en VNDK APEX ( com.android.vndk.v${VER} ).

La siguiente tabla resume cómo el sistema de compilación maneja las variantes del proveedor:

vendor_available vndk
habilitado
vndk
support_same_process
Descripciones de variantes de proveedores
true false false Las variantes del proveedor son SOLO VND . Las bibliotecas compartidas se instalan en /vendor/lib[64] .
true No válido (error de compilación)
true false Las variantes del proveedor son VNDK . Las bibliotecas compartidas se instalan en VNDK APEX.
true Las variantes del proveedor son VNDK-SP . Las bibliotecas compartidas se instalan en VNDK APEX.

false

false

false

Sin variantes de proveedor. Este módulo es SÓLO FWK .

true No válido (error de compilación)
true false Las variantes del 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 del 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 VNDK son bibliotecas compartidas VNDK con API adicionales. Las extensiones se instalan en /vendor/lib[64]/vndk[-sp] (sin sufijo de versión) y anulan las bibliotecas compartidas de VNDK originales en tiempo de ejecución.

Definición de extensiones VNDK

En Android 9 y superior, Android.bp compatible de forma nativa con las extensiones VNDK. Para crear 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 vendor:true , vndk.enabled:true , y extends propiedades 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 es libvndk.so lugar de libvndk_ext.so .
  • Las extensiones VNDK se instalan en /vendor/lib[64]/vndk .
  • Las extensiones VNDK-SP se instalan en /vendor/lib[64]/vndk-sp .
  • Las bibliotecas compartidas base deben tener vndk.enabled:true y vendor_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 las 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,
}

Usando extensiones VNDK

Si un módulo de proveedor depende de API adicionales definidas por extensiones VNDK, el módulo debe especificar el nombre de la extensión 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 las 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 (p /system/lib[64]/libexample.so Ej., /system/lib[64]/libexample.so )
  • Variante de proveedor (p /apex/com.android.vndk.v${VER}/lib[64]/libexample.so Ej., /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 VNDK de forma predeterminada. Puede proteger el código con las protecciones 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 . Las cflags o cppflags especificadas en target.vendor son específicas 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ódigo 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

Según 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 de los símbolos exportados

El verificador VNDK ABI compara la 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 variantes de proveedores de VNDK (por ejemplo, /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 extensiones VNDK (por ejemplo, /vendor/lib[64]/vndk/libexample.so ) deben ser superconjuntos de los símbolos definidos en los volcados ABI.

Si las variantes del proveedor de VNDK o las extensiones de VNDK no cumplen los requisitos anteriores, el verificador ABI de VNDK emite errores de compilación y detiene la compilación.

Excluir 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 both.c 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á excluida por la propiedad exclude_shared_libs .

Exportar encabezados de extensiones VNDK

Una extensión VNDK puede agregar nuevas clases o nuevas funciones a una biblioteca compartida 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 de libexample_ext :

  • Android.bp
  • include-ext / example / ext / feature_name.h
  • incluir / ejemplo / ejemplo.h
  • src / example.c
  • src / ext / feature_name.c

En el siguiente Android.bp , libexample exportaciones de libexample solo include , mientras que libexample_ext exportaciones de libexample_ext include y include-ext . Esto asegura que feature_name.h no sea incluido incorrectamente por los usuarios 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",
    },
}

Si no es posible separar las extensiones de los archivos de encabezado independientes, una alternativa es agregar guardias #ifdef . Sin embargo, asegúrese de que todos los usuarios de la extensión VNDK agreguen las banderas de definición. Puede definir cc_defaults para agregar banderas cflags 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 cc_defaults 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 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 proveedores de módulos con vndk.enabled se instalan independientemente de que los utilicen o no los módulos de proveedores.

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