Par conception, les fichiers Android.bp sont simples. Ils ne contiennent pas d'expressions conditionnelles ni d'instructions de flux de contrôle. Toute la complexité est gérée par la logique de compilation écrite en Go.
Modules
Un module dans un fichier Android.bp commence par un type de module, suivi d'un ensemble de
propriétés au format name: "value", :
cc_binary {
name: "gzip",
srcs: ["src/test/minigzip.c"],
shared_libs: ["libz"],
stl: "none",
}
Chaque module doit avoir une propriété name, et la valeur doit être unique dans tous les fichiers Android.bp, à l'exception des valeurs de propriété name dans les espaces de noms et les modules prédéfinis, qui peuvent se répéter.
La propriété srcs spécifie les fichiers sources utilisés pour compiler le module, sous forme de liste de chaînes. Vous pouvez référencer la sortie d'autres modules qui produisent
des fichiers sources, tels que genrule ou filegroup, à l'aide de la syntaxe de référence de module
":<module-name>".
Pour obtenir la liste des types de modules valides et de leurs propriétés, consultez la documentation de référence sur les modules Soong générée en exécutant m soong_docs. La sortie se trouvera dans out/soong/docs/soong_build.html.
Types
Les variables et les propriétés sont fortement typées, les variables étant basées dynamiquement sur la première attribution et les propriétés étant définies de manière statique par le type de module. Les types compatibles sont les suivants :
- Booléens (
trueoufalse) - Entiers (
int) - Chaînes (
"string") - Listes de chaînes (
["string1", "string2"]) - Mappages (
{key1: "value1", key2: ["value2"]})
Les mappages peuvent contenir des valeurs de n'importe quel type, y compris des mappages imbriqués. Les listes et les mappages peuvent comporter des virgules finales après la dernière valeur.
Globs
Les propriétés qui acceptent une liste de fichiers, telles que srcs, peuvent également accepter des modèles glob. Les modèles glob peuvent contenir le caractère générique UNIX normal *, par exemple
*.java. Les modèles glob peuvent également contenir un seul caractère générique ** en tant qu'élément de chemin, qui correspond à zéro ou plusieurs éléments de chemin. Par exemple, java/**/*.java correspond aux modèles java/Main.java et java/com/android/Main.java.
Variables
Un fichier Android.bp peut contenir des attributions de variables de niveau supérieur :
gzip_srcs = ["src/test/minigzip.c"],
cc_binary {
name: "gzip",
srcs: gzip_srcs,
shared_libs: ["libz"],
stl: "none",
}
Les variables sont limitées au reste du fichier dans lequel elles sont déclarées, ainsi qu'à tous les fichiers Blueprint enfants. Les variables sont immuables, à une exception près : elles peuvent être ajoutées avec une attribution +=, mais uniquement avant d'avoir été référencées.
Commentaires
Les fichiers Android.bp peuvent contenir des commentaires multilignes de style C /* */ et des commentaires sur une seule ligne de style C++ //.
Opérateurs
Les chaînes, les listes de chaînes et les mappages peuvent être ajoutés à l'aide de l'opérateur +.
Les entiers peuvent être additionnés à l'aide de l'opérateur +. L'ajout d'un mappage produit l'union des clés dans les deux mappages, en ajoutant les valeurs de toutes les clés présentes dans les deux mappages.
Modules par défaut
Les développeurs peuvent utiliser un module par défaut pour répéter les mêmes propriétés dans plusieurs modules. Exemple :
cc_defaults {
name: "gzip_defaults",
shared_libs: ["libz"],
stl: "none",
}
cc_binary {
name: "gzip",
defaults: ["gzip_defaults"],
srcs: ["src/test/minigzip.c"],
}
Modules prédéfinis
Certains types de modules prédéfinis permettent à un module d'avoir le même nom que ses homologues basés sur la source. Par exemple, il peut y avoir un cc_prebuilt_binary nommé foo lorsqu'il existe déjà un cc_binary portant le même nom. Les développeurs peuvent ainsi choisir la version à inclure dans leur produit final. Si une configuration de compilation contient les deux versions, la valeur de l'indicateur prefer dans la définition du module prédéfini détermine la version prioritaire.
Notez que certains modules prédéfinis ont des noms qui ne commencent pas par prebuilt, tels que android_app_import.
Modules d'espace de noms
Tant qu'Android n'aura pas entièrement migré de Make vers Soong, la configuration du produit Make devra spécifier une valeur PRODUCT_SOONG_NAMESPACES. Sa valeur doit être une liste d'espaces de noms séparés par des espaces que Soong exporte vers Make pour être compilés par la commande m. Une fois la migration d'Android vers Soong terminée, les détails de l'activation des espaces de noms pourront changer.
Soong permet aux modules de différents répertoires de spécifier le même nom, à condition que chaque module soit déclaré dans un espace de noms distinct. Les développeurs peuvent déclarer un espace de noms :
soong_namespace {
imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}
Notez qu'un espace de noms n'a pas de propriété name. Son chemin est automatiquement attribué comme nom.
Un espace de noms est attribué à chaque module Soong en fonction de son emplacement dans l'arborescence.
Chaque module Soong est considéré comme se trouvant dans l'espace de noms défini par le soong_namespace trouvé dans un fichier Android.bp du répertoire actuel ou du répertoire ancêtre le plus proche. Si aucun module soong_namespace de ce type n'est trouvé, le module est considéré comme se trouvant dans l'espace de noms racine implicite.
Voici un exemple : Soong tente de résoudre la dépendance D déclarée par le module M dans l'espace de noms N qui importe les espaces de noms I1, I2, I3…
- Si D est un nom complet au format
//namespace:module, seul l'espace de noms spécifié est recherché pour le nom de module spécifié. - Sinon, Soong recherche d'abord un module nommé D déclaré dans l'espace de noms N.
- Si ce module n'existe pas, Soong recherche un module nommé D dans les espaces de noms I1, I2, I3…
- Soong recherche dans l'espace de noms racine.
Expressions conditionnelles
Soong n'est pas compatible avec les expressions conditionnelles dans les fichiers Android.bp. Au lieu de cela, la complexité des règles de compilation qui nécessiteraient des expressions conditionnelles est gérée en Go, où des fonctionnalités de langage de haut niveau peuvent être utilisées et où les dépendances implicites introduites par les expressions conditionnelles peuvent être suivies. La plupart des expressions conditionnelles sont converties en une propriété de mappage, où l'une des valeurs du mappage est sélectionnée et ajoutée aux propriétés de niveau supérieur.
Par exemple, pour prendre en charge les fichiers spécifiques à l'architecture :
cc_library {
...
srcs: ["generic.cpp"],
arch: {
arm: {
srcs: ["arm.cpp"],
},
x86: {
srcs: ["x86.cpp"],
},
},
}
Formatter
Soong inclut un formateur canonique pour les fichiers Blueprint, semblable à
gofmt. Pour reformater de manière récursive tous les fichiers Android.bp du répertoire actuel, exécutez la commande suivante :
bpfmt -w .
Le format canonique inclut des retraits de quatre espaces, de nouvelles lignes après chaque élément d'une liste à plusieurs éléments et une virgule finale dans les listes et les mappages.