Gradle

Introduction

La tâche de compilation (le terme de ‘build’ sera parfois employé par la suite) fait partie intégrante de nos cycles de développement, celle ci est d’ailleurs souvent redouté et source de frustration (ça compile chez toi?). De nombreux outils – tel que Ant et Maven pour ne citer qu’eux –  existent déjà pour structurer et automatiser cette étape afin de la rendre la plus efficace et transparente possible.

Gradle est un outil de build opensource qui utilise une approche fédératrice avec ses principaux concurrents. En effet, sans jouer la carte de la révolution, il essaye d’utiliser les avantages de chacun tout en permettant de s’intégrer facilement dans des infrastructures de build existantes. On pourrait dire qu’il intègre la puissance des tâches Ant avec celle du système de management de dépendance du très controversé Maven.

Avec l’arrivée tant attendu de sa version 1.0 il y a de ça quelques semaines, Gradle arrive définitivement à maturité. De nombreux projets open-source importants ne s’y sont pas trompés et l’ont déjà adopté comme par exemple Hibernate, Spring Integration, Spring Security, Grails et Groovy.

Présentation

Avec Gradle, fini les configurations verbeuses en XML, l’équipe de développement a fait le choix de proposer un langage de spécification de domaine (DSL) en Groovy pour écrire les scripts de build. Groovy est un langage de programmation s’exécutant sur la JVM, on peut donc développer des fonctions avancées à l’intérieur du script de build, chose impossible avec une simple description en XML. Vous l’aurez deviné, bien que cette fonctionnalité soit extrêmement puissante, il faudra la consommer avec modération si l’on ne veut pas transformer son build en usine à gaz.

La philosophie sous jacente est que Gradle est conçu pour être utilisé comme un langage et non comme un framework; là où Maven impose ses conventions de structure de projet, Gradle s’adapte à votre modèle.

Un aspect important est la capacité de Gradle à s’intégrer dans une infrastructure Ant/Maven existante. Du coté gestion des dépendances il est tout à fait possible de s’interfacer aussi bien avec des repositories Maven ou Ivy. Pour les utilisateurs de Maven fainéant, il est à noter qu’iI existe un outil Maven2Gradle permettant de générer un fichier build.gradle à partir d’un fichier pom.xml. Quand aux utilisateurs de Ant ils sont encore mieux lotis, car les tâches Ant peuvent être appelées nativement à l’intérieur du script de build Gradle.

Une tâche Gradle est par défaut un objet de type DefaultTask qui ne fait rien de particulier mais qui contient les méthodes permettant de s’interfacer avec le modèle de projet Gradle, comme la définition des dépendances entre tâches.

Gradle propose quelques tâches communes afin de nous faciliter la vie. Prenons l’exemple présent dans la documentation officiel de la réalisation d’une copie (type Copy) de fichier pour découvrir les différentes syntaxes possibles de déclaration.

Tout d’abord par manipulation de proprieté:

1
2
3
4
5
6
task myCopy(type: Copy)
myCopy {
from 'resources'
into 'target'
include('**/*.txt', '**/*.xml', '**/*.properties')
}

Par fluent interface:

1
2
3
4
task(myCopy, type: Copy)
.from('resources')
.into('target')
.include('**/*.txt', '**/*.xml', '**/*.properties')

Par l’appel à la méthode configure présent chez tout les tâches:

1
2
3
4
5
6
task myCopy(type: Copy)
myCopy.configure {
from('source')
into('target')
include('**/*.txt', '**/*.xml', '**/*.properties')
}

ou encore avec une closure groovy:

1
2
3
4
5
task myCopy(type: Copy) {
from 'resources'
into 'target'
include('**/*.txt', '**/*.xml', '**/*.properties')
}

Pour créer votre tâche personnelle faisant tout et surtout n’importe quoi, il vous suffira de créer une classe Groovy étendant DefaultTask. Il est donc temps de réaliser le tant attendu HelloWorld.

1
2
3
4
5
6
7
task hello(type: HelloWorldTask)
class HelloWorldTask extends DefaultTask {
@TaskAction
def action() {
println 'hello world from my custom task'
}
}

Comme vous l’aurez remarqué, la classe présente une méthode annotée @TaskAction, c’est celle ci qui sera appelé lors de l’exécution de la tâche. Ici la classe est écrite directement dans le script build.gradle mais il est bien entendu possible de placer toutes nos tâches dans un répertoire spécifique au projet.

Pour comprendre comment fonctionne Gradle, intéressons nous au cycle de vie d’un build. Au lancement, le système commence par initialiser le modèle du projet. Derrière l’appellation ‘modèle du projet’ réside simplement la représentation du build sous forme d’un objet avec des attributs portant les informations du build et des API pour le manipuler programatiquement. Original non?

Gradle supportant les build multi-projets, le script est d’abord analysé pour déterminer les projets intervenant afin d’instancier un modèle par projet. Puis chaque modèle va être configuré par l’ajout des actions à exécuter sous la forme d’un DAG (Directed Acyclic Graph) représentant le build, notion que l’on retrouve également chez Ant. On termine sans grande surprise par la phase d’exécution des tâches dans l’ordre définit par leur dépendances.

Pour plus d’information sur ce cycle de vie, n’hésitez pas a consulter la documentation officielle.

Système de Plugin

Lorsque le DSL standard de Gradle ne permet pas de réaliser la tâche de vos rêves, vous pouvez également l’étendre à l’aide de plugins. Un certain nombre de plugins incontournables sont d’ailleurs intégrés nativement à Gradle afin d’enrichir l’API de base comme :

  • la compilation Java, Groovy ou Scala
  • la génération de métadonnée Eclipse etc.
  • l’analyse statique PMD, intégration avec sonar

Retrouvez la liste des plugins ici. Ces plugins sont bien sur optionels et peuvent être utilisés simplement en les déclarant dans le script.

L’écosystème des plugins tiers est en pleine activité, une liste non exhaustive est disponible ici. Tout comme Maven on retrouve des plugins classiques utilisés lors de la création de web application mais aussi des choses plus exotique grâce à la communauté Github très active; comme des plugins pour la compilation de CoffeeScript, la compilation de LessCss, le packaging Android, la génération d’un WAR pour Google App Engine etc.

Un exemple pour la route

Après cette partie assez théorique, finissons par un peu de pratique. Commençons par l’installation de Gradle. Celle ci se déroule de manière similaire à celle de Maven, on enchaine donc rapidement par le téléchargement de l’archive ici, la décompression dans un répertoire, la mise en place d’une variable système GRADLE_HOME et enfin l’ajout au PATH de GRADLE_HOME/bin.

On peut ensuite vérifier que l’installation s’est bien déroulé par la commande ‘gradle -v’

1
2
3
4
5
6
7
8
9
------------------------------------------------------------
Gradle 1.0
------------------------------------------------------------
Gradle build time: mardi 12 juin 2012 00 h 56 UTC
Groovy: 1.8.6
Ant: Apache Ant(TM) version 1.8.2 compiled on December 20 2010
Ivy: 2.2.0
JVM: 1.6.0_25 (Sun Microsystems Inc. 20.0-b11)
OS: Windows 7 6.1 x86

Si vous suivez toujours, il suffira par la suite de se placer dans le répertoire du projet et d’invoquer ‘gradle build’.

Il est temps d’écrire notre premier script de build, attaquons directement la compilation d’un projet java dont le contenu nous importe peu.

1
2
3
4
5
6
7
8
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.1'
testCompile 'junit:junit:4.10'
}
  1.  application du plugin java spécifiant la nature de la compilation.
  2. utilisation du repositorie central de maven.
  3. déclaration des dépendances avec une super syntaxe légère.

En lançant le build dans le repertoire du projet nous pouvons observer dans la console les tâches invoquées issues du plugin java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
gradle build
:compileJava
:processResources
:classes
:jar
:assemble
:compileTestJava
:processTestResources
:testClasses
:test
:check
:build

BUILD SUCCESSFUL

 

Conclusion 

Les qualités de Gradle sont indéniables, en choisissant de fédérer les meilleurs idées de ses concurrents, tout en conservant une grande compatibilité avec ceux ci, Gradle se positionne comme une solution efficace de remplacement pour des builds problématiques sous Ant ou Maven.

Du coté des défauts on peut lui reprocher son manque d’intégration au sein des IDE. Il existe un plugin STS pour lancer les builds mais nous sommes encore loin d’un m2e.

Gradle est un outil très riche dont certains aspects tel que l’amélioration des performances par l’utilisation d’un build incrémental ou encore l’automatisation des tests n’ont pas été abordé dans cette article. J’espère néanmoins vous avoir donné envie d’aller plus loin en commençant par consulter la documentation officielle http://gradle.org/overview.

VN:R_U [1.9.22_1171]
Rating: +1 (from 1 vote)
Share
Ce contenu a été publié dans JVM, Outils, avec comme mot(s)-clef(s) , , . Vous pouvez le mettre en favoris avec ce permalien.

2 réponses à Gradle

  1. Cyril Brouillard dit :

    Le coté “gradle s’adapte à votre modèle” me semble un tantinet risqué… Le COC imposé Maven me semble être un avantage non repris …

    Quand au plugin Eclipse … et bien tant pis ! non ? vu la me$$$de qu’a été l’intégration Maven pendant quelques années, mieux vaut ne pas avoir de plugin plutôt que de faire n’importe quoi.

    VN:R_U [1.9.22_1171]
    Rating: 0 (from 0 votes)
    • Arnaud Gourlay dit :

      J’ai oublié d’en parler mais Gradle adopte également la philosophie de convention-over-configuration (COC).

      Les plugins sont pré-configurés pour reprendre “grosso modo” les conventions Maven par défaut.
      Prenons l’exemple du plugin Java qui par défaut cherche les sources dans ‘src/main/java’ et génère ces fichiers dans ‘build/classes/main’. Il est également possible de rédéfinir ces valeurs.

      1
      2
      apply plugin: 'java'
      compileJava.destinationDir = file("$buildDir/my/Output/Folder")

      Quand à ma conclusion sur l’intégration IDE, je comparais bien évidement le plugin Gradle STS à son homologue m2e quand il fonctionne correctement…si si ça arrive…parfois…

      VN:R_U [1.9.22_1171]
      Rating: 0 (from 0 votes)

Laisser un commentaire