Intéressé par des cours d'informatique en ligne ?
Visitez mon nouveau site
https://www.yesik.it !
Dans ce tutoriel, nous allons voir comment construire une application Java avec Ant.
Objectifs | A la fin de ce tutoriel, vous saurez:
|
---|---|
Prérequis |
|
Moyens |
Sommaire
Le projet
Fichiers sources
L'application qui va servir de support à ce tutoriel est un programme de simulation de compte bancaire. Elle est composées de deux classes Banque et Compte.
La classe Compte est chargée de la gestion d'un compte. Et permet de créditer ou débiter celui-ci. elle est définie dans le fichier Compte.java dont voici le source:
package fr.esicom.exemples; /** * Un compte en banque */ public class Compte { private double solde; /** * Ouvre un compte. */ Compte() { solde = 0; } /** * Depose de l'argent sur le compte */ public void depose(double somme) { solde += somme; } /** * Retire de l'argent du compte. */ public double retire(double somme) { if (somme > solde) somme = solde; if (somme < 0) return 0; return solde -= somme; } /** * Affichage */ public String toString() { return "Le solde du compte est de " + solde; } };
La classe Banque ne contient que le programme principal. C'est un simple programme de démonstration qui instancie un Compte, le crédite, puis le débite et enfin affiche le solde. Cette classe est définie dans le fichier Banque.java
package fr.esicom.exemples; public class Banque { public static void main(String argv[]) { Compte compte = new Compte(); compte.depose(3000); compte.retire(1200); System.out.println(compte.toString()); } };
Organisation du projet
Notre projet va être créé dans le répertoire ProjetBanque. Celui-ci contient deux sous répertoires:
- src pour les sources (les fichiers .java)
- build pour les fichiers compilés (les fichiers .class).
Pour l'instant, le répertoire build est vide. Le répertoire src contient lui une hiérarchie de sous-répertoires qui reprennent les parties du nom de package fr.esicom.exemples. Les fichiers sources sont placés dans le dernier sous-répertoire.
Il est impératif de respecter cette hiérarchie pour que Ant puisse fonctionner correctement.
Compiler le projet
Le fichier build.xml
Pour fonctionner, Ant a besoin d'un fichier build.xml qui définit les différentes cibles et les tâches à effectuer. Notre fichier build.xml sera situé à la racine du projet.
Pour l'instant, il contiendra le code suivant:
<?xml version="1.0" ?> <project name="ProjetBanque" default="compile"> <target name="compile"> <javac srcdir="src" destdir="build" /> </target> </project>
Ce fichier définit une cible appelée compile. Dans cette cible, on trouve une tâche javac.
Cette tâche a pour but de compiler des fichiers .java. Elle va chercher dans le répertoire indiqué par l'attribut srcdir (et tous ses sous-répertoires) les fichiers sources pour les compiler. Les fichiers compilés sont stockés dans le répertoire indiqué par l'attribut destdir.
La tâche javac ne compile que les fichiers dont le .class est absent du répertoire destdir ou ceux qui sont plus récents que ceux présents dans le répertoire destdir.
Compiler
Pour voir javac en action, ouvrez un terminal et tapez:
sh$ cd ProjetBanque sh$ ant
Si tout s'est bien passé, vous devriez obtenir l'affichage suivant:
Buildfile: build.xml compile: [javac] Compiling 2 source files to /Users/sylvain/ProjetBanque/build BUILD SUCCESSFUL Total time: 4 seconds
Tester
Pour tester le programme, il vous faut aller dans le sous-répertoire build (puisque c'est là que sont enregistrés les fichiers compilés), puis invoquer java (en précisant bien le nom qualifié de votre classe -- c'est à dire sans oublier le nom de paquetage):
sh$ cd build sh$ java fr.esicom.exemples.Banque
Vous devriez avoir la joie de constater qu'il vous reste en banque:
Le solde du compte est de 1800.0
Que s'est-il passé?
Si l'on examine le contenu du répertoire build, on se rend compte que la tâche javac y a créé une hiérarchie similaire à celle du dossier src. Les fichiers Banque.class et Compte.class se trouvant dans le dernier sous-répertoire.
En fait, pour être plus précis, la tâche javac a créé tout une arborescence à partir de build qui reflète le nom du package auquel appartiennent les classes:
- build
- fr
- esicom
- exemples
- Banque.class
- Compte.class
- exemples
- esicom
- fr
Ne recompiler que ce qui est nécessaire
Tout l'intérêt d'utiliser ant plutôt qu'un simple script shell, c'est qu'il ne va recompiler que ce qui est nécessaire.
Nous allons illustrer ici le fait que la tâche javac ne recompile que les sources dont la version compilée est absente ou ceux qui sont plus récent que leur version compilée.
.class absent
Nous allons supprimer un des deux fichiers compilés, puis relancer ant. Dans un terminal, à partir du répertoire ProjetBanque:
sh$ rm build/fr/esicom/exemples/Banque.class sh$ ant
Buildfile: build.xml compile: [javac] Compiling 1 source file to /Users/sylvain/ProjetBanque/build BUILD SUCCESSFUL Total time: 4 seconds
Notez que la tâche javac indique qu'elle ne compile qu'un seul fichier cette fois ci.
.java plus récent que le .class
Maintenant voyons ce qui se passe quand on modifie un fichier .java.
Plutôt que de modifier vraiment le fichier, nous allons nous servir de la commande touch qui permet de changer la date de dernière modification d'un fichier. Ce sera suffisant pour abuser ant:
sh$ touch src/fr/esicom/exemples/Compte.java sh$ ant
Vous devriez obtenir le résultat suivant:
Buildfile: build.xml compile: [javac] Compiling 1 source file to /Users/sylvain/ProjetBanque/build BUILD SUCCESSFUL Total time: 3 seconds
Ici encore, un seul fichier recompilé: celui qui a été modifié.
Et si rien n'a changé
Si les fichiers .class sont présents, et si les fichiers .java n'ont pas été modifiés depuis la dernière compilation, la tâche javac ne fait rien:
sh$ ant
Buildfile: build.xml compile: BUILD SUCCESSFUL Total time: 1 seconds
Quelques cibles de plus
la cible clean
Que ce soit pour archiver ou pour diffuser son code, il n'est pas nécessaire de conserver les versions compilées des fichiers. Seuls les sources sont intéressants et de toute façon, il est toujours possible de recompiler l'application.
Généralement les buildfiles ant contiennent toujours une cible spécifique pour faire le ménage. traditionnellement cette cible s'appelle clean.
Dans notre cas, faire le ménage revient simplement à supprimer le répertoire build.
Nous allons donc ajouter la cible suivante au fichier build.xml:
<target name="clean" description="Fait le ménage"> <delete dir="build" /> </target>
Empressons nous de tester:
sh$ ant clean
Buildfile: build.xml clean: [delete] Deleting directory /Users/sylvain/ProjetBanque/build BUILD SUCCESSFUL Total time: 1 second
Vous pourrez facilement vérifier que le répertoire build a été supprimé.
la cible init
Après avoir fait le ménage à l'étape précédente, on peut essayer de reconstruire l'application:
sh$ ant
Buildfile: build.xml compile: BUILD FAILED /Users/sylvain/ProjetBanque/build.xml:4: destination directory "/Users/sylvain/ProjetBanque/build" does not exist or is not a directory Total time: 1 second
Malheureusement, il y a une erreur: Ant nous signale qu'il ne peut pas construire la cible compile car le répertoire ProjetBanque/build n'existe pas. Effectivement, nous l'avons supprimé avec la cible clean.
Nous allons donc ajouter à notre build.xml la cible init spécialement pour créer ce répertoire. Et nous allons dire que la cible compile dépend de init. Voici le code complet de build.xml:
<?xml version="1.0" ?> <project name="ProjetBanque" default="compile"> <target name="init"> <mkdir dir="build" /> </target> <target name="compile" depends="init"> <javac srcdir="src" destdir="build" /> </target> <target name="clean" description="Fait le menage"> <delete dir="build" /> </target> </project>
Exécuter la commande ant produit maintenant le résultat:
Buildfile: build.xml init: [mkdir] Created dir: /Users/sylvain/ProjetBanque/build compile: [javac] Compiling 2 source files to /Users/sylvain/ProjetBanque/build BUILD SUCCESSFUL Total time: 4 seconds
Le répertoire build est d'abord créé, puis l'application est compilée avec succès.
Keep it DRY
Si l'on examine la dernière version de notre fichier build.xml, on se rend compte que l'information qui précise le nom de notre répertoire build est répété dans chacune des trois cibles. En vertue du DRY principle, nous allons essayer d'éviter cette redondance.
Pour ce faire, Ant nous propose un outil sous la forme des propriétés. Nous allons donc créer une propriété qui mémorise le nom du dossier qui sert à enregistrer les fichiers compilés. Et dans un soucis d'uniformité, nous allons également créer une propriété pour le nom du dossier source.
Le code complet devient:
<?xml version="1.0" ?> <project name="ProjetBanque" default="compile"> <property name="build.dir" value="build" /> <property name="src.dir" value="src" /> <target name="init"> <mkdir dir="${build.dir}" /> </target> <target name="compile" depends="init"> <javac srcdir="${src.dir}" destdir="${build.dir}" /> </target> <target name="clean" description="Fait le menage"> <delete dir="${build.dir}" /> </target> </project>
Maintenant, il n'y a que dans les deux éléments property que sont codés "en dur" les noms de nos répertoires src et build. Ce seront donc les seules lignes à changer si ces répertoires changent.