Compatibilidad con el sistema de compilación del VNDK

En Android 8.1 y versiones posteriores, el sistema de compilación tiene compatibilidad integrada con VNDK. Cuándo La compatibilidad con VNDK está habilitada, el sistema de compilación verifica las dependencias entre compila una variante específica del proveedor para los módulos de proveedor y instala automáticamente esos módulos en directorios designados.

Ejemplo de compatibilidad con la compilación VNDK

En este ejemplo, la definición del módulo Android.bp define una biblioteca llamada libexample. El vendor_available indica que los módulos del framework y los módulos de los proveedores pueden depender libexample

libexample provider_available:true y vndk.enabled:true

Figura 1: Compatibilidad habilitada

El framework ejecutable /system/bin/foo y el proveedor ejecutables /vendor/bin/bar dependen de libexample y tienen libexample en sus propiedades shared_libs.

Si el proveedor y los módulos del framework usan libexample se compilan dos variantes de libexample. La variante principal (con el nombre de libexample) se usan en los módulos del framework y la El proveedor utiliza la variante de proveedor (con el nombre libexample.vendor). módulos. 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 APEX de VNDK debido a lo siguiente: vndk.enabled es true.

Para obtener más detalles, consulta la definición del módulo.

Cómo configurar la compatibilidad con compilaciones

Para habilitar la compatibilidad total con el sistema de compilación para un dispositivo de producto, agrega De BOARD_VNDK_VERSION a BoardConfig.mk:

BOARD_VNDK_VERSION := current

Este parámetro de configuración tiene un efecto global: cuando se define en BoardConfig.mk, se verificaron todos los módulos. Como no hay un mecanismo para incluir en la lista negra o la lista blanca un módulo ofensivo, debes borrar todo las dependencias innecesarias antes de agregar BOARD_VNDK_VERSION. Tú puedes probar y compilar un módulo configurando BOARD_VNDK_VERSION en tus variables de entorno:

$ BOARD_VNDK_VERSION=current m module_name.vendor

Cuando se habilita BOARD_VNDK_VERSION, varias configuraciones globales se quitan las rutas de búsqueda de encabezados. Por ejemplo:

  • 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, debes especificar (De forma explícita) las dependencias con header_libs, static_libs o shared_libs.

APEX del VNDK

En Android 10 y versiones anteriores, los módulos con vndk.enabled se instalaban en /system/lib[64]/vndk[-sp]-${VER} En Android 11 y versiones posteriores, Las bibliotecas de VNDK se empaquetan en formato APEX y el nombre de ese formato es com.android.vndk.v${VER} Según la configuración del dispositivo, VNDK APEX está plano o sin compactar, y está disponible en la ruta canónica /apex/com.android.vndk.v${VER}

APEX del VNDK

Figura 2: APEX de VNDK

Definición del módulo

Para compilar Android con BOARD_VNDK_VERSION, debes revisar el definición del módulo en Android.mk o Android.bp En esta sección, se describen diferentes tipos de módulos definiciones, varias propiedades de módulos relacionadas con VNDK y verificaciones de dependencias implementadas en el sistema de compilación.

Módulos de proveedores

Los módulos de proveedor son bibliotecas compartidas o ejecutables específicos del proveedor que debe instalarse en una partición del proveedor. En Android.bp archivos, Los módulos de proveedor deben establecer el proveedor o la propiedad de propiedad en true. En archivos Android.mk, los módulos de proveedores deben establecer LOCAL_VENDOR_MODULE o LOCAL_PROPRIETARY_MODULE para true

Si se define BOARD_VNDK_VERSION, el sistema de compilación no permite las dependencias entre los módulos de proveedores y los módulos del framework, 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 que no es llndk_library y que no tiene vendor:true ni vendor_available:true.

La verificación de dependencias se aplica a header_libs, static_libs y shared_libs en Android.bp y, para LOCAL_HEADER_LIBRARIES, LOCAL_STATIC_LIBRARIES y LOCAL_SHARED_LIBRARIES en Android.mk

LL-NDK

Las bibliotecas compartidas de LL-NDK son bibliotecas compartidas con ABI estables. Ambos framework y proveedores comparten la misma implementación, la más reciente. Por cada En la biblioteca compartida de LL-NDK, cc_library contiene un Propiedad llndk con un archivo de símbolos:

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

El archivo de símbolos describe los símbolos visibles para los módulos de los proveedores. 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 stub para módulos de proveedores, que se vinculan con estas bibliotecas cuando Se habilitó BOARD_VNDK_VERSION. El código auxiliar incluye un símbolo biblioteca compartida solo si:

  • No está definido al final de la sección con _PRIVATE o _PLATFORM,
  • No tiene la etiqueta #platform-only.
  • No tiene etiquetas #introduce* o la etiqueta coincide con el objetivo.

VNDK

En los archivos Android.bp, cc_library, cc_library_static, cc_library_shared y Las definiciones del módulo cc_library_headers admiten tres tipos propiedades: vendor_available, vndk.enabled y vndk.support_system_process

Si vendor_available o vndk.enabled es true, hay dos variantes (núcleo y proveedor) que se construyen. La variante principal se debe tratar como un módulo de framework y se debe tratar al proveedor variante debe tratarse como un módulo de proveedor. Si algunos módulos del framework dependen en este módulo, se compila la variante principal. Si algunos módulos de proveedores depender de este módulo, se compila la variante del proveedor. El sistema de compilación aplica la siguiente verificación de dependencias:

  • La variante principal siempre es exclusiva del framework y es inaccesible para el proveedor. módulos.
  • Los módulos del framework no siempre pueden acceder a la variante del proveedor.
  • Todas las dependencias de la variante del proveedor, que se especifican en header_libs, static_libs o shared_libs, debe ser llndk_library o módulo con vendor_available o vndk.enabled.
  • Si vendor_available es true, la variante del proveedor sea accesible para todos los módulos de proveedores.
  • Si vendor_available es false, la variante del proveedor será accesible únicamente para otros módulos VNDK o VNDK-SP (es decir, módulos con vendor:true no puede vincular vendor_available:false módulos).

La ruta de instalación predeterminada para cc_library o cc_library_shared se determina según las siguientes reglas:

  • La variante principal se instala en /system/lib[64].
  • El proceso de instalación de la variante del proveedor puede variar:
    • Si vndk.enabled es false, la variante del proveedor está instalada en /vendor/lib[64].
    • Si vndk.enabled es true, la variante del proveedor esté instalado en VNDK APEX(com.android.vndk.v${VER}).

En la siguiente tabla, se resume la forma en que el sistema de compilación maneja las variantes de los proveedores:

proveedor_disponible vndk
habilitado
vndk
support_same_process
Descripciones de variantes del proveedor
true false false Las variantes de proveedores son SOLO VND. Las bibliotecas compartidas son Se instaló en /vendor/lib[64].
true No válido (error de compilación)
true false Las variantes de proveedores son VNDK. Se instalaron las bibliotecas compartidas a VNDK APEX.
true Las variantes de proveedores son VNDK-SP. Las bibliotecas compartidas son instalarse en VNDK APEX.

false

false

false

No hay variantes de proveedores. Este módulo es SOLO PARA FWK.

true No válido (error de compilación)
true false Las variantes de proveedores son VNDK-Private. Las bibliotecas compartidas son instalarse en VNDK APEX. Estas no deben ser que los módulos de los proveedores usan directamente.
true Las variantes de proveedores son VNDK-SP-Private. Las bibliotecas compartidas son instalarse en VNDK APEX. Estas no deben ser que los módulos de los proveedores usan directamente.

Extensiones del VNDK

Las extensiones del VNDK son bibliotecas compartidas del VNDK con APIs adicionales. Las extensiones son instalada en /vendor/lib[64]/vndk[-sp] (sin sufijo de versión) y anular las bibliotecas compartidas del VNDK original en el tiempo de ejecución.

Cómo definir las extensiones del VNDK

En Android 9 y versiones posteriores, Android.bp es compatible de forma nativa con VNDK. extensiones. Para compilar una extensión de VNDK, define otro módulo con una 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 Las propiedades de extends definen la extensión de VNDK:

  • La propiedad extends debe especificar una biblioteca compartida de VNDK base nombre de la biblioteca (o el nombre de la biblioteca compartida VNDK-SP).
  • Las extensiones del VNDK (o extensiones VNDK-SP) llevan el nombre del módulo básico. los nombres con los que se extienden. Por ejemplo, el objeto binario de salida de libvndk_ext es libvndk.so en lugar de libvndk_ext.so
  • Las extensiones del 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 del VNDK (o extensiones del VNDK-SP) pueden depender de las herramientas compartidas por otros proveedores. bibliotecas:

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

Cómo usar extensiones del VNDK

Si un módulo de proveedor depende de APIs adicionales definidas por las extensiones del VNDK, el 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 extensiones del VNDK, esas extensiones se Se instalará en /vendor/lib[64]/vndk[-sp] automáticamente. Si un módulo ya no depende de una extensión VNDK, agrega un paso limpio a CleanSpec.mk para quitar la biblioteca compartida. Por ejemplo:

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

Compilación condicional

En esta sección, se describe cómo abordar las diferencias sutiles (p.ej., agregar o quitar una función de una de las variantes) entre las siguientes tres bibliotecas compartidas VNDK:

  • Variante principal (p.ej., /system/lib[64]/libexample.so)
  • Variante del proveedor (p.ej., /apex/com.android.vndk.v${VER}/lib[64]/libexample.so)
  • Extensión VNDK (p.ej., /vendor/lib[64]/vndk[-sp]/libexample.so)

Marcas condicionales del compilador

El sistema de compilación de Android define __ANDROID_VNDK__ para el proveedor. variantes y extensiones del VNDK de forma predeterminada. Puedes proteger el código con las protecciones del preprocesador de C:

void all() { }

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

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

Además de __ANDROID_VNDK__, diferentes cflags o Se puede especificar cppflags en Android.bp. El cflags o cppflags especificados en target.vendor es específico 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",
    ],
}

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 y vndk_ext

Requisitos para los símbolos exportados

El verificador de ABI del VNDK compara la ABI de las variantes de los proveedores del VNDK y Extensiones del VNDK a los volcados de ABI de referencia en prebuilts/abi-dumps/vndk

  • Símbolos exportados por variantes de proveedores del VNDK (p.ej., /apex/com.android.vndk.v${VER}/lib[64]/libexample.so) deben ser idénticos a los símbolos definidos en los volcados de ABI (no a los superconjuntos de estos).
  • Símbolos exportados por extensiones de VNDK (p.ej., /vendor/lib[64]/vndk/libexample.so) deben ser superconjuntos de la definidos en los volcados de ABI.

Si no se cumplen las variantes de los proveedores del VNDK ni las extensiones del VNDK de acuerdo con los requisitos anteriores, el verificador de ABI del VNDK emite errores de compilación y detiene la compilar.

Cómo excluir archivos de origen o bibliotecas compartidas de variantes de proveedores

Para excluir archivos fuente de la variante del proveedor, agrégalos al exclude_srcs. Del mismo modo, para garantizar que las bibliotecas compartidas no está vinculada con la variante del proveedor, agrega esas bibliotecas a la 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, se muestra la variante principal de libexample_cond_exclude incluye el código de fwk.c y both.c, y depende en las bibliotecas compartidas libfwk_only y libboth. El variante de proveedor de libexample_cond_exclude incluye solo el código de both.c porque fwk.c es excluido por exclude_srcs. Del mismo modo, solo depende de la biblioteca compartida libboth porque libfwk_only es excluido por el propiedad exclude_shared_libs.

Cómo exportar encabezados de extensiones de VNDK

Una extensión del VNDK puede agregar clases o funciones nuevas a un VNDK compartido. biblioteca. Se recomienda mantener esas declaraciones en encabezados independientes y evita cambiar los encabezados existentes.

Por ejemplo, un archivo de encabezado nuevo Se crea include-ext/example/ext/feature_name.h para el VNDK extensión libexample_ext:

  • Android.bp
  • include-ext/example/ext/nombre_de_función.h
  • include/example/example.h
  • src/ejemplo.c
  • src/ext/feature_name.c

En el siguiente Android.bp, libexample exportaciones solo include, mientras que libexample_ext exporta ambas include y include-ext. Esto garantiza feature_name.h no se incluirán incorrectamente en 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 con archivos de encabezado independientes, un como alternativa, puedes agregar protecciones #ifdef. Sin embargo, asegúrate de que todos Los usuarios de la extensión VNDK agregan las marcas de definición. Puedes definir cc_defaults para agregar marcas de definición a cflags y vincular bibliotecas compartidas con shared_libs.

Por ejemplo, para agregar una nueva función de miembro Example2::get_b() a la extensión libexample2_ext del VNDK, debes modificar el archivo de encabezado y agrega 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_

Un cc_defaults llamado libexample2_ext_defaults es definido 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 defaults propiedad:

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 se deben instalada en el dispositivo. Las dependencias transitivas del tipo módulos también se instalan implícitamente en el dispositivo.

Si habilitas BOARD_VNDK_VERSION, los módulos con vendor_available o vndk.enabled son especiales tratamiento. Si un módulo de framework depende de un módulo con vendor_available o vndk.enabled, que son la variante principal se incluye en el conjunto de instalación transitivo. Si un módulo de proveedor depende de un módulo con vendor_available, la variante de proveedor es incluido en el conjunto de instalación transitivo. Sin embargo, las variantes de módulos de proveedores con vndk.enabled se instalan sin importar si los usan o no los módulos de proveedores.

Cuando las dependencias son invisibles para el sistema de compilación (p.ej., bibliotecas compartidas) que se puede abrir con dlopen() en el tiempo de ejecución), debes especificar los nombres de los módulos en PRODUCT_PACKAGES para instalar esos módulos de forma explícita.

Si un módulo tiene vendor_available o vndk.enabled, el nombre del módulo significa su variante principal. Para especificar explícitamente el variante de proveedor en PRODUCT_PACKAGES, agrega un .vendor en el 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, agregar libexample.vendor a PRODUCT_PACKAGES:

PRODUCT_PACKAGES += libexample.vendor