Interdépendances entre les outils et les bibliothèques

Les dépendances de compilation sont des composants externes requis pour compiler correctement votre projet. Une compilation peut dépendre de bibliothèques, de plug-ins et de sous-projets, du SDK Android, d'outils tels que les compilateurs Kotlin et Java, d'environnements de développement tels que Android Studio et de Gradle lui-même.

Chaque dépendance peut elle-même nécessiter d'autres dépendances. Nous les appelons dépendances transitives et peuvent augmenter rapidement les dépendances globales utilisées par votre application. Lorsque vous souhaitez mettre à niveau une dépendance, qu'il s'agisse d'une bibliothèque, d'un outil ou du SDK Android, cette mise à niveau peut se propager à de nombreuses autres dépendances.

Cela ne pose généralement aucun problème, car de nombreuses bibliothèques suivent un schéma appelé gestion sémantique des versions. Ces bibliothèques limitent les types de modifications qu'elles effectuent afin d'assurer la compatibilité avec leurs versions antérieures.

La gestion sémantique des versions suit un format major.minor.patch. Par exemple, dans le numéro de version 4.8.3, 4 correspond à la version major, 8 à la version minor et 3 au numéro patch. Lorsque la partie major change, la bibliothèque peut présenter des modifications importantes au niveau de l'API ou du comportement. Cela peut avoir une incidence sur le comportement de votre build ou de votre application.

Lorsque les parties minor (nouvelles fonctionnalités) ou patch (correction de bugs) changent, les développeurs de la bibliothèque vous indiquent que celle-ci est toujours compatible et ne devrait pas avoir d'incidence sur votre application.

Il est important de surveiller ces modifications. Plusieurs outils de mise à niveau des dépendances peuvent vous y aider.

Relations dans votre build

Les builds Android contiennent des relations entre:

  • Code source : code et ressources que vous contrôlez
  • Dépendances de bibliothèque : bibliothèques ou modules externes que votre projet et vos sous-projets incluent lors de la compilation
  • Outils : compilateurs, plug-ins et SDK qui traduisent votre source en application ou en bibliothèque
Créer des dépendances et leurs relations
Figure 1. Nouer des relations

Code source

Le code source est le code Kotlin ou Java que vous écrivez dans votre application ou votre bibliothèque. (Pour en savoir plus sur l'utilisation de C++, consultez la page NDK Android.)

Le code source dépend des bibliothèques (y compris des bibliothèques d'exécution Kotlin et Java) et du SDK Android, et nécessite le compilateur Kotlin ou Java correspondant.

Certains codes sources incluent des annotations qui nécessitent un traitement supplémentaire. Par exemple, si vous écrivez du code Jetpack Compose, vous ajoutez des annotations telles que @Composable qui doivent être traitées par le plug-in du compilateur Kotlin Compose. D'autres annotations peuvent être traitées par un processeur de symboles Kotlin (KSP) ou des outils de traitement des annotations distincts.

Dépendances des bibliothèques

Les bibliothèques contiennent du bytecode extrait dans le cadre de votre application. Il peut s'agir d'un fichier JAR Java, d'une bibliothèque Android (AAR) ou d'un sous-projet de votre build. De nombreuses bibliothèques suivent la gestion sémantique des versions, ce qui peut vous aider à déterminer quand elles restent compatibles (ou non) lors d'une mise à niveau.

Les bibliothèques peuvent dépendre d'autres bibliothèques pour la réutilisation, ce qui est appelé une dépendance transitive. Cela réduit les dépendances que vous devez gérer explicitement : vous spécifiez celles que vous utilisez directement, et Gradle les extrait en même temps que ces dépendances transitives. Sachez que lorsque vous mettez à niveau vos dépendances directes, elles peuvent mettre à niveau ces dépendances transitives.

Il est possible qu'une bibliothèque nécessite des versions minimales du SDK Android au moment de l'exécution (minSdk) ou de la compilation (compileSdk). Cela est nécessaire lorsqu'une bibliothèque utilise des fonctions incluses dans le SDK Android ou ses API JDK fournies. La minSdk effective de votre application est la minSdk la plus élevée demandée par votre application et toutes ses dépendances de bibliothèques directes et transitives.

L'utilisation de certaines bibliothèques peut nécessiter l'utilisation d'un plug-in Gradle spécifique. Ces plug-ins d'assistance installent souvent des processeurs de symboles Kotlin ou d'autres processeurs d'annotations qui génèrent du code ou modifient la compilation de votre source pour vous permettre d'utiliser les fonctionnalités de la bibliothèque. Par exemple, Jetpack Room inclut des annotations et un KSP qui les transforme en code généré pour récupérer et modifier des données dans une base de données. Jetpack Compose nécessite le plug-in de compilation Compose pour modifier les fonctions annotées afin de gérer la façon et le moment où cette fonction est réexécutée.

Outils

Gradle

Gradle est l'outil de compilation qui lit vos fichiers de compilation et génère votre application ou bibliothèque. Il expose également une API permettant aux plug-ins d'étendre ses fonctionnalités. Gradle exécute plusieurs processus sur une ou plusieurs machines virtuelles Java, et ses plug-ins Java appellent les outils Java dans le JDK.

Plug-ins Gradle

Les plug-ins Gradle étendent Gradle en définissant de nouvelles tâches et de nouvelles configurations. L'application d'un plug-in à votre compilation active des fonctionnalités de compilation spécifiques, configurées en tant que données dans vos scripts de compilation. Pour les builds Android, le plug-in Gradle le plus important est le plug-in Android Gradle (AGP).

Compilateurs

Le compilateur Kotlin ou Java transforme votre code source en bytecode exécutable. Le compilateur Kotlin expose une API de plug-in qui permet d'exécuter l'analyse externe et la génération de code directement dans le compilateur, en accédant à la structure de code analysée.

Plug-ins de compilation

Les plug-ins du compilateur effectuent une analyse et génèrent du code dans le compilateur Kotlin pendant que celui-ci analyse votre code. Ils sont installés lorsque vous appliquez leurs plug-ins Gradle au build.

SDK Android

Le SDK Android contient la plate-forme Android et les API Java pour une version spécifique d'Android, ainsi que les outils correspondants. Ces outils vous aident à gérer le SDK, à créer vos applications, et à communiquer avec et à émuler des appareils Android.

Chaque version du SDK Android fournit des API Java spécifiques auxquelles votre code source peut accéder, ainsi qu'une fonctionnalité de désugarisation pour utiliser ces API sur les versions antérieures d'Android.

JDK

Le kit de développement Java, qui contient des bibliothèques et des exécutables Java pour compiler le code source Java et exécuter des applications Java. Plusieurs JDK sont utilisés dans un build Android. Pour en savoir plus, consultez Versions de Java dans les builds Android.

Champs d'application Gradle

Gradle regroupe les dépendances de bibliothèque dans différents champs d'application (appelés configurations dans l'API Gradle), ce qui vous permet de spécifier différents ensembles de dépendances de bibliothèque à utiliser dans différentes parties de votre build. Par exemple, vous ne souhaitez probablement pas inclure de bibliothèques de test telles que JUnit dans votre application ou bibliothèque publiée, mais vous en avez besoin lorsque vous créez et exécutez vos tests unitaires. Les champs d'application permettent également d'ajouter des processeurs de symboles ou d'annotations afin d'analyser votre code.

Par exemple, AGP définit les champs d'application implementation et api, qui vous permettent de spécifier si une dépendance doit être exposée aux utilisateurs de votre sous-projet. Pour en savoir plus sur ces champs d'application et d'autres utilisés dans un build Android, consultez la section Configurer les dépendances.

Ajoutez des dépendances de bibliothèque dans le bloc dependencies de vos fichiers de compilation, sous forme de chaînes group:artifact:version:

Kotlin

// In a module-level build script
// explicit dependency strings ("group:artifact:version")
dependencies {
    implementation("com.example:library1:1.2.3")
    api("com.example:library2:1.1.1")
}

Groovy

// In a module-level build script
// explicit dependency strings ("group:artifact:version")
dependencies {
    implementation 'com.example:library1:1.2.3'
    api 'com.example:library2:1.1.1'
}

ou dans un catalogue de versions:

# Version catalog - gradle/libs.versions.toml
[versions]
exampleLib = "1.2.3"
examplePlugin = "2.3.4"

[libraries]
example-library = { group = "com.example", name = "library", version.ref = "exampleLib" }

[plugins]
example-plugin = { id = "com.example.plugin", version.ref = "examplePlugin" }

et spécifiez les variables générées dans vos fichiers de compilation:

Kotlin

// In a module-level build script
// Using a version catalog
plugins {
    alias(libs.plugins.example.plugin)
}

dependencies {
    implementation(libs.example.library)
}

Groovy

// In a module-level build script
// Using a version catalog
plugins {
    alias(libs.plugins.example.plugin)
}

dependencies {
    implementation libs.example.library
}