= Ant versus Make = === (Jean-Noël Albert / Avril 2005 / Groupe de développeurs du LAL) === == présentation == Make et Ant sont tous deux des systèmes pour la construction d'application. Make : * est un standard UNIX * est orienté “tâche à accomplir” tandis que Ant : * vise la portabilité * est orienté “enchaînement de taches” * est extensible * est écrit en Java et donc très bien adapté aux développements Java == Make == ''c'est l'histoire d'un make…'' Make est devenu un standard au même titre que UNIX * il existe une implémentation de Make par variante de UNIX, globalement similaires, mais assez différentes dans les détails pour rendre difficile les portages ; * plus une variante GNU : GNU Make ou GMake * la plus riche en extensions ; * la plus utilisée par les développeurs ; * adoptée par Linux. == L'approche Make == === Principe : on décrit le but à atteindre, et non pas la façon d'y parvenir. === Exemple : pour construire le programme ''hello'' à partir du source ''hello.c'', il suffit de lancer la commande : % '''make hello''' Make procède automatiquement à la recherche des fichiers qui lui permettent d'atteindre le but demandé (la construction de ''hello''). Il trouve un fichier ''hello.c''. Il dispose d'une règle interne lui permettant de passer d'un fichier C à une application. Il lance la compilation et l'édition de liens C. Résultat : {{{ cc hello.c -o hello }}} Et le programme hello est construit. Ca marcherait aussi avec un fichier source en Fortran, en C++ etc. Si on relance la même commande : % '''make hello''' {{{ make: `hello' is up to date. }}} Il n'y a rien à faire, puisque l'application hello vient d'être compilée et que la source 'hello.c'' n'a pas changé. Si on modifie le fichier source : % '''touch hello.c''' % '''make hello''' {{{ cc hello.c -o hello }}} Make détecte que le fichier source est plus récent que l'application compilée et la reconstruit. Make se base sur la date des fichiers pour savoir quels fichiers reconstruire. Si l'application dépend de plusieurs sources, Make ne reconstruit que ce qui a changé. Il s'ensuit un _gain de temps_ (surtout avec C++ qui est long à compiler) ; et l'application est toujours en phase avec les développements. == Makefile == Pour des applications plus compliquées, on utilise un fichier de description nommé '''Makefile''' (''makefile'' est également accepté – et selon la mouture de Make, d'autres fichiers sont reconnus et traités ; par exemple GMake utilise de préférence le fichier GNUmakefile, si celui-ci existe dans le répertoire). Le fichier de description contient une liste de “buts à atteindre” (appelés le plus souvent “cible”) et les moyens d'y parvenir. Lorsqu'un fichier Makefile existe dans le répertoire, Make le lit et exécute le premier “objectif”. Pour exécuter un autre objectif, on l'indique sur la ligne de commandes de Make. Exemple d'un fichier Makefile simple : {{{ hello : hello.c # Supprime les fichiers compilés et les sauvegardes XEmacs clean : rm hello hello.o *~ }}} Pour construire l'application : % '''make''' {{{ cc -c -o hello.o hello.c cc hello.o -o hello }}} Make exécute le premier objectif du fichier (hello). Un but peut dépendre d'étapes intermédiaires (par exemple pour la construction de librairies). Exemple très simplifié : {{{ hello : hello.o hello.o : hello.c }}} Un but peut ne correspondre à aucun fichier, comme "clean" dans l'exemple précédent. Dans ce cas, il sera toujours accompli. Exemple : suppression des fichiers compilés : % '''make clean''' {{{ rm hello hello.o *~ }}} == Principaux inconvénients == * Lorsque les Makefiles deviennent compliqués, on ne sait pas toujours très bien quel va être le cheminement de Make, ni s'il va exécuter les étapes prévues, et dans quel ordre. * Pas très bien adapté à des projets comportant plusieurs répertoires – il faut souvent un fichier Makefile par répertoire, plus un fichier Makefile général pour reconstruire l'application pour chacun des répertoires. * Il faut souvent imposer à Make les opérations à réaliser, en fonction des saveurs de UNIX : options de compilations différentes d'une variante à l'autre, commandes différentes d'une plate-forme à l'autre, … * portage difficile - principales difficultés : les options de CC ; * GMake introduit des blocs if … else … pour tenir compte des plates-formes * ne simplifie pas la compréhension des fichiers Makefile ; * nécessite d'installer GMake (on peut aller le chercher sur le site GNU). * Portage difficile vers Windows (80-90 % des postes de travail) * principale difficulté : les noms de fichiers Windows sont incompatibles avec les noms de fichiers UNIX Exemple : * UNIX : /usr/bin/cc * Windows : C:\Windows\system32\cc.exe * une possibilité : '''Cygwin''' (portage des commandes UNIX sous Windows) - représente les fichiers Windows avec la syntaxe UNIX - utilise GMake * Exemple : /c/Windows/system32/cc.exe (le ".exe" est alors optionnel) * problème : les applications natives de Windows (comme par exemple Java) ne reconnaissent pas les noms UNIX. == Ant == La construction de l'application se fait en indiquant une succession d'opérations à réaliser. Ant utilise un fichier '''build.xml'''. Une tâche peut dépendre d'une ou de plusieurs autres tâches. L'exécution d'une tâche peut dépendre de conditions, par exemple pour ne pas construire une partie du code qui dépend d'une librairie qui n'est pas installée (exemple : un interface d'accès au HPSS du CC IN2P3). Tout comme Make, Ant ne traite que les fichiers plus récents que les résultats à obtenir. Ant assure qu'une tache ne sera accomplie qu'une seule fois dans le processus de construction : * ceci évite des situations de bouclage apparaissant avec Make lorsqu'une cible intermédiaire est en prémisse de plusieurs autres cibles * cas typiques : génération de fichiers à partir de sources qui ne sont pas des fichiers (base de données, …) Plutôt que de laisser l'utilisateur indiquer les commandes à exécuter (rm, cc, …), Ant fournit un ensemble de taches permettant de réaliser les opérations escomptées : * compiler les fichiers sources * construire une librairie * construire la documentation * créer des répertoires * supprimer des fichiers de travail * … Ant intègre la notion d'opérations récursives sur un ensemble de fichiers et de répertoires. Il vise la portabilité et tente de masquer les opérations sur les fichiers. Il est bien adapté à Java. == Java, Make & Ant == Les projets Java sont naturellement organisés en packages, et les fichiers sources doivent être placés dans une hiérarchie de répertoires reproduisant la hiérarchie des packages. Le processus de compilation doit donc parcourir tous les répertoires - l'ordre n'est pas très important grâce au mécanisme de compilation incrémental de Java. Make ne pas très bien adapté à cette situation; il y aurait deux possibilités : tout recompiler à chaque fois (lourd) ou lancer Make sur chacun des répertoires (peu pratique). Mêmes difficultés pour construire la documentation (JavaDoc) : il faut passer en revue tous les répertoires. Ant permet de résoudre la plupart de ces difficultés en trois taches : {{{ }}} L'exemple complet : {{{ }}} La construction de l'application : % '''ant''' {{{ Buildfile: build.xml build: [javac] Compiling 1 source file to /albert/Test/classes [jar] Building jar: /albert/Test/lib/hello.jar BUILD SUCCESSFUL Total time: 3 seconds }}} L'élimination des fichiers intermédiaires (par exemple, après l'installation du projet) % ant '''clean''' {{{ Buildfile: build.xml clean: [delete] Deleting 2 files from /albert/Test BUILD SUCCESSFUL Total time: 1 second }}} == Portabilité == Ant est écrit en Java, donc portable. Exemple : exécution du même script Ant sous Windows/XP et Cygwin : $ '''ant doc''' {{{ Buildfile: build.xml build: [javac] Compiling 1 source file to D:\Projets\test\classes [jar] Building jar: D:\Projets\test\lib\hello.jar doc: [javadoc] Generating Javadoc [javadoc] Javadoc execution [javadoc] Loading source files for package demo... [javadoc] Constructing Javadoc information... [javadoc] Standard Doclet version 1.5.0_01 [javadoc] Building tree for all the packages and classes... [javadoc] Building index for all the packages and classes... [javadoc] Building index for all classes... BUILD SUCCESSFUL Total time: 9 seconds }}} Bien qu'on soit dans une émulation de l'environnement UNIX, les fichiers sont indiqués à Java en utilisant la notation native (le Java de Windows ne reconnaît pas la notation UNIX des fichiers…). Autre exemple sous le shell Windows natif : D:\Projets\test> '''PATH D:\externals\Ant\apache-ant-1.6.2\bin;%PATH%''' D:\Projets\test> '''ant doc''' {{{ Buildfile: build.xml build: [javac] Compiling 1 source file to D:\Projets\test\classes [jar] Building jar: D:\Projets\test\lib\hello.jar [javadoc] Generating Javadoc [javadoc] Javadoc execution [javadoc] Loading source files for package demo... [javadoc] Constructing Javadoc information... [javadoc] Standard Doclet version 1.5.0_01 [javadoc] Building tree for all the packages and classes... [javadoc] Building index for all the packages and classes... [javadoc] Building index for all classes... BUILD SUCCESSFUL Total time: 4 seconds }}} == Extension == On peut ajouter des tâches en fournissant une archive Jar contenant les classes exécutant les nouvelles opérations et en définissant cette librairie dans le fichier '''build.xml'''. Il n'y a pas de reconstruction de Ant : le chargement des librairies Java est dynamique (-> à l'exécution). Cet aspect est utilisé par exemple pour le support de C++ et de Doxygen. Un exemple de fichier build.xml utilisant l'extension C++ : {{{ }}} Exemple Linux : % '''ant''' {{{ Buildfile: build.xml build: [cc] 1 total files to be compiled. [cc] Starting link BUILD SUCCESSFUL Total time: 2 seconds }}} % '''./demo.exe''' {{{ Hello, world ! }}} Sous Windows, on peut utiliser Cygwin pour avoir un compilateur C++. Le mécanisme pour écrire des tâches Ant est détaillé dans _Writing Your Own Task_. == Intégration == Ant est accepté par de nombreux IDE (''Integrated Development Environment'') : Eclipse, JBuilder, !VisualAge for Java, !WebSphere Studio. == Liens == * Ant : http://ant.apache.org/ * Documentation Ant : http://ant.apache.org/manual/index.html * C++ / Ant : http://sourceforge.net/projects/ant-contrib/ Note : il faut prendre aussi la distribution cpptasks * Doxygen / Ant : http://www.sourceforge.net/projects/ant-doxygen * Cygwin : http://cygwin.com/ * GNU : http://www.gnu.org/