Noções básicas sobre versões de 64 bits

O sistema de compilação permite a criação de binários para duas arquiteturas de CPU de destino (64 bits e 32 bits) no mesmo build. Isso é conhecido como build multilib.

Para bibliotecas estáticas nativas e bibliotecas compartilhadas, o sistema de criação 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 compilação cria apenas a versão de 64 bits por padrão, mas é possível modificar essa configuração usando uma variável global BoardConfig.mk ou uma variável com escopo de módulo.

Configuração do produto

BoardConfig.mk inclui as seguintes variáveis para configurar a segunda arquitetura de CPU e ABI:

  • TARGET_2ND_ARCH
  • TARGET_2ND_ARCH_VARIANT
  • TARGET_2ND_CPU_VARIANT
  • TARGET_2ND_CPU_ABI
  • TARGET_2ND_CPU_ABI2

Veja um exemplo em build/target/board/generic_arm64/BoardConfig.mk.

Se quiser que o sistema de criação crie executáveis e apps de 32 bits por padrão, defina a seguinte variável:

TARGET_PREFER_32_BIT := true

Você pode modificar essa configuração usando variáveis específicas do módulo em Android.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 compilação. Para bibliotecas extraídas por dependência, uma biblioteca de 32 bits será instalada apenas se for exigida por outra biblioteca ou executável de 32 bits. O mesmo ocorre para bibliotecas de 64 bits.

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.

Definição de módulo no Android.mk

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

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).
  • "" é o padrão. O sistema de compilação decide qual arquitetura será criada com base na classe do módulo e em 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
    Defina 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 compilação.
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH
    Essa variável é o oposto de LOCAL_MODULE_TARGET_ARCH. Se a arquitetura que está sendo criada não estiver nessa lista, o módulo atual será incluído pelo sistema de compilação.

Existem variantes menores dessas duas variáveis:

  • LOCAL_MODULE_TARGET_ARCH_WARN
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN

O sistema de compilação avisará se o módulo atual for ignorado por causa das arquiteturas listadas.

Para configurar sinalizações de criação para uma arquitetura específica, use as variáveis LOCAL_ específicas da arquitetura. Uma variável LOCAL_ específica da arquitetura é uma variável LOCAL_ normal com um sufixo de 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 sinalizações 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,

Como instalar um caminho

Anteriormente, era possível 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.

Em um build multilib, use LOCAL_MODULE_RELATIVE_PATH:

LOCAL_MODULE_RELATIVE_PATH := hw

Com esse formato, as bibliotecas de 64 e 32 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.

Origens geradas

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 funcionará de forma confiável. Isso ocorre porque as intermediárias origens 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 compilação fornece um diretório intermediário dedicado e compatível com multilib para gerar origens. Você pode chamar $(local-generated-sources-dir) ou $(generated-sources-dir-for) para indicar o caminho do diretório. As formas de usá-los são semelhantes a $(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.

Pré-versões

Em um build multilib, não é possível usar TARGET_ARCH (ou junto com TARGET_2ND_ARCH) para informar ao sistema de compilação a que a arquitetura o binário pré-construído é destinada. 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 compilação 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é-compilado, chame $(get-prebuilt-src-arch).

Geração de arquivos ODEX

Por padrão, para dispositivos de 64 bits, geramos arquivos ODEX de 32 e 64 bits para a imagem de inicialização e as bibliotecas Java. Para os APKs, por padrão, geramos 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 compilação a incluí-las.