Suporte ao sistema de build do VNDK

No Android 8.1 e versões mais recentes, o sistema de build tem suporte integrado ao VNDK. Quando a compatibilidade com o VNDK estiver ativada, o sistema de compilação verificará as dependências entre módulos, cria uma variante específica do fornecedor para os módulos do fornecedor e instala esses módulos automaticamente nos diretórios designados.

Exemplo de suporte de build do VNDK

Neste exemplo, a definição do módulo Android.bp define um chamada libexample. O vendor_available indica que os módulos de framework e de fornecedor podem depender libexample:

libexamplevendor_available:true e vndk.enabled:true

Figura 1. Suporte ativado.

O executável do framework /system/bin/foo e o fornecedor /vendor/bin/bar executável dependem de libexample e têm libexample nas propriedades shared_libs.

Se libexample for usado pelos módulos do framework e pelo fornecedor módulos, são criadas duas variantes de libexample. A variante principal (nomeado de acordo com libexample) é usado por módulos de framework e o variante do fornecedor (com o nome de libexample.vendor) é usada pelo fornecedor módulos. As duas variantes são instaladas em diretórios diferentes:

  • A variante principal é instalada /system/lib[64]/libexample.so:
  • A variante do fornecedor é instalada no VNDK APEX porque vndk.enabled é true.

Para mais detalhes, consulte Definição do módulo.

Configurar o suporte a build

Para ativar o suporte completo ao sistema de build em um dispositivo de produto, adicione De BOARD_VNDK_VERSION a BoardConfig.mk:

BOARD_VNDK_VERSION := current

Esta configuração tem efeito global: quando definida em BoardConfig.mk, todos os módulos estão marcados. Como não há mecanismo adicionar um módulo ofensivo à lista de proibições ou à lista de permissões, limpe dependências desnecessárias antes de adicionar BOARD_VNDK_VERSION. Você pode testar e compilar um módulo configurando BOARD_VNDK_VERSION no as variáveis de ambiente:

$ BOARD_VNDK_VERSION=current m module_name.vendor

Quando BOARD_VNDK_VERSION está ativado, vários padrões globais os caminhos de pesquisa do cabeçalho são removidos. São eles:

  • 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 um módulo depender dos cabeçalhos desses diretórios, será necessário especificar explicitamente as dependências com header_libs; static_libs e/ou shared_libs.

APEX do VNDK

No Android 10 e versões anteriores, os módulos com vndk.enabled foram instalados em /system/lib[64]/vndk[-sp]-${VER}. No Android 11 e versões mais recentes, As bibliotecas do VNDK são empacotadas em um formato APEX, e o nome do VNDK APEX é com.android.vndk.v${VER}: Dependendo da configuração do dispositivo, O APEX do VNDK é nivelado ou não nivelado e está disponível no caminho canônico. /apex/com.android.vndk.v${VER}

APEX do VNDK

Figura 2. APEX do VNDK.

Definição do módulo

Para criar o Android com BOARD_VNDK_VERSION, você precisa revisar o do módulo em Android.mk ou Android.bp Esta seção descreve os diferentes tipos de módulos diversas definições de módulo relacionadas ao VNDK e verificações de dependência implementadas no sistema de build.

Módulos do fornecedor

Os módulos do fornecedor são executáveis ou bibliotecas compartilhadas específicos do fornecedor que precisam ser instalados em uma partição de fornecedor. Nos arquivos Android.bp, os módulos do fornecedor precisam definir a propriedade proprietária ou do fornecedor como true. Em arquivos Android.mk, os módulos do fornecedor precisam definir LOCAL_VENDOR_MODULE ou LOCAL_PROPRIETARY_MODULE para true.

Se BOARD_VNDK_VERSION for definido, o sistema de build não permitirá dependências entre os módulos do fornecedor e do framework e emitir erros se:

  • um módulo sem vendor:true depende de um módulo com vendor:true ou
  • um módulo com vendor:true depende da módulo diferente de llndk_library que não tem vendor:true nem vendor_available:true.

A verificação de dependência se aplica a header_libs, static_libs e shared_libs em Android.bp e até LOCAL_HEADER_LIBRARIES, LOCAL_STATIC_LIBRARIES e LOCAL_SHARED_LIBRARIES em Android.mk.

LL-NDK

As bibliotecas compartilhadas do LL-NDK são bibliotecas compartilhadas com ABIs estáveis. Ambas as estruturas e módulos de fornecedor compartilham a mesma implementação e a mais recente. Para cada biblioteca compartilhada do LL-NDK, o cc_library contém uma llndk com um arquivo de símbolo:

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

O arquivo de símbolos descreve os símbolos visíveis para os módulos do fornecedor. Exemplo:

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

Com base no arquivo de símbolo, o sistema de compilação gera uma biblioteca compartilhada de stubs para módulos de fornecedores, que são vinculados a essas bibliotecas ao BOARD_VNDK_VERSION está ativado. Um símbolo está incluído no stub Biblioteca compartilhada somente se ela:

  • não estiver definido na seção que termina com _PRIVATE ou; _PLATFORM,
  • Não tem a tag #platform-only.
  • Não tem tags #introduce* ou corresponde ao alvo.
.

VNDK

Nos arquivos Android.bp, cc_library, cc_library_static, cc_library_shared e As definições do módulo cc_library_headers oferecem suporte a três APIs relacionadas ao VNDK propriedades: vendor_available, vndk.enabled, e vndk.support_system_process.

Se vendor_available ou vndk.enabled for true, duas variantes (principal e fornecedor) podem ser construído. A variante principal precisa ser tratada como um módulo do framework e o fornecedor variante deve ser tratada como um módulo de fornecedor. Se alguns módulos do framework dependerem neste módulo, a variante principal é criada. Se alguns módulos do fornecedor dependerem deste módulo, a variante do fornecedor é criada. O sistema de build aplica as seguintes verificações de dependência:

  • A variante principal é sempre apenas o framework e está inacessível para o fornecedor módulos.
  • A variante do fornecedor está sempre inacessível para os módulos do framework.
  • Todas as dependências da variante do fornecedor, que são especificadas em header_libs, static_libs e/ou shared_libs, precisa ser llndk_library ou módulo com vendor_available ou vndk.enabled.
  • Se vendor_available for true, a variante do fornecedor é acessível a todos os módulos do fornecedor.
  • Se vendor_available for false, a variante do fornecedor só pode ser acessado por outros módulos VNDK ou VNDK-SP (ou seja, módulos com vendor:true não pode vincular vendor_available:false módulos).

O caminho de instalação padrão para cc_library ou cc_library_shared é determinado pelas seguintes regras:

  • A variante principal está instalada em /system/lib[64].
  • O caminho de instalação da variante do fornecedor pode variar:
    • Se vndk.enabled for false, a variante do fornecedor está instalado no /vendor/lib[64].
    • Se vndk.enabled for true, a variante do fornecedor está instalado no VNDK APEX(com.android.vndk.v${VER}).

A tabela abaixo resume como o sistema de build lida com as variantes do fornecedor:

fornecedor_disponível vndk
ativado
vndk
support_same_process
Descrições das variantes do fornecedor
true false false As variantes do fornecedor são SOMENTE VND. As bibliotecas compartilhadas são instalado no /vendor/lib[64].
true Inválido (erro de build)
true false As variantes do fornecedor são VNDK. As bibliotecas compartilhadas estão instaladas ao VNDK APEX.
true As variantes do fornecedor são VNDK-SP. As bibliotecas compartilhadas são instalado no VNDK APEX.

false

false

false

Nenhuma variante de fornecedor. Este módulo é SOMENTE FWK.

true Inválido (erro de build)
true false As variantes do fornecedor são VNDK-Private. As bibliotecas compartilhadas são instalado no VNDK APEX. Elas não podem ser usado diretamente pelos módulos do fornecedor.
true As variantes do fornecedor são VNDK-SP-Private. As bibliotecas compartilhadas são instalado no VNDK APEX. Elas não podem ser usado diretamente pelos módulos do fornecedor.

Extensões VNDK

As extensões do VNDK são bibliotecas compartilhadas do VNDK com outras APIs. As extensões são instalado no /vendor/lib[64]/vndk[-sp] (sem sufixo de versão) e substituir as bibliotecas compartilhadas do VNDK originais no momento da execução.

Definir extensões do VNDK

No Android 9 e versões mais recentes, o Android.bp oferece suporte nativo ao VNDK extensões. Para criar uma extensão do VNDK, defina outro módulo com uma vendor:true e uma propriedade extends:

cc_library {
    name: "libvndk",
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libvndk_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk",
    },
}

Um módulo com vendor:true, vndk.enabled:true e As propriedades extends definem a extensão do VNDK:

  • A propriedade extends precisa especificar uma biblioteca compartilhada VNDK de base. (ou nome da biblioteca compartilhada VNDK-SP).
  • As extensões VNDK (ou extensões VNDK-SP) são nomeadas com base no módulo base e os nomes de origem deles. Por exemplo, o binário de saída libvndk_ext é libvndk.so em vez de libvndk_ext.so
  • As extensões do VNDK são instaladas em /vendor/lib[64]/vndk.
  • As extensões do VNDK-SP são instaladas /vendor/lib[64]/vndk-sp:
  • As bibliotecas compartilhadas de base precisam ter vndk.enabled:true e vendor_available:true.

Uma extensão VNDK-SP precisa se estender de uma biblioteca compartilhada do VNDK-SP. (vndk.support_system_process precisa ser igual a):

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

As extensões VNDK (ou extensões VNDK-SP) podem depender de outros fornecedores compartilhados 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,
}

Usar extensões VNDK

Se um módulo de fornecedor depender de APIs adicionais definidas pelas extensões do VNDK, o precisa especificar o nome da extensão do VNDK no Propriedade 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 um módulo de fornecedor depender das extensões do VNDK, essas extensões do VNDK serão instalado no /vendor/lib[64]/vndk[-sp] automaticamente. Se um módulo não depende mais de uma extensão do VNDK, adicione uma etapa de limpeza ao CleanSpec.mk para remover a biblioteca compartilhada. Exemplo:

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

Compilação condicional

Esta seção descreve como lidar com as diferenças sutis (por exemplo, adicionar ou remover um atributo de uma das variantes) entre os seguintes três bibliotecas compartilhadas do VNDK:

  • Variante principal (por exemplo, /system/lib[64]/libexample.so)
  • A variante do fornecedor (por exemplo, /apex/com.android.vndk.v${VER}/lib[64]/libexample.so)
  • Extensão do VNDK (por exemplo, /vendor/lib[64]/vndk[-sp]/libexample.so)

Sinalizações do compilador condicional

O sistema de build do Android define __ANDROID_VNDK__ para o variantes e extensões do VNDK por padrão. É possível proteger o código com as proteções do pré-processador C:

void all() { }

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

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

Além de __ANDROID_VNDK__, diferentes cflags ou cppflags pode ser especificado em Android.bp. A cflags ou cppflags especificado em target.vendor é específico para a variante do fornecedor.

Por exemplo, o Android.bp abaixo define 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",
    ],
}

Esta é a 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 acordo com esses dois arquivos, o sistema de compilação gera bibliotecas compartilhadas com os seguintes símbolos exportados:

Caminho de instalação 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 para os símbolos exportados

O verificador de ABI VNDK compara a ABI das variantes do fornecedor do VNDK e Extensões VNDK para os despejos da ABI de referência em prebuilts/abi-dumps/vndk.

  • Símbolos exportados pelas variantes do fornecedor do VNDK (por exemplo, /apex/com.android.vndk.v${VER}/lib[64]/libexample.so) precisam ser idênticos aos (não aos superconjuntos) dos símbolos definidos nos despejos da ABI.
  • Símbolos exportados por extensões VNDK (por exemplo, /vendor/lib[64]/vndk/libexample.so) precisam ser superconjuntos da símbolos definidos em despejos de ABI.

Se as variantes do fornecedor do VNDK ou as extensões do VNDK não forem seguidas os requisitos acima, o verificador de ABI do VNDK emite erros de build e interrompe a ser construído.

Excluir arquivos de origem ou bibliotecas compartilhadas das variantes do fornecedor

Para excluir arquivos de origem da variante do fornecedor, adicione-os ao exclude_srcs. Da mesma forma, para garantir que as bibliotecas compartilhadas sejam não vinculadas à variante do fornecedor, adicione essas bibliotecas ao exclude_shared_libs. Exemplo:

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

Neste exemplo, a variante principal de libexample_cond_exclude inclui o código de fwk.c e both.c e depende nas bibliotecas compartilhadas libfwk_only e libboth. A variante de fornecedor de libexample_cond_exclude inclui apenas o código de both.c porque fwk.c é excluído pelo propriedade exclude_srcs. Da mesma forma, depende apenas da Biblioteca compartilhada libboth porque libfwk_only é excluído pelo propriedade exclude_shared_libs.

Exportar cabeçalhos de extensões VNDK

Uma extensão do VNDK pode adicionar novas classes ou funções a um VNDK compartilhado. biblioteca. Sugerimos manter essas declarações em cabeçalhos independentes, e evite alterar os cabeçalhos existentes.

Por exemplo, um novo arquivo principal include-ext/example/ext/feature_name.h é criado para o VNDK. extensão libexample_ext:

  • Android.bp
  • include-ext/example/ext/feature_name.h (link em inglês)
  • incluir/exemplo/exemplo.h
  • src/exemplo.c
  • src/ext/feature_name.c (link em inglês)

Nas exportações de Android.bp a seguir, libexample somente include, enquanto libexample_ext exporta ambos include e include-ext. Isso garante feature_name.h não serão incluídos incorretamente pelos usuários 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",
    },
}

Se não for possível separar as extensões em arquivos de cabeçalho independentes, uma alternativa é adicionar guardas #ifdef. No entanto, certifique-se de que todas Os usuários da extensão VNDK adicionam as sinalizações de definição. Você pode definir cc_defaults para adicionar flags para definir a cflags e vincular bibliotecas compartilhadas com shared_libs.

Por exemplo, para adicionar uma nova função de membro Example2::get_b() a extensão libexample2_ext do VNDK, você precisa modificar a e adicione uma proteção #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_

Um cc_defaults chamado libexample2_ext_defaults está definido para os usuários 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",
    ],
}

Os usuários de libexample2_ext podem simplesmente incluir libexample2_ext_defaults na defaults :

cc_binary {
    name: "example2_user_executable",
    defaults: ["libexample2_ext_defaults"],
    vendor: true,
}

Pacotes de produtos

No sistema de build do Android, a variável PRODUCT_PACKAGES especifica os executáveis, bibliotecas compartilhadas ou pacotes que devem ser instalado no dispositivo. As dependências transitivas do objeto especificado módulos também são implicitamente instalados no dispositivo.

Se BOARD_VNDK_VERSION estiver ativado, os módulos com vendor_available ou vndk.enabled ganham oferta especial tratamento. Se um módulo de framework depender de um módulo com vendor_available ou vndk.enabled, a variante principal está incluído no conjunto de instalação transitiva. Se um módulo de fornecedor depende de um módulo com vendor_available, a variante do fornecedor é incluído no conjunto de instalações transitivas. No entanto, as variantes de módulos do fornecedor com vndk.enabled são instalados, quer sejam usados ou não pelos módulos do fornecedor.

Quando as dependências são invisíveis para o sistema de build (por exemplo, bibliotecas compartilhadas). que pode ser aberto com dlopen() durante a execução), especifique os nomes dos módulos em PRODUCT_PACKAGES para instalar esses módulos explicitamente.

Se um módulo tiver vendor_available ou vndk.enabled: o nome do módulo representa a variante principal dele. Para especificar explicitamente o variante do fornecedor em PRODUCT_PACKAGES, anexe um .vendor ao nome do módulo. Exemplo:

cc_library {
    name: "libexample",
    srcs: ["example.c"],
    vendor_available: true,
}

Neste exemplo, libexample significa /system/lib[64]/libexample.so e libexample.vendor significa /vendor/lib[64]/libexample.so. Para instalar /vendor/lib[64]/libexample.so, adicionar libexample.vendor para PRODUCT_PACKAGES:

PRODUCT_PACKAGES += libexample.vendor