Présentation de la compilation Gradle

Les applications Android sont généralement créées à l'aide du build Gradle. du système d'exploitation. Avant d'entrer dans les détails de la configuration de votre build, explorer les concepts qui sous-tendent la compilation afin de visualiser le système dans son ensemble.

Qu'est-ce qu'un build ?

Un système de compilation transforme votre code source en une application exécutable. Les compilations impliquent souvent plusieurs outils pour analyser, compiler, associer et empaqueter une application ou une bibliothèque spécifiques. Gradle utilise une approche basée sur les tâches pour organiser et exécuter ces commandes.

Les tâches encapsulent les commandes qui traduisent leurs entrées en de sortie. Les plug-ins définissent les tâches et leur configuration. Application en cours un plug-in à votre build enregistre ses tâches et les relie entre elles à l'aide de leur entrées et sorties. Par exemple, en appliquant le plug-in Android Gradle (AGP) à votre fichier de compilation enregistre toutes les tâches nécessaires à la création d'un fichier APK, ou un fichier Bibliothèque Android. Le plug-in java-library vous permet de créer un fichier JAR à partir d'une source Java. du code source. Il existe des plug-ins similaires pour Kotlin et d'autres langages, mais d'autres plug-ins sont destinés à étendre les plug-ins. Par exemple, le plug-in protobuf est destiné à ajouter Prise en charge des tampons de protocole pour les plug-ins existants tels qu'AGP ou java-library.

Gradle privilégie la convention plutôt que la configuration pour que les plug-ins offrent valeurs par défaut prêtes à l'emploi, mais vous pouvez configurer davantage la compilation via un Langage spécifique au domaine (DSL) déclaratif. Le DSL est conçu Pouvez-vous spécifier quoi compiler plutôt que comment le compiler ? La logique les plug-ins gèrent le « comment ». Cette configuration est spécifiée fichiers de compilation dans votre projet (et vos sous-projets).

Les entrées des tâches peuvent être des fichiers et des répertoires, ainsi que d'autres informations encodées sous forme Types Java (entiers, chaînes ou classes personnalisées). Les sorties ne peuvent être que des répertoires ou des fichiers, car ils doivent être écrits sur le disque. Connecter la sortie d'une tâche à une autre une entrée de tâche, relie les tâches entre elles afin que l'une doive s'exécuter avant l'autre.

Bien que Gradle prenne en charge l'écriture de code arbitraire et de déclarations de tâches dans votre build les fichiers, cela peut rendre plus difficile pour les outils de comprendre votre compilation et à gérer. Par exemple, vous pouvez écrire des tests pour le code dans des plug-ins. mais pas dans les fichiers de compilation. Vous devez plutôt limiter la logique et les tâches de compilation aux plug-ins (que vous ou une autre personne définissez) et déclarez comment vous voulez utiliser cette logique dans vos fichiers de compilation.

Que se passe-t-il lorsqu'un build Gradle s'exécute ?

Les compilations Gradle s'exécutent en trois phases. Chacune de ces phases exécute différentes parties de code que vous définissez dans vos fichiers de compilation.

  • L'initialisation détermine les projets et sous-projets inclus dans la compilation, et configure des classpaths contenant vos fichiers de compilation et plug-ins. Cette phase se concentre sur un fichier de paramètres dans lequel vous déclarez les projets et les emplacements à partir desquels récupérer les plug-ins et les bibliothèques.
  • Configuration enregistre les tâches pour chaque projet et exécute la compilation pour appliquer les spécifications de compilation de l'utilisateur. Il est important de comprendre que votre code de configuration n'aura pas accès aux données ou aux fichiers générés pendant l'exécution.
  • L'exécution effectue le "bâtiment" de votre application. Le résultat de configuration est un graphe orienté acyclique (DAG) de tâches, représentant toutes les étapes de compilation requises par l'utilisateur (les fournies sur la ligne de commande ou comme valeurs par défaut dans les fichiers de compilation). Ce graphique représente la relation entre les tâches, explicite dans le ou en fonction de ses entrées et sorties. Si une tâche contient une entrée est le résultat d'une autre tâche, elle doit alors s'exécuter après l'autre tâche. Ce exécute des tâches obsolètes dans l'ordre défini dans le graphique ; si une tâche n'ont pas changé depuis sa dernière exécution, Gradle l'ignore.

Pour en savoir plus, consultez le cycle de vie de compilation Gradle.

DSL de configuration

Gradle utilise un langage spécifique au domaine (DSL) pour configurer compilations. Cette approche déclarative se concentre sur la spécification de vos données rédiger des instructions étape par étape (impératives).

Avec les DSL, tout le monde, les experts du domaine et les programmeurs contribuent à un projet, en définissant un petit langage qui représente les données dans un de manière plus naturelle. Les plug-ins Gradle peuvent étendre le DSL pour configurer les données qu'ils dont ils ont besoin pour leurs tâches.

Par exemple, la configuration de la partie Android de votre build peut ressembler à ceci:

Kotlin

android {
    namespace = "com.example.app"
    compileSdk = 34
    // ...

    defaultConfig {
        applicationId = "com.example.app"
        minSdk = 34
        // ...
    }
}

Groovy

android {
    namespace 'com.example.myapplication'
    compileSdk 34
    // ...

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdk 24
        // ...
    }
}

En arrière-plan, le code DSL ressemble à ceci:

fun Project.android(configure: ApplicationExtension.() -> Unit) {
    ...
}

interface ApplicationExtension {
    var compileSdk: Int
    var namespace: String?

    val defaultConfig: DefaultConfig

    fun defaultConfig(configure: DefaultConfig.() -> Unit) {
        ...
    }
}

Chaque bloc du DSL est représenté par une fonction qui prend un lambda pour la configurer, et une propriété portant le même nom pour y accéder. Ainsi, le code dans vos fichiers de compilation ressemble davantage à une spécification de données.

Dépendances externes

Le système de compilation Maven a introduit une spécification de dépendance, de stockage et de gestion. Les bibliothèques sont stockées dans dépôts (serveurs ou répertoires), ainsi que des métadonnées incluant leur version et leurs dépendances sur d'autres bibliothèques. Vous spécifiez les dépôts que vous souhaitez rechercher, les versions des dépendances que vous souhaitez utiliser le système de compilation les télécharge pendant la compilation.

Les artefacts Maven sont identifiés par le nom du groupe (entreprise, développeur, etc.), ou par artefact nom (nom de la bibliothèque) et version de cet artefact. Il s'agit généralement représentée par group:artifact:version.

Cette approche améliore considérablement la gestion des builds. Vous entendrez souvent "Maven Repositories", mais il s'agit de les artefacts sont empaquetés et publiés. Ces référentiels et métadonnées ont été réutilisé dans plusieurs systèmes de compilation, y compris Gradle (et Gradle peut publier dans dans ces dépôts). Les référentiels publics permettent un partage pour tous, et les référentiels de l’entreprise conservent les dépendances internes en interne.

Vous pouvez également modulariser votre projet en sous-projets. (également appelés "modules" dans Android Studio), qui peuvent également être utilisés comme les dépendances. Chaque sous-projet produit des sorties (telles que des fichiers JAR) qui peuvent être consommés par les sous-projets ou votre projet de niveau supérieur. Cela peut réduire la durée de compilation en isolant les pièces à reconstruire responsabilités dans l'application.

Nous verrons plus en détail comment spécifier des dépendances dans la section Ajouter dépendances.

Variantes de compilation

Lorsque vous créez une application Android, vous devez en général créer plusieurs variantes. Les variantes contiennent un code différent ou sont construites avec disponibles, et sont composées de types de compilation et de types de produit.

Les types de compilation varient selon les options de compilation déclarées. Par défaut, l'AGP configure le paramètre "release" et "debug" types de compilation, mais vous pouvez les ajuster et en ajouter d'autres (par exemple, en préproduction ou en test interne).

Une version de débogage ne réduit ni n'obscurcit votre application, ce qui accélère son construire et préserver tous les symboles tels quels. Il marque également l'application comme "débogable", en le signant avec une clé de débogage générique et en autorisant l'accès au les fichiers d'application installés sur l'appareil. Cela permet d'explorer des données enregistrées dans des fichiers et des bases de données tout en exécutant l'application.

Un build optimise l'application, la signe avec votre clé de release protège les fichiers d’application installés.

À l'aide des types de produit, vous pouvez modifier la source incluse et la dépendance variantes de l'application. Par exemple, vous pouvez créer "demo" et "complet" pour votre application, ou "sans frais" et "payant" les différentes saveurs. Vous écrivez votre source commune dans un bloc "principal" source set (ensemble de sources) et remplacer ou ajouter une source dans un ensemble de sources nommé d'après le type.

AGP crée des variantes pour chaque combinaison de type de compilation et de type de produit. Si vous ne définissez pas de types, les variantes portent le nom des types de compilation. Si vous lorsque vous définissez les deux, la variante est nommée <flavor><Buildtype>. Par exemple, avec build les types release et debug, et les types demo et full, AGP créera variantes:

  • demoRelease
  • demoDebug
  • fullRelease
  • fullDebug

Étapes suivantes

Maintenant que vous connaissez les concepts de compilation, découvrez la version d'Android structure de votre projet.