I. Introduction▲
Gérer le build d'un projet logiciel a toujours été une tâche plus ou moins ingrate dans la vie d'un développeur. Les plus anciens d'entre vous peuvent en témoigner, le chemin a été long depuis l'époque des makefiles, des scripts shell et des scripts Ant. Néanmoins, l'arrivée de Maven en 2004 a permis une nette amélioration des choses pour les projets Java. Dix ans après son lancement, Maven est devenu le standard pour la majorité des développements.
N'avez-vous jamais pesté contre la gestion des exclusions et les obscures dépendances transitives ? N'avez-vous jamais détourné le fonctionnement d'un plugin pour arriver à vos fins ? Ne vous êtes-vous jamais sentis frustrés par l'outil ? Si c'est le cas, c'est que vous êtes probablement mûrs pour essayer Gradle.
Cet article trouve son origine dans une conférence donnée au Devoxx France 2014. L'orateur du jour, Cédric Champeau (@CedricChampeau), est un fervent partisan de Groovy le langage sur lequel Gradle repose. Pendant une heure, ce dernier nous a exposé pourquoi il était temps de trouver un successeur à Maven, et en quoi Gradle pouvait reprendre le flambeau et aller plus loin.
II. Structurer le build▲
Au-delà de la gestion des dépendances, Maven se veut aussi un structurateur de build grâce au principe de la « convention over configuration ».
Ce rôle de structurateur passe aussi par l'idée que le processus de build comporte un ensemble d'étapes récurrentes et prédéfinies afin d'obtenir l'artefact final.
Ces conventions permettent d'uniformiser la structure d'un projet et sont des hypothèses fortes sur comment vous devriez organiser votre code. Mais ces dernières ne seraient-elles pas trop fortes ?
II-A. Au secours mon projet sort de l'ordinaire !▲
Dans le cadre d'un projet en phase de démarrage, il est facile de se conformer à ces conventions. Quid de mes projets historiques, que faire si la structure de mon projet s'éloigne trop de celle imaginée par les concepteurs de Maven ?
Beaucoup de développeurs se mettront en quête d'un plugin tiers (s'il existe) ou spécifiquement développé pour l'occasion. La multitude de plugins créés pour pallier ces situations est une preuve indirecte du manque de flexibilité de l'outil. Il suffit, pour s'en convaincre, de parcourir la liste des plugins officiels sur codehaus.org. Chacun a été développé dans le but de pallier une situation précise qui n'était pas obligatoirement prise en compte dans le cycle de vie habituel de Maven. Et c'est justement là où réside le plus gros problème de Maven actuellement.
Objectivement parlant, adapter le cycle de vie en rajoutant une étape et/ou une tâche spécifique n'est pas réalisable de manière simple. La seule alternative reste de se raccrocher à l'étape qui semble la plus proche. Maven se comporte ici comme une boîte noire avec en entrée du code et un artefact en sortie. Entre ces deux étapes, le développeur ne garde pas la main sur les opérations réalisées.
Certes Gradle utilise aussi le concept de « convention over configuration » associé à un cycle de vie par défaut, mais contrairement à son prédécesseur, la modification de la mécanique de build reste possible. Voyons comment.
III. Ouvrir la boîte noire▲
La base du processus du build est le fichier build.gradle. Ce fichier, rédigé en Groovy, sert tout d'abord à définir les propriétés de votre build. Commençons par définir nos entrepôts d'artefacts.
III-A. Gestion des entrepôts d'artefacts▲
Avec Maven, travailler avec un entrepôt d'artefacts se limite très rapidement aux entrepôts ne contenant que des artefacts Maven. Gradle, au contraire, supporte plusieurs types d'entrepôts (entrepôts locaux ou distants, artefacts Maven, Ivy ou simples jar). La déclaration se fait de manière relativement aisée comme nous le montrent les exemples suivants :
repositories {
mavenCentral
(
)
}
repositories {
mavenLocal
(
)
}
repositories {
flatDir {
dirs 'lib'
, 'myLib'
}
}
III-B. Do you speak Java ? Sprechen Sie Groovy ? ¿Hablas Scala ?▲
Idéologiquement, Maven reste un outil orienté Java. Pour autant, est-ce que le processus de build d'un artefact est fonction du langage dans lequel il est codé ? Évidemment non. C'est donc dans cette optique que Gradle supporte le polyglottisme. Le passage d'un langage à un autre se fait très simplement par le seul changement du plugin appelé.
apply plugin: 'java'
apply plugin: 'groovy'
III-C. Prédictibilité du build et de l'artefact▲
Vous l'aurez probablement remarqué, un descripteur de build Maven ne pose pas de préconditions sur l'exécution du build. La seule condition à respecter est que le descripteur soit syntaxiquement correct pour la version de Maven que vous utilisez.
Imaginez à présent qu'un autre développeur récupère votre pom.xml, mais l'utilise avec une autre version Maven. Pire encore, et si c'était votre serveur d'intégration continue qui ne disposait pas de la même version ? La compatibilité descendante est certes souvent assurée, mais rien n'est moins sûr pour la compatibilité ascendante.
Pour contrer cela, Gradle dispose d'un système de wrapper. Grâce à ce dernier, vous êtes assuré que votre build sera exécuté avec la version spécifiée, même si la machine réalisant le build ne dispose pas de cette version.
L'intérêt de ce wrapper est évident pour les équipes de développement et notamment pour éviter le fameux « je ne comprends pas, cela compilait chez moi ».
task wrapper
(
type: Wrapper) {
gradleVersion =
'1.4'
}
III-D. Groovy à la rescousse▲
Comme évoqué précédemment, le fichier build.gradle utilise le langage Groovy. Ce choix permet de remplacer une syntaxe XML verbeuse et monolithique nuisant à la lisibilité du descripteur. Mais ce n'est pas tout.
L'utilisation d'un tel langage permet surtout d'enrichir directement le processus de build, car le descripteur dispose d'une API donnant accès à la mécanique interne de Gradle. Une analogie simple serait de dire que le descripteur n'est rien d'autre qu'une classe héritant du descripteur par défaut, et à ce titre, il peut redéfinir, surcharger ou enrichir tout ou partie du comportement de Gradle.
On parle alors de « convention over configuration », car en plus des conventions par défaut, vous pouvez définir vos propres conventions si un besoin spécifique se fait sentir.
Un très bon exemple d'enrichissement du descripteur de build est disponible au sein du projet Android tools qui a récemment adopté Gradle. En effet, malgré l'arrivée des profils, Maven reste campé sur sa position du « 1 pom.xml = 1 artefact » ; ce qui rend difficile la customisation du processus de build en fonction de la plate-forme ciblée.
Dans le cas des applications Android, il convient de pouvoir gérer simultanément les éléments suivants :
- la plate-forme matérielle (x86, ARM, Mips…) ;
- le format (smartphone, tablette, phablet…) ;
- la fragmentation de l'OS (Froyo, JellyBean, KitKat…) ;
- les déclinaisons gratuites ou payantes.
Décrire la manière dont cette gestion est réalisée serait fastidieux. Je vous invite donc à lire directement la documentation du projet ADT ici et là.
Néanmoins, l'existence de ce projet et sa capacité à produire des artefacts en fonction de la plate-forme ciblée prouve toute la flexibilité du DSL de Gradle. Avec cette syntaxe, on accède non seulement à un descripteur de build, mais aussi à une API complète de customisation du processus. Et c'est justement cela qu'il faut retenir de Gradle, à savoir qu'il va au-delà de ce que propose Maven actuellement.
IV. En conclusion▲
Le but de cet article n'est pas de tirer un boulet rouge sur Maven qui a rendu des services inestimables à un moment où les processus de build devaient être rationalisés. Il continuera certainement d'être utilisé dans de nombreux projets grâce à ses nombreux avantages. Néanmoins, en sortant de la conférence de Cédric Champeau, il faut se demander si le changement n'est pas pour maintenant. Maven a amorcé le mouvement des structurateurs de build, mais il est temps de se projeter un peu plus dans l'avenir et de lui trouver un remplaçant. Et à mon sens, Gradle est bien parti .
V. Pour aller plus loin▲
- Blog de Cédric Champeau : http://melix.github.io/blog/
- Slides de la présentation au Devoxx France : https://speakerdeck.com/melix/gradle-ne-fait-pas-que-remplacer-maven
- Gradle User Guide : http://www.gradle.org/docs/current/userguide/userguide.html
- Android tools project-Gradle plugin user guide : http://tools.android.com/tech-docs/new-build-system/user-guide
- Android tools project - Gradle plugin user guide (Build variants) : http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
- Android developpers-Multiple APK support : http://developer.android.com/google/play/publishing/multiple-apks.html
VI. Remerciements▲
Cet article a été publié avec l'aimable autorisation de la société Soat.
Nous tenons à remercier Malick SECK et Jacques THÉRY pour leur relecture orthographique attentive de cet article et Régis Pouiller pour la mise au gabarit.