Créer des builds pour les architectures 32 bits et 64 bits

Le système de compilation permet de compiler des binaires pour deux architectures de processeur cibles, 32 bits et 64 bits, dans la même compilation. Cette compilation à deux cibles est appelée compilation multilib.

Pour les bibliothèques statiques et partagées intégrées, le système de compilation configure des règles pour compiler des binaires pour les deux architectures. La configuration du produit (PRODUCT_PACKAGES), ainsi que le graphique des dépendances, déterminent les binaires qui sont compilés et installés dans l'image système.

Pour les exécutables et les applications, le système de compilation ne compile que la version 64 bits par défaut, mais vous pouvez remplacer ce paramètre par une variable BoardConfig.mk globale ou une variable à portée de module.

Identifier une deuxième architecture de processeur et une deuxième ABI

BoardConfig.mk inclut les variables suivantes pour configurer la deuxième architecture de processeur et la deuxième interface binaire d'application (ABI) :

  • TARGET_2ND_ARCH
  • TARGET_2ND_ARCH_VARIANT
  • TARGET_2ND_CPU_VARIANT
  • TARGET_2ND_CPU_ABI
  • TARGET_2ND_CPU_ABI2

Pour obtenir un exemple de makefile qui utilise ces variables, consultez build/make/target/board/generic_arm64/BoardConfig.mk.

Dans une compilation multilib, les noms de modules dans PRODUCT_PACKAGES couvrent les binaires 32 bits et 64 bits, à condition qu'ils soient définis par le système de compilation. Pour les bibliothèques incluses par dépendance, une bibliothèque 32 bits ou 64 bits n'est installée que si elle est requise par une autre bibliothèque ou un autre exécutable 32 bits ou 64 bits.

Toutefois, les noms de modules sur la ligne de commande make ne couvrent que la version 64 bits. Par exemple, après avoir exécuté lunch aosp_arm64-eng, make libc ne compile que la libc 64 bits. Pour compiler la libc 32 bits, vous devez exécuter make libc_32.

Définir l'architecture du module dans Android.mk

Vous pouvez utiliser la variable LOCAL_MULTILIB pour configurer votre compilation pour 32 bits et 64 bits, et remplacer la variable TARGET_PREFER_32_BIT globale.

Pour remplacer TARGET_PREFER_32_BIT, définissez LOCAL_MULTILIB sur l'une des valeurs suivantes :

  • both compile les versions 32 bits et 64 bits.
  • 32 ne compile que la version 32 bits.
  • 64 ne compile que la version 64 bits.
  • first ne compile que pour la première architecture (32 bits sur les appareils 32 bits et 64 bits sur les appareils 64 bits).

Par défaut, LOCAL_MULTILIB n'est pas défini et le système de compilation décide de l'architecture à compiler en fonction de la classe de module et d'autres LOCAL_* variables, telles que LOCAL_MODULE_TARGET_ARCH et LOCAL_32_BIT_ONLY.

Si vous souhaitez compiler votre module pour des architectures spécifiques, utilisez les variables suivantes :

  • LOCAL_MODULE_TARGET_ARCH : définissez cette variable sur une liste d'architectures, par exemple arm x86 arm64. Si l'architecture en cours de compilation figure dans cette liste, le module actuel est inclus par le système de compilation.

  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH : cette variable est l'opposé de LOCAL_MODULE_TARGET_ARCH. Si l'architecture en cours de compilation not figure dans cette liste, le module actuel est inclus par le système de compilation.

Il existe des variantes mineures de ces deux variables :

  • LOCAL_MODULE_TARGET_ARCH_WARN
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN

Le système de compilation avertit si le module actuel est ignoré en raison des architectures listées.

Pour configurer des indicateurs de compilation pour une architecture particulière, utilisez les variables spécifiques à l'architecture LOCAL_** est un suffixe spécifique à l'architecture, par exemple :

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

Ces variables ne sont appliquées que si un binaire est compilé pour cette architecture.

Il est parfois plus facile de configurer des indicateurs selon que le binaire est compilé pour 32 bits ou 64 bits. Utilisez la LOCAL_* variable avec un _32 ou _64 suffixe, par exemple :

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

Définir le chemin d'installation de la bibliothèque

Pour une compilation non multilib, vous pouvez utiliser LOCAL_MODULE_PATH pour installer une bibliothèque à un emplacement autre que l'emplacement par défaut. Par exemple, LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw.

Toutefois, dans une compilation multilib, utilisez plutôt LOCAL_MODULE_RELATIVE_PATH :

LOCAL_MODULE_RELATIVE_PATH := hw

Avec ce format, les bibliothèques 64 bits et 32 bits sont installées au bon emplacement.

Si vous compilez un exécutable en 32 bits et 64 bits, utilisez l'une des variables suivantes pour distinguer le chemin d'installation :

  • LOCAL_MODULE_STEM_32, LOCAL_MODULE_STEM_64 : spécifie le nom de fichier installé.
  • LOCAL_MODULE_PATH_32, LOCAL_MODULE_PATH_64 : spécifie le chemin d'installation.

Obtenir le répertoire intermédiaire pour les fichiers sources

Dans une compilation multilib, si vous générez des fichiers sources dans $(local-intermediates-dir) (ou $(intermediates-dir-for) avec des variables explicites), cela ne fonctionne pas de manière fiable. En effet, les sources intermédiaires générées sont requises par les compilations 32 bits et 64 bits, mais $(local-intermediates-dir) ne pointe que vers l'un des deux répertoires intermédiaires.

Le système de compilation fournit un répertoire intermédiaire dédié, compatible avec multilib, pour générer des sources. Pour récupérer le chemin du répertoire intermédiaire, utilisez la macro $(local-generated-sources-dir) ou $(generated-sources-dir-for). L'utilisation de ces macros est semblable à celle de $(local-intermediates-dir) et $(intermediates-dir-for).

Si un fichier source est généré dans ce répertoire dédié et récupéré par LOCAL_GENERATED_SOURCES, il est compilé pour 32 bits et 64 bits dans une compilation multilib.

Indiquer l'architecture système des cibles binaires précompilées

Dans une compilation multilib, vous ne pouvez pas utiliser TARGET_ARCH ni TARGET_ARCH combiné à TARGET_2ND_ARCH pour indiquer l'architecture système des cibles binaires précompilées. Utilisez plutôt les LOCAL_* variables LOCAL_MODULE_TARGET_ARCH ou LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH.

Avec ces variables, le système de compilation peut choisir le binaire précompilé 32 bits correspondant, même s'il fonctionne sur une compilation multilib 64 bits.

Si vous souhaitez utiliser l'architecture choisie pour calculer le chemin source du binaire précompilé, appelez $(get-prebuilt-src-arch).

S'assurer de la génération des fichiers ODEX 32 bits et 64 bits

Pour les appareils 64 bits, Google génère par défaut des fichiers ODEX 32 bits et 64 bits pour l'image de démarrage et toutes les bibliothèques Java. Pour les APK, Google ne génère par défaut que des fichiers ODEX pour l'architecture 64 bits principale. Si une application est lancée dans des processus 32 bits et 64 bits, utilisez LOCAL_MULTILIB := both pour vous assurer que les fichiers ODEX 32 bits et 64 bits sont générés. Si l'application comporte des bibliothèques JNI 32 bits ou 64 bits, cet indicateur indique également au système de compilation de les inclure.