Comparatif des outils de build pour Java

| Romain Linsolas | Grégory Boissinot |

Cet article recense les principaux outils de construction (builds) de projets informatiques écrits en Java.

Commentez ♪

- Titre : Comparatif des outils de build pour Java

- Auteurs : Romain Linsolas, Grégory Boissinot

- Parution : 23 novembre 2009

- Licence : Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- I. Introduction

- I-A. But de cet article

- I-B. Glossaire

- I-C. Définition et intérêts d'un outil de build

- I-D. Les outils

- II. Ligne de commandes, Makefile, batch

- II-A. Présentation

- II-B. Avantages

- II-C. Inconvénients

- III. Ant

- III-A. Présentation

- III-B. Avantages

- III-C. Inconvénients

- III-D. Références

- IV. Ivy

- IV-A. Présentation

- IV-B. Avantages

- IV-C. Inconvénients

- IV-D. Références

- V. Maven

- V-A. Présentation

- V-A-1. Historique

- V-A-2. Principes

- V-A-3. Gestion des dépendances

- V-A-4. Site et rapports

- V-B. Avantages

- V-C. Inconvénients

- V-D. Références

- V-E. Un mot sur Maven 3

- VI. Gradle

- VI-A. Présentation

- VI-A-1. L'architecture

- VI-A-2. Principes

- VI-A-3. Notion de tâches

- VI-A-4. Gestion des dépendances

- VI-B. Avantages

- VI-C. Inconvénients

- VI-D. Références

- VII. Quelques autres outils

- VIII. Matrices

- VIII-A. Généralités

- VIII-B. Intégration dans les IDE

- VIII-C. Utilisation dans l'Intégration Continue

- IX. Conclusion

- X. Remerciements

I - Introduction

I-A - But de cet article

Le but de cet article est de faire un tour rapide sur les différents outils de builds dans le monde Java. Nous aborderons essentiellement les outils Ant (avec ou sans Ivy), Maven (1 et 2), ainsi que Gradle.

Nous n'aborderons ici que les solutions propres à Java. Toutefois, certains de ces outils sont également capables de construire des projets écrits dans d'autres langages : Ruby, C / C++, .Net, etc. Nous n'incluons cependant pas les outils propres à ces derniers dans notre comparatif.

I-B - Glossaire

Nous définissons ici quelques termes ou concepts que nous serons amenés à rencontrer souvent dans cet article.

Terme

Définition

build / builder

Construction / Construire un projet informatique.

Dépendance transitive

Le projet que l'on gère a sa propre liste de dépendances, mais certaines d'entre elles ont également besoin de librairies supplémentaires. Ces dernières, qui ne sont pas des dépendances directes de notre projet, sont appelées dépendances transitives.

Intégration Continue

L'intégration continue est un ensemble de pratiques utilisées en génie logiciel visant à vérifier que chaque modification de code source ne produit pas de régression de l'application en cours de développement. Il existe un certain nombre d'outils permettant de mettre en place l'Intégration Continue : Hudson, Cruise Control, Continuum, TeamCity, etc.

livrable (ou artefact)

Produit final de la construction du projet. Il peut s'agir d'un exécutable, d'une librairie Java (JAR), d'une application web (WAR), d'un ZIP, etc.

repository

Endroit où sont stockés les différents artefacts, les librairies, etc.

Test unitaire

Classe Java permettant de tester fonctionnellement une autre classe Java. Ils sont utiles pour s'assurer qu'une classe ou une méthode fait bien ce qu'elle est censée faire, mais également pour détecter les possibles régressions créées par la modification du code source. Ils sont généralement exécutés par JUnit ou TestNG.

I-C - Définition et intérêts d'un outil de build

Build signifie construction en anglais. Par voie de conséquence, un outil de build est un outil destiné - entre autres - à construire un projet informatique pour obtenir un livrable (ou un « artefact ») tel qu'un exécutable, un JAR ou encore un WAR (destiné à être déployé sur un serveur d'applications). Ce processus permet de transformer le code source, qui n'est finalement qu'un ensemble de fichiers texte, en fichiers binaires exécutables par le système (ou une machine virtuelle). Il s'agit ici de la phase de compilation. Toutefois, la construction d'un projet ne se résume pas à cette seule tâche de compilation.

Ainsi, si l'on prend exemple sur le cycle de vie défini par l'outil Apache Maven2, le processus complet peut se diviser en un certain nombre de tâches, dont voici les principales étapes.

- Préparation des fichiers de ressources, par exemple en adaptant les fichiers de propriétés à l'environnement cible (environnement de développement, d'homologation, de production…).

- Compilation des sources Java.

- Ces mêmes tâches sont ensuite exécutées sur les ressources et le code source des tests unitaires.

- Les tests unitaires sont alors exécutés sur le projet.

- Les livrables (JAR, WAR, EAR, ZIP, etc.) sont enfin créés, comprenant les binaires et les ressources du projet.

Les principales étapes du cycle de vie défini par Maven2 (Maven: The Definitive Guide)

À ces tâches peuvent s'ajouter d'autres tâches supplémentaires, telles que :

- déploiement du livrable ainsi créé, soit sur un « repository » général, soit sur un serveur d'applications (Tomcat, Glassfish, etc.) ;

- création de rapports de qualité du code (Sonar, Checkstyle, Cobertura, PMD, FindBugs, JUnit, etc.) ;

- génération et déploiement du site du projet.

On le voit, la compilation est ainsi accompagnée de nombreuses autres tâches. Les réaliser manuellement pose de sérieux problèmes : non seulement cela prend du temps, mais plus les tâches sont complexes, plus le risque d'erreurs est important.

Il est donc primordial d'automatiser ces tâches. Ainsi, l'automatisation va nous permettre :

- d'accélérer les builds ;

- de les rendre plus fiables, grâce à l'exclusion de l'intervention humaine ;

- de réaliser des tâches complexes relativement simplement ;

- de les rendre indépendants d'une plateforme particulière. Combien de compilations réussissent sur un poste de développeur complètement configuré, mais pas sur une machine fraîchement installée ?

- de réaliser des builds de façon périodique (chaque nuit par exemple), ou encore à chaque modification du code source. On arrive ici sur le principe de l'Intégration Continue.

Le choix d'un outil de build va donc permettre de nous aider à réaliser ces opérations avec plus ou moins de facilité.

I-D - Les outils

Le langage Java est très répandu, et par conséquent, le nombre d'outils pour réaliser telle ou telle tâche est généralement élevé. Pourtant, dès que l'on s'intéresse aux outils de builds, à première vue, on constate que le nombre d'outils est plutôt faible. En réalité, il existe de nombreux outils : Ant, Maven, Gradle, GAnt, EasyAnt, etc. Toutefois, seule une poignée d'entre eux sont vraiment connus et réputés. On notera que la plupart des outils vus ici sont proposés par la fondation Apache : Ant, Ivy, Maven 1 ou 2…

Nous aborderons ici les plus communs de ces outils, en insistant sur les caractéristiques minimales requises pour cette catégorie d'outils, à savoir :

- facilité de prise en main ;

- intégration dans les outils de développement (IDE ou serveurs d'Intégration Continue) ;

- pérennité ;

- documentation complète ;

- adaptation à de nombreux types de projets différents.

Notons également que j'avais initié ici un sondage sur le site developpez.com afin de connaître la répartition de l'utilisation des outils de builds dans le monde Java. Les résultats sont les suivants (à l'heure actuelle, 188 votants, choix multiples autorisés) :

Outils

Votes

Pourcentage *

Pourcentage corrigé **

Maven 2

82

43,62 %

30,83 %

IDE ***

81

43,09 %

30,45 %

Ant

75

39,89 %

28,20 %

Make / script

12

6,38 %

4,51 %

Ant + Ivy

7

3,72 %

2,63 %

Gradle

1

0,53 %

0,38 %

Autres

8

4,26 %

3 %

Total

266

141,9 % *

100 %

* La somme des pourcentages excède 100 % compte tenu de la possibilité des votants de choisir plusieurs outils.
** Ce pourcentage montre la proportion de votes qu'a obtenus un outil par rapport au nombre total de votes (266).
*** Cette option est un peu faussée étant donné que l'on utilise souvent Ant ou Maven 2 au sein de son IDE pour construire les projets.

On constate donc que Maven et Ant restent les solutions privilégiées par les développeurs !

II - Ligne de commandes, Makefile, batch

II-A - Présentation

Au début de l'histoire de Java, la construction des projets s'avérait relativement simple, et leur compilation pouvait se réaliser par une simple commande javac. De fait, la ligne de commandes, le Makefile (hérité du monde Unix) ou le fichier de script (.sh ou .bat) pouvait très bien remplir ce rôle. Mais avec la complexification de la compilation (gestion des dépendances, manipulation des fichiers de ressources, etc.), mais également avec l'envie de faire plus que de la simple compilation (exécution des tests, déploiement de l'artefact, etc.), cette solution ne semble plus du tout envisageable aujourd'hui.

II-B - Avantages

- On peut faire pratiquement tout ce que l'on veut (mais à quel coût ?) !

- Euh…

II-C - Inconvénients

- Maintenance difficile.

- Devient très vite complexe.

- Fonctionnalités limitées.

- Dépendant de l'OS.

- Tout plein d'autres choses.

III - Ant

III-A - Présentation

Ant est un projet open source de la fondation Apache. Ant repose sur un fichier XML (le build.xml) qui est un ensemble de cibles (ou targets) ayant chacune un rôle bien précis dans la construction du projet : nettoyage de répertoires, initialisation, compilation, transfert de fichiers, etc. Chaque cible est décomposée en un ensemble de tâches, chaque tâche étant destinée à réaliser une opération particulière. Ainsi, la tâche <javac …/> a pour rôle de compiler des classes Java, la tâche <copy …/> copiera un ensemble de fichiers, etc.

Ci-dessous, un exemple de fichier build.xml pour Ant :

<project name="MyProject" default="dist" basedir=".">
<description>simple example build file</description>
<!-- set global properties for this build -->
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist"  location="dist"/>

<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
</target>

<target name="compile" depends="init" description="compile the source " >
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}"/>
</target>

<target name="dist" depends="compile" description="generate the distribution" >
<!-- Create the distribution directory -->
<mkdir dir="${dist}/lib"/>
<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
<jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
</target>

<target name="clean" description="clean up" >
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
</project>

La force d'Ant, en plus d'une intégration parfaite dans la plupart des outils de développement, est la disponibilité d'une large panoplie de tâches. La liste des tâches « officielles » compte autour d'une centaine d'éléments !

III-B - Avantages

- Intégré dans la quasi-totalité des IDE.

- Supporté nativement par les outils d'Intégration Continue.

- Connu pratiquement par tout le monde, il est aussi enseigné dans les écoles.

- De nombreuses tâches sont disponibles.

- On peut tout faire avec Ant.

- Plutôt facile à prendre en main, relativement intuitif.

- Grande flexibilité.

III-C - Inconvénients

- Devient vite verbeux.

- Finalement, cela reste un script (amélioré, certes).

- Pas de conventions dans l'écriture du XML, ce qui amène de la complexité dans le script.

- Aucun mécanisme de gestion des dépendances.

- Création complexe et répétitive d'un processus complet de création d'un artefact JAR ou WAR (compilation, tests, package…).

III-D - Références

- Site officiel d'Ant

- Forum developpez.com sur Ant

- Prise en main d'Ant (tutoriel developpez.com)

- Déboguer un script Ant avec NetBeans (tutoriel vidéo developpez.com)

- Courte introduction à Ant : partie 1 et partie 2 (tutoriels developpez.com)

- Projet Ant Script Library, regroupant des scripts Ant réutilisables.

IV - Ivy

IV-A - Présentation

Le projet Apache Ivy est en réalité une extension à Ant permettant avant tout de disposer d'un véritable mécanisme de gestion des dépendances. Comme nous l'avons vu dans le chapitre sur Ant, ce dernier ne dispose d'aucun gestionnaire de dépendances, contrairement à Maven 2 (voir chapitre suivant).

Ci-dessous, un exemple simple de fichier ivy.xml, définissant les dépendances directes de notre projet :

<ivy-module version="2.0">
<info organisation="apache" module="hello-ivy"/>
<dependencies>
<dependency org="commons-lang" name="commons-lang" rev="2.0"/>
<dependency org="commons-cli" name="commons-cli" rev="1.0"/>
</dependencies>
</ivy-module>

Il suffit alors d'ajouter une cible à son build.xml géré par Ant pour utiliser Ivy :

<project xmlns:ivy="antlib:org.apache.ivy.ant" name="hello-ivy" default="run">
...
<!-- Résoud les dépendances -->
<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve />
</target>
</project>

À noter qu'Ivy va utiliser par défaut le repository de Maven 2 (la librairie des dépendances gérée par Maven 2). Ainsi, nous évitons de gérer plusieurs librairies de dépendances sur sa propre machine ou sur un serveur.

À tout cela s'ajoute la possibilité de générer des rapports sur l'utilisation des dépendances, ainsi que sur leur hiérarchie. En voici quelques exemples : exemple 1, exemple 2 ou encore sous forme d'image :

IV-B - Avantages

- Se base sur Ant, l'un des outils les plus utilisés et connus en Java.

- Moins verbeux que Maven 2 (en ce qui concerne la déclaration des dépendances).

- Permet de générer des rapports.

- Gère les dépendances transitives.

- Peut utiliser le repository de Maven 2.

- Ivy peut être invoqué par des API, et donc hors d'Ant.

- Propose des services supplémentaires par rapport à Maven en fournissant par exemple une gestion intelligente des exclusions, la possibilité de désactiver la transitivité des dépendances (y compris pour les dépendances Maven), ainsi qu'un algorithme de résolution de conflits plus avancé.

- Contrairement à Maven, il est possible de générer plusieurs artefacts différents pour un même projet.

IV-C - Inconvénients

- Ne se charge que des dépendances et ne résout pas les autres lacunes d'Ant. Toutefois, ce ne sont pas là les objectifs d'Ivy…

- Faible popularité, et évolution relativement lente.

IV-D - Références

- Site officiel d'Ivy.

- IvyIDE, intégration d'Ivy dans Eclipse.

V - Maven

V-A - Présentation

V-A-1 - Historique

Maven 1, développé en 2002 en tant que sous-projet du projet Apache Turbine, est devenu un projet Apache à part entière en 2003. Toutefois, cette version n'a pas rencontré un succès notoire.

Maven 2, est apparu fin 2005. Reprenant les bases de Maven 1, il a été complètement refondu et a corrigé nombre de lacunes de son prédécesseur. Il est depuis devenu l'un des outils les plus utilisés pour réaliser la construction de projets Java. C'est d'ailleurs généralement l'outil adopté lors du démarrage d'un nouveau projet.

V-A-2 - Principes

Maven prend une autre direction que celle empruntée par Ant. Ici, il n'est plus question de créer un fichier XML décrivant précisément les tâches que l'on doit exécuter pour construire son projet. Maven 2 propose de décrire son projet, Maven 2 s'adaptant alors à cette description pour construire le projet.

Le fichier principal, le pom.xml (signifiant Project Object Model), va donc décrire le projet. Nous y trouvons entre autres :

- l'endroit où se situent le code source et les fichiers de ressources ;

- la version de Java utilisée pour compiler le code source ;

- les dépendances directes du projet ;

- les plugins utilisés ;

- les rapports techniques demandés ;

- etc.

En plus de cela, Maven 2 insiste sur le principe de favoriser l'utilisation des conventions plutôt que de configurer son projet. En anglais, ce principe porte le nom de Convention over Configuration (la Convention plutôt que la Configuration). Ainsi, si l'on respecte certaines conventions définies par Maven 2, il devient inutile de préciser certaines informations dans son pom.xml. Par exemple, Maven 2 préconise l'utilisation du répertoire src/main/java pour stocker les fichiers source du projet. En respectant ceci, il devient alors inutile de spécifier à Maven 2 où se trouvent les sources Java, ce qui allège d'autant l'écriture du pom.xml.

Grâce à ce principe, il est possible d'écrire un pom.xml minimaliste de six lignes :

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0</version>
</project>

Avec ce simple pom.xml il devient possible de réaliser tout le processus de construction d'un projet avec Maven 2, à savoir :

- gérer les fichiers de ressources ;

- compiler les sources Java ;

- compiler et exécuter les tests unitaires ;

- créer le fichier JAR du projet ;

- déployer le JAR.

Cela est possible, car Maven 2 définit un cycle de vie très précis sur lequel vient se calquer la construction du projet. On peut voir ici une introduction complète du cycle de vie défini par Maven 2.

V-A-3 - Gestion des dépendances

Êtes-vous déjà arrivé sur un projet possédant un répertoire lib contenant plusieurs dizaines de librairies JAR ? À quelle version de la librairie correspondent-elles ? Quelle est la raison de leur présence : est-ce une dépendance de notre projet ou une dépendance de l'une de nos dépendances ?

Maven 2 résout ce problème de deux façons : d'une part grâce aux repositories, ces « services de stockage de librairies », et d'autre part à la façon dont on déclare les dépendances dans le pom.xml.

Comme on l'a vu sur le pom.xml minimaliste, une librairie est définie par trois informations : le groupId, l'artifactId et la version. Tous les projets utilisant Maven 2 disposent obligatoirement de ces informations. Ainsi, lorsque l'on a besoin d'indiquer à Maven 2 nos dépendances, il suffit simplement de connaître ces trois informations, et les préciser dans le pom.xml. Par exemple, si l'on souhaite utiliser la librairie log4j dans sa version 1.2.14, il suffira d'ajouter le code XML suivant :

<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<dependency>
</dependencies>

Maven 2 se chargera alors de récupérer le fichier JAR depuis un repository global, puis de le copier sur le repository local, pour enfin pouvoir l'utiliser dans le classPath du projet (et éventuellement l'inclure dans le paquetage final). Le processus exact est celui-ci :

1. Maven commence par définir la liste des dépendances nécessaires au projet, via la lecture du pom.xml du projet.

2. Maven interroge alors le repository local afin de trouver les dépendances utilisées.

3. Si la dépendance n'est pas trouvée, alors Maven va interroger les repositories distants.

4. Les dépendances absentes du repository local sont alors téléchargées depuis les repositories distants, de telle façon à ce qu'elles soient disponibles lors des prochains builds.

5. Maven peut alors utiliser la dépendance pour la construction du projet.

L'intérêt de ce mécanisme, en plus de sa simplicité, est que nous ne définissons plus que les dépendances directes de notre projet. Les dépendances de nos dépendances, autrement appelées dépendances transitives sont directement gérées par Maven 2, et ne préoccupent plus l'esprit du développeur.

En addition à tout cela, Maven 2 intègre aussi la notion de scope qui permet de limiter l'utilisation d'une dépendance à un cycle bien précis. Cela est très utile, entre autres, pour la dépendance JUnit, que nous limiterons au scope test, ce qui aura pour conséquence de ne pas inclure le JAR de JUnit dans le package final (le WAR par exemple).

V-A-4 - Site et rapports

Sans ajout particulier, Maven permet la génération d'un site web complet sur le projet. La seule chose à faire est de lancer la commande mvn site ! Ce site contient alors un certain nombre d'informations propres au projet, telles que les dépendances déclarées, la liste des développeurs, la licence du projet, les mailing lists, etc. Mais ce site contient également des rapports plus techniques, comme Checkstyle, Cobertura, PMD, le rapport des tests unitaires, la Javadocs, etc. Toutefois, d'autres rapports peuvent être générés en les ajoutant dans le pom.xml dans la section <reporting/>.

Pour de plus amples détails sur la génération de site par Maven, je vous renvoie vers le tutoriel de Baptiste Wicht traitant de ce sujet. Vous pouvez également visualiser un exemple d'un site généré ici.

V-B - Avantages

- Utilisation des conventions Maven, permettant de raccourcir le pom.xml.

- La gestion des dépendances, en particulier les dépendances transitives.

- L'héritage de projets.

- De nombreux plugins sont aujourd'hui disponibles.

- Possibilité de réaliser de nombreuses tâches avec un pom.xml simple (compilation, packaging, site, rapports).

- Supporté par la majorité des outils d'Intégration Continue.

- Relative facilité de création de nouveaux plugins.

- Les archetypes, assez nombreux, facilitant la création de nouveaux projets.

- Il existe plusieurs gestionnaires de repositories locaux, les plus utilisés étant Nexus, Archiva et Artifactory.

V-C - Inconvénients

- Dès que l'on veut sortir un peu du système Maven 2, que l'on veut faire des choses en dehors du cadre de l'outil, ça devient vite complexe.

- Le pom.xml est trop verbeux, par exemple pour la définition dépendances.

- Trop grande utilisation de plugins, y compris pour réaliser certaines tâches simples.

- Documentation « officielle » peu fournie et assez fouillis. Heureusement, plusieurs ouvrages complets (et pour certains gratuits) existent !

- XML parfois redondant, même en utilisant l'héritage.

- Support pas encore parfait dans les IDE, bien que les choses s'améliorent.

- Développement et support des plugins « officiels » inégaux.

- Manque de souplesse, de rigueur sur certains principes (difficile de sortir du cycle de vie par exemple).

V-D - Références

- Site officiel de Maven2

- Forum developpez.com sur Maven2

- FAQ Maven2 (developpez.com)

- Utiliser Maven2 (tutoriel developpez.com)

- Introduction à Maven2 (developpez.com)

- MvnRepository, un moteur de recherche d'artefact Maven 2.

- Maven: The Definitive guide.

- Traduction française du livre « Maven: The Definitive Guide »

- Apache Maven, en français, par Arnaud Héritier et Nicolas de Loof.

V-E - Un mot sur Maven 3

Maven 3, qui sortira en 2010, est une réécriture complète de l'outil, visant à améliorer la plupart des points négatifs de son prédécesseur. Un effort particulier est apporté au nettoyage du code, ainsi que des points d'extension, de façon à impliquer plus encore la communauté autour de cet outil. L'un des autres grands attraits de Maven 3 sera le support d'autres langages que le XML : le Ruby, le Groovy ou encore le YAML. Ainsi, les POM devraient être plus faciles à écrire, à lire et donc à maintenir. Voici un exemple de pom yamlisé :

groupId: org.twdata.maven
artifactId: maven-yamlpom-plugin
version: 1.0-SNAPSHOT
packaging: maven-plugin
name: YAML POM Plugin
dependencies:
- { groupId: org.apache.maven, artifactId: maven-plugin-api, version: 2.0 }
- { groupId: SnakeYAML, artifactId: SnakeYAML, version: 1.1 }
- { groupId: commons-io, artifactId: commons-io, version: 1.4 }
- { groupId: dom4j, artifactId: dom4j, version: 1.4 }
- { groupId: junit, artifactId: junit, version: 3.8.1, scope: test }
- { groupId: xmlunit, artifactId: xmlunit, version: 1.2, scope: test }
build:
plugins:
- artifactId: maven-compiler-plugin
configuration:
source: 1.5
target: 1.5
repositories:
- id: snakeyaml
name: SnakeYAML repository
url: http://snakeyamlrepo.appspot.com/repository

Maven 3 est prévu pour 2010, bien qu'il soit déjà intégré dans certains IDE (en particulier NetBeans).

VI - Gradle

VI-A - Présentation

VI-A-1 - L'architecture

Gradle est un outil plutôt récent (2008) proposant d'écrire ses scripts de build dans un langage de scripts Java : Groovy. Gradle est né de l'expertise acquise sur les principaux outils de build tels que Ant, Ivy et Maven. L'objectif de Gradle est de fournir un système de build complet à la Maven en proposant tous les avantages des outils de build existants sans les inconvénients. Afin de faciliter l'utilisation (et l'adoption) de Gradle, ce dernier permet d'utiliser bon nombre de ressources propres à Ant ou encore Maven 2, par exemple la gestion des build.xml, pom.xml, repositories, etc.

Grade se livre sous forme d'un produit tout en un, contenant le nécessaire pour mettre en place une chaîne de build sur son projet. L'architecture de Gradle se décompose comme suit :

En termes d'architecture, Gradle se compose de quatre couches principales :

- Une couche API composée :

- d'une partie core,

- d'une partie UI pour l'utilisation de Gradle en interface graphique,

- d'une partie Wrapper pour l'utilisation de Gradle sans requérir initialement son installation,

- d'une partie open-API pour l'utilisation de Gradle par un système externe (type Intégration Continue par exemple),

- et d'une partie documentation ;

- une couche plugins comportant tous les plugins de Gradle. Contrairement a Maven, Gradle utilise peu de plugins, mais cela est suffisant pour son fonctionnement : des plugins de build comme le plugin java pour la construction d'une librairie Java, un plugin war pour le build d'une application Web ou des plugins de reporting et de qualité de code ;

- une couche outil de build comportant une distribution Ant, Ivy, Groovy et les tâches Ant. Installer Gradle, c'est pouvoir utiliser et réutiliser des infrastructures Ant / Ivy et Maven sans avoir besoin d'installer ces outils respectifs ;

- une couche pour la qualimétrie du code source comportant des librairies comme Checkstyle et codeNarc (qui est l'équivalent de Checkstyle pour les applications Groovy).

On constate en particulier que tous les plugins Gradle sont déjà inclus dans la distribution. Ainsi, de par son architecture, Gradle est à l'image de Ant et Ivy, et ne requiert ainsi aucune dépendance vers l'extérieur pour construire une simple librairie Java de type HelloWorld. Cet aspect-là est très utile dans certaines organisations de type militaire où l'accès à Internet ou à un réseau externe est limité, voire inexistant.

VI-A-2 - Principes

Gradle prend la même direction que Maven en proposant de décrire le projet à construire à travers son descripteur de build, le fichier build.gradle. Écrit en Groovy, ce fichier décrit les éléments suivants :

- l'endroit où se situent le code source et les fichiers de ressources ;

- la version de Java utilisée pour compiler le code source ;

- les dépendances directes du projet ;

- les plugins utilisés ;

- les rapports techniques demandés ;

- etc.

Comme pour Maven, Gradle propose le pattern Convention over Configuration en s'appuyant sur les mêmes conventions que Maven :

- convention de la structure du projet (i.e. les répertoires) ;

- convention de noms ;

- mise à disposition d'un cycle de vie complet.

Ci-dessous, nous voyons un exemple de build Gradle pour un projet Java :

usePlugin 'java'

usePlugin 'eclipse'

sourceCompatibility = 1.5
version = '1.0'
manifest.mainAttributes(
'Implementation-Title': 'Gradle Quickstart',
'Implementation-Version': version
)

repositories {
mavenCentral()
}

dependencies {
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
testCompile group: 'junit', name: 'junit', version: '4.+'
}

test {
options.systemProperties['property'] = 'value'
}

uploadArchives {
repositories {
flatDir(dirs: file('repos'))
}
}

Avec ce simple fichier, il devient possible de réaliser tout le processus de construction d'un projet à savoir :

- gérer les fichiers de ressources ;

- compiler les sources Java ;

- compiler et exécuter les tests unitaires ;

- créer le fichier JAR du projet ;

- déployer le JAR.

VI-A-3 - Notion de tâches

Un script de build est défini par un ensemble de tâches. Avec Ant, il existait un ensemble de cibles (target) délégant le travail de construction à des tâches (les nœuds XML contenus dans ces targets). Pour Gradle, ces deux notions se recoupent, sous la forme de tâches. À chaque tâche sont ajoutées des actions sous forme de closures Groovy.

task distribution  << {
println "Distribution"
}

task release (dependsOn: 'distribution') << {
println "Release"
}

Plus précisément, les tâches Gradle peuvent être de deux types : simple ou enrichie via une API :

task mycopy (type:Copy) {
description = 'Copies the resources dir'
from(file('resources'))
into(file('target'))
include('**/*.txt', '**/*.xml')
}

ou :

task distrib(type:Zip){
dependsOn(jar)
baseName = 'dist'
from sourceSets.main.java
from jar.archivePath
}

Dans ce dernier cas, une tâche Gradle est une instance d'une classe appartenant à une hiérarchie de classes. Chaque tâche est extrêmement riche, et expose un ensemble de propriétés très facilement configurable.

VI-A-4 - Gestion des dépendances

Grâce à Ivy qui nous ouvre aux deux mondes (Maven et Ivy), Gradle est capable de récupérer les dépendances dans des repositories Maven ou ceux d'Ivy. Mais Gradle offre également la possibilité de pouvoir récupérer des librairies au sein d'un système de fichiers, ou même dans un gestionnaire de configuration logicielle tel que Subversion, et le tout sans avoir à stocker des métadonnées. C'est la notion de client modules. C'est en réalité au niveau du script build.gradle que seront directement définies les dépendances et la hiérarchie de dépendances à récupérer transitivement.

Gradle peut récupérer des dépendances dans un repository. Mais il peut également publier des artefacts dans des repositories distants. Plus précisément, Gradle est capable de publier les artefacts qu'il construit avec des métadonnées Ivy dans des repositories Ivy. De plus, Gradle est capable de publier des artefacts qu'il produit dans des repositories Maven avec des métadonnées Maven. À noter que la gestion du déploiement des snapshots est gérée parfaitement, contrairement à une solution classique Ant / Ivy qui ne sait pas gérer ce type d'artefacts.

VI-B - Avantages

- Livré tout en un.

- Peut réutiliser et compléter une infrastructure basée sur Ant, Ivy ou Maven 2.

- Basé sur Groovy, on peut tout faire avec plus ou moins de facilité.

- Très peu verbeux.

- Gère les cycles complets de création de projets.

- Projet assez vivant.

- Modèle de description très riche et extensible.

- Est compatible avec les nouvelles normes Java et JavaEE 6 (en raison de sa jeunesse, par défaut, c'est-à-dire sans configuration supplémentaire, Gradle considère que le code est en Java 5 et que par exemple le descripteur web.xml d'une application Web est optionnel dans src/main/webapp, ce qui est une fonctionnalité de JavaEE6).

- Simplicité de modification du cycle de vie d'un projet pour ajouter ou supprimer des étapes de construction, ou encore en insérer de nouvelles.

- Enrichit la portée des dépendances Maven en proposant les scopes providedCompile et providedRuntime.

VI-C - Inconvénients

- Outil encore jeune.

- Quid de son adoption et de sa pérennité ?

- Support encore faible dans les IDE et les outils d'Intégration Continue.

- Résistera-t-il à l'arrivée de Maven 3 ?

- Manque encore de maturité, par exemple le changement régulier de la DSL (Domain Specific Language) des scripts Gradle entre deux versions sans compatibilité ascendante, ce qui nécessite une migration manuelle de ces scripts de build lors d'une mise à jour de la version du builder.

VI-D - Références

- Site officiel de Gradle

- Roadmap de Gradle

- FAQ de Gradle

- User Guide (version 0.8).

- La bataille des builders, présentation lors du Normandy JUG.

VII - Quelques autres outils

Nous venons de passer en revue les principaux outils de builds du monde Java. Cependant, il existe quelques autres outils, plus confidentiels toutefois. En voici une liste non exhaustive.

- EasyAnt se base sur le couple Ant / Ivy, auquel il ajoute un certain nombre de scripts permettant de faciliter certaines tâches « classiques », comme la construction d'un WAR, d'une librairie JAR, etc. À cela, il ajoute également des conventions, bien qu'il n'impose aucun cadre rigide aux utilisateurs. Enfin, il reste compatible avec les scripts Ant « traditionnels », de façon à limiter son coût d'adoption.

- GAnt, ou comment faire du Ant, mais en Groovy ! Cet outil est avant tout une façade du Groovy AntBuilder, et ne propose pas de gestion avancée des dépendances, de cycle de vie complet, ou encore de support multimodule, contrairement à Gradle.

- Buildr, d'Apache permettant de construire des projets Java, Groovy ou Scala.

- Simple Build Tool, mais essentiellement destiné à la construction de projets écrits en Scala.

- Quokka

- Kundo

- SCons

VIII - Matrices

VIII-A - Généralités

Ant

Ivy

Maven2

Gradle

Éditeur

Apache

Apache

Apache

Gradle Inc.

Site

site

site

site

site

Téléchargement

téléchargement

téléchargement

téléchargement

téléchargement

Documentation

documentation

documentation

documentation

documentation

Version

1.7.1

2.1.0

2.2.1

0.8

Date de sortie

27 juin 2008

8 octobre 2009

11 août 2009

28 septembre 2009

Existe depuis

2000

2007

2003 (Maven 1) ; 2005 (Maven 2)

2008

Type de licence

Apache Software Licence 2.0

Apache Software Licence 2.0

Apache Software Licence 2.0

Apache Software Licence 2.0

VIII-B - Intégration dans les IDE

Il est important de connaître la façon dont s'intègre l'outil de build au sein de son propre IDE. Dans le tableau ci-dessous, nous faisons un rapide bilan de l'existant, pour les principaux éditeurs Java, à savoir Eclipse, NetBeans et IntelliJ.

IDE

Ant

Ivy

Maven 2

Gradle

Eclipse

(plugin)

(m2eclipse)

*

NetBeans

(module)

**

JetBrains IntelliJ

(plugin)

***

* Un plugin pour Groovy existe sur Eclipse, mais sa compatibilité avec Gradle n'est pas vérifiée. À noter également l'apparition d'un autre plugin, encore très jeune, mais dont l'initiative doit être saluée.
** NetBeans ne supporte pas nativement Gradle, toutefois il est possible de le configurer pour lancer des commandes pour cet outil.
*** IntelliJ offre déjà un plugin Groovy (JetGroovy). Toutefois, IntelliJ 9 intégrera un support natif à Gradle.

VIII-C - Utilisation dans l'Intégration Continue

L'Intégration Continue est le nom donné initialement par la communauté de l'Extreme Programming (« XP ») pour désigner la pratique de génie logiciel visant à accélérer la livraison des logiciels en réduisant le temps d'intégration. D'un point de vue technique, il s'agit d'un serveur connecté au gestionnaire de sources du projet, et qui va aller vérifier périodiquement la modification du code source, et dans le cas échéant, recompilera le projet.

Le schéma ci-dessous montre une architecture classique où est mise en place l'Intégration Continue :

On y distingue les éléments principaux de cette architecture.

- Le gestionnaire de sources (CVS, Subversion, Git, etc.) qui permet de stocker et de partager les sources du projet.

- Les développeurs, qui collaborent au projet en commitant leur travail sur le gestionnaire de sources.

- Le serveur d'Intégration Continue, qui va périodiquement vérifier le gestionnaire de sources à la recherche de modifications du code source.

Lorsque le serveur d'Intégration Continue détecte une modification du code source, ce dernier va lancer la recompilation - et l'exécution des tests unitaires - du projet.

Il est important que l'outil de build du projet soit bien géré par les outils d'Intégration Continue existants. La matrice suivante montre le support des outils de build par les principaux serveurs d'Intégration Continue.

Outils d'I.C.

script

Ant

Ivy

Maven 1

Maven 2

Gradle

Hudson

(plugin)

(plugin)

Apache Continuum

*

**

Cruise Control

*

**

JetBrains TeamCity

*

**

Atlassian Bamboo

*

**

* Étant donné qu'Ivy vient se greffer sur Ant, par définition, les outils gérant Ant gèrent aussi Ivy. Toutefois, certains outils proposent, éventuellement par l'ajout d'un plugin, d'un support avancé d'Ivy.
** Gradle n'est pas encore officiellement supporté par la plupart des serveurs d'Intégration Continue. Il existe cependant différentes parades pour construire un projet en utilisant Gradle : plugin, script lançant la commande Gradle, etc.

Retrouvez ici une matrice très complète sur toutes les fonctionnalités supportées par pratiquement tous les serveurs d'Intégration Continue existants.

IX - Conclusion

Choisir un outil de build n'est pas quelque chose à prendre à la légère. La construction d'un projet doit être rapide, fiable et reproductible. Toutefois, elle doit également s'intégrer parfaitement dans le processus de développement, et donc être supportée par les outils utilisés par l'équipe, en particulier l'IDE.

Aujourd'hui, Ant conserve une bonne réputation et reste le choix de beaucoup d'équipes, qui reprochent à Maven d'être trop rigide et complexe.

De son côté, Maven industrialise la construction d'un projet d'une façon appréciable, et permet de disposer simplement de nombreuses fonctionnalités, comme un processus complet de construction de projets, la génération de rapports et de site web, etc. Maven 3 réussira-t-il le pari de réconcilier les développeurs fâchés avec la version 2, tout en conservant ses adeptes actuels ?

Quant à Gradle, c'est grâce à sa jeunesse et à la richesse de Maven qui en fait un outil extrêmement intéressant en terme de services rendus. Pour bénéficier de tous les avantages et de la puissance de Gradle, il faut le voir non pas comme un système de build alternatif aux principaux systèmes de build actuels comme Ant / Ivy ou Maven, mais plutôt comme un complément.

Concernant les autres solutions de build, elles restent encore peu utilisées, mais certaines proposent tout de même des idées intéressantes.

Notons enfin que lors de la conférence CitConf Paris 2009 (lire mon compte-rendu), un sondage sur l'utilisation des outils de build avait été lancé. En voici les résultats en image :

On y voit sans surprise que Ant et Maven restent les deux solutions de build les plus couramment utilisées (2/3 des votes), mais que Gradle pourrait prendre de l'importance à l'avenir…

X - Remerciements

Un grand merci à Grégory Boissinot pour ses excellents retours, et en particulier pour la rédaction du chapitre sur Gradle.
Je tiens également à remercier ellene pour sa relecture attentive.