Creazione per architetture a 32 e 64 bit

Il sistema di compilazione supporta la compilazione di file binari per due architetture CPU di destinazione, a 32 e 64 bit, nella stessa compilazione. Questa compilazione con due target è nota come compilazione multilib.

Per le librerie statiche integrate e le librerie condivise, il sistema di compilazione configura regole per creare file binari per entrambe le architetture. La configurazione del prodotto (PRODUCT_PACKAGES), insieme al grafico delle dipendenze, determina quali binari vengono compilati e installati nell'immagine di sistema.

Per gli eseguibili e le app, per impostazione predefinita il sistema di build crea solo la versione a 64 bit, ma puoi eseguire l'override di questa impostazione con una variabile BoardConfig.mk globale o con una variabile basata sui moduli.

Identifica una seconda architettura CPU e ABI

BoardConfig.mk include le seguenti variabili per configurare la seconda architettura CPU e l'ABI (Application Binary Interface):

  • TARGET_2ND_ARCH
  • TARGET_2ND_ARCH_VARIANT
  • TARGET_2ND_CPU_VARIANT
  • TARGET_2ND_CPU_ABI
  • TARGET_2ND_CPU_ABI2

Per un esempio di file make che utilizza queste variabili, consulta build/make/target/board/generic_arm64/BoardConfig.mk.

In una build multilib, i nomi dei moduli in PRODUCT_PACKAGES coprono i binari a 32 e 64 bit, a condizione che siano definiti dal sistema di compilazione. Per le librerie incluse per dipendenza, una libreria a 32 o 64 bit viene installata solo se richiesta da un'altra libreria o un altro eseguibile a 32 o 64 bit.

Tuttavia, i nomi dei moduli nella riga di comando make coprono solo la versione a 64 bit. Ad esempio, dopo aver eseguito lunch aosp_arm64-eng, make libc viene compilata solo la libc a 64 bit. Per compilare la libc a 32 bit, devi eseguire make libc_32.

Definire l'architettura del modulo in Android.mk

Puoi utilizzare la variabile LOCAL_MULTILIB per configurare la build a 32 e 64 bit e sostituire la variabile TARGET_PREFER_32_BIT globale.

Per eseguire l'override di TARGET_PREFER_32_BIT, imposta LOCAL_MULTILIB su uno dei seguenti valori:

  • both esegue build sia a 32 bit che a 64 bit.
  • 32 crea solo build a 32 bit.
  • 64 esegue la build a solo 64 bit.
  • first viene compilato solo per la prima architettura (32 bit sui dispositivi a 32 bit e 64 bit sui dispositivi a 64 bit).

Per impostazione predefinita, LOCAL_MULTILIB non è impostato e il sistema di compilazione decide quale architettura compilare in base alla classe del modulo e ad altre variabili LOCAL_*, come LOCAL_MODULE_TARGET_ARCH e LOCAL_32_BIT_ONLY.

Se vuoi creare il modulo per architetture specifiche, utilizza le seguenti variabili:

  • LOCAL_MODULE_TARGET_ARCH: imposta questa variabile su un elenco di architetture, come arm x86 arm64. Se l'architettura in fase di compilazione è in quell'elenco, il modulo corrente viene incluso dal sistema di compilazione.

  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH: questa variabile è l'opposto di LOCAL_MODULE_TARGET_ARCH. Se l'architettura in fase di compilazione è not in questo elenco, il modulo corrente viene incluso dal sistema di compilazione.

Esistono varianti minori di queste due variabili:

  • LOCAL_MODULE_TARGET_ARCH_WARN
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN

Il sistema di compilazione avvisa se il modulo corrente viene saltato a causa delle architetture elencate.

Per configurare i flag di compilazione per una determinata architettura, utilizza le variabili LOCAL_* specifiche dell'architettura, dove * è un suffisso specifico dell'architettura, ad esempio:

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

Queste variabili vengono applicate solo se viene creato un programma binario per quell'architettura.

A volte è più facile configurare i flag in base al fatto che il file binario sia in fase di compilazione per 32 o 64 bit. Utilizza la variabile LOCAL_* con un suffisso _32 o _64, ad esempio:

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

Imposta percorso di installazione della libreria

Per una build non multilib, puoi utilizzare LOCAL_MODULE_PATH per installare una libreria in una posizione diversa da quella predefinita. Ad esempio, LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw.

Tuttavia, in una build multilib, usa invece LOCAL_MODULE_RELATIVE_PATH:

LOCAL_MODULE_RELATIVE_PATH := hw

Con questo formato, le librerie a 64 e 32 bit vengono installate nella posizione corretta.

Se crei un eseguibile sia a 32 che a 64 bit, utilizza una delle seguenti variabili per distinguere il percorso di installazione:

  • LOCAL_MODULE_STEM_32, LOCAL_MODULE_STEM_64 - Specifica il nome file installato.
  • LOCAL_MODULE_PATH_32, LOCAL_MODULE_PATH_64 - Specifica il percorso di installazione.

Ottenere la directory intermedia per i file di origine

In una compilazione multilib, se generi file di origine per $(local-intermediates-dir) (o $(intermediates-dir-for) con variabili esplicite), il funzionamento non è affidabile. Questo accade perché le sorgenti generate intermedie sono richieste sia per le build a 32 bit sia per quelle a 64 bit, ma $(local-intermediates-dir) fa riferimento a una sola delle due directory intermedie.

Il sistema di compilazione fornisce una directory intermedia dedicata e compatibile con multilib per la generazione delle sorgenti. Per recuperare il percorso della directory intermedia, utilizza la macro $(local-generated-sources-dir) o $(generated-sources-dir-for). Gli utilizzi di queste macro sono simili a quelli di $(local-intermediates-dir) e $(intermediates-dir-for).

Se un file di origine viene generato in questa directory dedicata e rilevato da LOCAL_GENERATED_SOURCES, viene compilato sia per 32 bit che per 64 bit in una compilazione multilib.

Indica l'architettura di sistema dei target binari predefiniti

In una compilazione multilib, non puoi utilizzare TARGET_ARCH o TARGET_ARCH combinato con TARGET_2ND_ARCH per indicare l'architettura di sistema dei target compilati in precedenza. Utilizza invece le variabili LOCAL_* LOCAL_MODULE_TARGET_ARCH o LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH.

Con queste variabili, il sistema di compilazione può scegliere il file binario predefinito a 32 bit corrispondente anche se sta utilizzando una build multilib a 64 bit.

Se vuoi utilizzare l'architettura scelta per calcolare il percorso della sorgente per il codice binario precompilato, chiama $(get-prebuilt-src-arch).

Assicurati la generazione di file ODEX a 32 e 64 bit

Per i dispositivi a 64 bit, per impostazione predefinita Google genera file ODEX a 32 e 64 bit per l'immagine di avvio e le eventuali librerie Java. Per gli APK, per impostazione predefinita Google genera ODEX solo per l'architettura principale a 64 bit. Se un'app viene avviata nei processi a 32 e a 64 bit, utilizza LOCAL_MULTILIB := both per assicurarti che vengano generati file ODEX a 32 e 64 bit. Se l'app ha librerie JNI a 32 o 64 bit, il flag comunica anche al sistema di build di includerle.