Builds para arquiteturas de 32 e 64 bits

O sistema de build permite a criação de binários para duas arquiteturas de CPU de destino de 32 e 64 bits no mesmo build. Esse build de dois destinos é conhecido como versão multilib.

Para bibliotecas estáticas integradas e bibliotecas compartilhadas, o sistema de build configura regras para criar binários para as duas arquiteturas. A configuração do produto (PRODUCT_PACKAGES), junto com o gráfico de dependência, determina quais binários são criados e instalados na imagem do sistema.

Para executáveis e apps, o sistema de build cria apenas a versão de 64 bits por padrão, mas é possível substituir essa configuração usando uma variável global BoardConfig.mk ou uma variável com escopo de módulo.

Identificar uma segunda arquitetura de CPU e ABI

O BoardConfig.mk inclui as seguintes variáveis para configurar a segunda arquitetura de CPU e interface binária do aplicativo (ABI):

  • TARGET_2ND_ARCH
  • TARGET_2ND_ARCH_VARIANT
  • TARGET_2ND_CPU_VARIANT
  • TARGET_2ND_CPU_ABI
  • TARGET_2ND_CPU_ABI2

Para conferir um exemplo de makefile que usa essas variáveis, consulte build/make/target/board/generic_arm64/BoardConfig.mk.

Em um build multilib, os nomes dos módulos em PRODUCT_PACKAGES abrangem os binários de 32 e 64 bits, desde que eles sejam definidos pelo sistema de build. Para bibliotecas incluídas por dependência, uma biblioteca de 32 ou 64 bits é instalada somente se for exigida por outra biblioteca de 32 ou 64 bits ou executável.

No entanto, os nomes dos módulos na linha de comando make abrangem apenas a versão de 64 bits. Por exemplo, após executar lunch aosp_arm64-eng, make libc cria somente a libc de 64 bits. Para criar a libc de 32 bits, é necessário executar make libc_32.

Definir a arquitetura com módulos em Android.mk

Você pode usar a variável LOCAL_MULTILIB para configurar seu build para 32 e 64 bits e substituir a variável TARGET_PREFER_32_BIT global.

Para substituir TARGET_PREFER_32_BIT, defina LOCAL_MULTILIB como um dos seguintes:

  • both cria 32 bits e 64 bits.
  • 32 cria apenas 32 bits.
  • 64 cria apenas 64 bits.
  • first cria apenas para a primeira arquitetura (32 bits em dispositivos de 32 bits e 64 bits em dispositivos de 64 bits).

Por padrão, o LOCAL_MULTILIB não está definido, e o sistema de build decide qual arquitetura criar com base na classe do módulo e outras variáveis LOCAL_*, como LOCAL_MODULE_TARGET_ARCH e LOCAL_32_BIT_ONLY.

Se você quiser criar seu módulo para arquiteturas específicas, use as seguintes variáveis:

  • LOCAL_MODULE_TARGET_ARCH: define essa variável como uma lista de arquiteturas, como arm x86 arm64. Se a arquitetura que está sendo criada estiver nessa lista, o módulo atual será incluído pelo sistema de build.

  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH: essa variável é o oposto de LOCAL_MODULE_TARGET_ARCH. Se a arquitetura que está sendo criada not (não) estiver nessa lista, o módulo atual será incluído pelo sistema de build.

Existem variantes menores dessas duas variáveis:

  • LOCAL_MODULE_TARGET_ARCH_WARN
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN

O sistema de build vai avisar se o módulo atual for ignorado por causa das arquiteturas listadas.

Para configurar flags de criação para uma arquitetura específica, use as variáveis LOCAL_* específicas da arquitetura, em que * é um sufixo específico da arquitetura. Por exemplo:

  • LOCAL_SRC_FILES_arm, LOCAL_SRC_FILES_x86,
  • LOCAL_CFLAGS_arm, LOCAL_CFLAGS_arm64,
  • LOCAL_LDFLAGS_arm, LOCAL_LDFLAGS_arm64,

Essas variáveis serão aplicadas somente se um binário estiver sendo criado para essa arquitetura.

Às vezes, é mais fácil configurar flags de acordo com a criação do binário atual para 32 ou 64 bits. Use a variável LOCAL_* com um sufixo _32 ou _64, por exemplo:

  • LOCAL_SRC_FILES_32, LOCAL_SRC_FILES_64,
  • LOCAL_CFLAGS_32, LOCAL_CFLAGS_64,
  • LOCAL_LDFLAGS_32, LOCAL_LDFLAGS_64,

Definir o caminho de instalação da biblioteca

Para um build não multilib, você pode usar LOCAL_MODULE_PATH para instalar uma biblioteca em um local diferente do padrão. Por exemplo: LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw.

No entanto, em um build multilib, use LOCAL_MODULE_RELATIVE_PATH:

LOCAL_MODULE_RELATIVE_PATH := hw

Com esse formato, as bibliotecas de 32 e 64 bits são instaladas no local correto.

Se você criar um executável como 32 bits e 64 bits, use uma das seguintes variáveis para diferenciar o caminho de instalação:

  • LOCAL_MODULE_STEM_32, LOCAL_MODULE_STEM_64: especifica o nome do arquivo instalado.
  • LOCAL_MODULE_PATH_32, LOCAL_MODULE_PATH_64: especifica o caminho de instalação.

Conseguir o diretório intermediário para arquivos de origem

Em um build multilib, se você gerar arquivos de origem para $(local-intermediates-dir) (ou $(intermediates-dir-for) com variáveis explícitas), ela não vai funcionar de forma confiável. Isso ocorre porque as origens intermediárias geradas são exigidas pelas versões de 32 e 64 bits, mas $(local-intermediates-dir) aponta apenas para um dos dois diretórios intermediários.

O sistema de build fornece um diretório intermediário dedicado e compatível com multilib para gerar origens. Para recuperar o caminho intermediário do diretório, use a macro $(local-generated-sources-dir) ou $(generated-sources-dir-for). O uso dessas macros é parecido com $(local-intermediates-dir) e $(intermediates-dir-for).

Se um arquivo de origem for gerado para esse diretório dedicado e escolhido por LOCAL_GENERATED_SOURCES, ele será criado para 32 bits e 64 bits em um build multilib.

Indicar a arquitetura do sistema de alvos binários pré-criados

Em um build multilib, não é possível usar TARGET_ARCH, ou TARGET_ARCH com TARGET_2ND_ARCH, para indicar a arquitetura do sistema de de alvos binários pré-criados. Em vez disso, use as variáveis LOCAL_* LOCAL_MODULE_TARGET_ARCH ou LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH.

Com essas variáveis, o sistema de build pode escolher o binário pré-criado de 32 bits correspondente, mesmo que esteja criando um build multilib de 64 bits.

Se você quiser usar a arquitetura escolhida para calcular o caminho de origem do binário pré-criado, chame $(get-prebuilt-src-arch).

Garantir a geração de arquivos ODEX de 32 e 64 bits

Por padrão, para dispositivos de 64 bits, o Google gera arquivos ODEX de 32 e 64 bits para a imagem de inicialização e as bibliotecas Java. Para os APKs, por padrão, o Google gera o ODEX apenas para a arquitetura principal de 64 bits. Se um app for iniciado em processos de 32 e 64 bits, use LOCAL_MULTILIB := both para garantir que os arquivos ODEX de 32 e de 64 bits sejam gerados. Caso o app tenha alguma biblioteca JNI de 32 ou 64 bits, essa sinalização também instrui o sistema de build a incluí-las.