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

O sistema de compilação oferece suporte à compilação de binários para duas arquiteturas de CPU de destino (64 bits e 32 bits) na mesma compilação. Isso é conhecido como uma compilação multilib .

Para bibliotecas estáticas nativas e bibliotecas compartilhadas, o sistema de compilação configura regras para compilar binários para ambas as arquiteturas. A configuração do produto ( PRODUCT_PACKAGES ), juntamente com o gráfico de dependência, determina quais binários são compilados e instalados na imagem do sistema.

Para executáveis ​​e aplicativos, o sistema de compilação compila apenas a versão de 64 bits por padrão, mas você pode substituir essa configuração por 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

Você pode ver um exemplo em build/target/board/generic_arm64/BoardConfig.mk .

Em uma compilação multilib, os nomes dos módulos em PRODUCT_PACKAGES abrangem os binários de 32 e 64 bits, desde que sejam definidos pelo sistema de compilação. Para bibliotecas extraídas por dependência, uma biblioteca de 32 bits é instalada somente se for exigida por outra biblioteca de 32 bits ou executável. O mesmo vale para bibliotecas de 64 bits.

No entanto, os nomes dos módulos na linha de comando make cobrem apenas a versão de 64 bits. Por exemplo, depois de executar lunch aosp_arm64-eng , make libc compila apenas a libc de 64 bits. Para construir a libc de 32 bits, você precisa executar make libc_32 .

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

Você pode usar a variável LOCAL_MULTILIB para configurar sua compilação para 32 bits/64 bits e substituir a variável global TARGET_PREFER_32_BIT .

Defina LOCAL_MULTILIB para um dos seguintes:

  • "both" cria 32 bits e 64 bits.
  • "32" cria apenas 32 bits.
  • "64" cria apenas 64 bits.
  • "first" compila 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 construir com base na classe do módulo e outras variáveis LOCAL_ , como LOCAL_MODULE_TARGET_ARCH e LOCAL_32_BIT_ONLY .

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

  • LOCAL_MODULE_TARGET_ARCH
    Defina essa variável para uma lista de arquiteturas, como arm x86 arm64 . Se a arquitetura que está sendo construída estiver nessa lista, o módulo atual será incluído pelo sistema de compilação.
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH
    Esta variável é o oposto de LOCAL_MODULE_TARGET_ARCH . Se a arquitetura que está sendo construída não estiver nessa lista, o módulo atual é incluído pelo sistema de compilação.

Existem pequenas variantes dessas duas variáveis:

  • LOCAL_MODULE_TARGET_ARCH_WARN
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN

O sistema de compilação avisa se o módulo atual for ignorado devido às arquiteturas listadas.

Para configurar sinalizadores de compilaçã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 ​​são aplicadas somente se um binário estiver sendo construído para essa arquitetura.

Às vezes, é mais fácil configurar sinalizadores com base no fato de o binário estar sendo construído atualmente para 32 bits 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,

Instalando um caminho

Anteriormente, você podia 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 uma compilação multilib, use LOCAL_MODULE_RELATIVE_PATH :

LOCAL_MODULE_RELATIVE_PATH := hw

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

Se você construir um executável como 32 bits e 64 bits, use uma das seguintes variáveis ​​para distinguir 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.

Fontes geradas

Em uma compilação multilib, se você gerar arquivos de origem para $(local-intermediates-dir) (ou $(intermediates-dir-for) com variáveis ​​explícitas), ele não funcionará de maneira confiável. Isso porque as fontes geradas intermediárias são exigidas pelas compilações de 32 bits 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 multilibs para a geração de fontes. Você pode chamar $(local-generated-sources-dir) ou $(generated-sources-dir-for) para obter o caminho do diretório. Seus usos são semelhantes a $(local-intermediates-dir) e $(intermediates-dir-for) .

Se um arquivo de origem for gerado para esse diretório dedicado e selecionado por LOCAL_GENERATED_SOURCES , ele será criado para 32 bits e 64 bits em uma compilação multilib.

Pré-construídos

Em uma compilação multilib, você não pode usar TARGET_ARCH (ou junto com TARGET_2ND_ARCH ) para informar ao sistema de compilação qual arquitetura o binário pré-compilado visa. 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é-compilado de 32 bits correspondente, mesmo que esteja trabalhando em uma compilação multilib de 64 bits.

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

Geração de arquivo ODEX

Para dispositivos de 64 bits, por padrão, geramos arquivos ODEX de 32 e 64 bits para a imagem de inicialização e quaisquer bibliotecas Java. Para APKs, por padrão, geramos ODEX apenas para a arquitetura primária de 64 bits. Se um aplicativo for iniciado em processos de 32 bits e 64 bits, use LOCAL_MULTILIB := both para garantir que os arquivos ODEX de 32 bits e 64 bits sejam gerados. Se o aplicativo tiver bibliotecas JNI de 32 ou 64 bits, esse sinalizador também informa ao sistema de compilação para incluí-las.