Catégorie : Bureautique     Tags :      0 Commentaire

    Retrouvez cet article dans : Linux Magazine 84

    La gestion d’un petit document écrit en LaTeX est très simple : on fait les modifications nécessaires, on compile, et c’est prêt. Lorsque l’on rédige un document un tant soit peu important, les choses se corsent. On se retrouve avec une multitude de fichiers tex, des dizaines de fichiers images à convertir, un (ou plusieurs) fichier(s) de bibliographie, des listings à inclure... Réussir à prendre en compte tous ces fichiers, sans en oublier, et sans non plus passer sa vie à recompiler à la moindre modification devient vite ingérable... Les programmeurs, qui eux aussi doivent gérer des multitudes de fichiers, ont conçu un système pour automatiser tout ça : les Makefiles.

    Le makefile, exécuté par la commande make, décrit les dépendances entre les différents fichiers de votre projet LaTeX. Lorsque vous modifiez l’un des fichiers de votre projet, make se base sur ces dépendances et la date de leur dernière modification pour savoir quelles sont les étapes à effectuer pour obtenir un document à jour.
    Par exemple, si vous ne modifiez que votre fichier tex principal, une seule exécution de latex peut suffire. Pas besoin de régénérer les fichiers images ou la bibliographie !
    Le rôle de make peut sembler simpliste, mais nous allons voir qu’il permet d’automatiser de nombreuses choses, et d’éviter autant d’erreurs.

    Principe de fonctionnement

    Un makefile est un fichier texte nommé Makefile par convention. Ce fichier contient des règles définissant la méthode pour construire une cible à partir d’une ou plusieurs source(s). Ces règles ont la forme suivante :

    cible : source(s)
         action_a_faire

    cible et source sont séparés par deux points, et action_a_faire est indenté d’une tabulation.
    Attention ! Il s’agit bien d’une tabulation et non pas d’espaces (make n’accepte que la première). Certains éditeurs de texte effectuent une substitution malheureuse. Vérifiez que ce n’est pas votre cas. La règle la plus simple pour compiler un fichier LaTeX nommé document.tex sera donc :

     document.pdf : document.tex
        pdflatex document.tex

    Il suffit alors d’exécuter make dans le répertoire contenant les fichiers document.tex et Makefile pour obtenir le fichier document.pdf.
    Jusque là, on ne gagne pas grand-chose à passer par make plutôt qu’à appeler directement pdflatex document.tex. Cependant, si on exécute de nouveau make, on obtient directement le message suivant :

    make a détecté qu’il n’y avait pas besoin de refaire appel à pdflatex, puisque l’on n’a pas modifié le fichier source. Pour cela, il s’est basé sur les dates de modification des fichiers : si la cible est plus récente que la source, on ne fait rien. Dans le cas contraire, il faut recompiler !

    Makefile simple

    Premiers pas

    Maintenant que nous avons entrevu l’utilité d’un makefile, nous allons pouvoir passer à une étude de cas simple, mais réaliste.
    Imaginons un fichier LaTeX, dans lequel nous voulons inclure une courbe tracée par Gnuplot. Nous décidons arbitrairement d’utiliser pdflatex pour générer directement un document LaTeX, ce qui nous oblige à inclure des figures au format png, jpg ou pdf.
    Dans ce cas, la méthode la plus satisfaisante (puisqu’elle permet de conserver des figures au format vectoriel), c’est de générer une figure en eps, puis de la convertir en pdf avant de l’appeler dans le fichier tex.
    Pour résumer, nous allons donc suivre le cheminement décrit figure 1 :

    • Compilation du fichier Gnuplot sinus.plt pour produire le fichier sinus.eps ;
    • Conversion du format eps en pdf à l’aide de la commande epstopdf ;
    • Compilation du fichier LaTeX rapport.tex, qui fait appel à la figure sinus.pdf.

    Pour nos essais, nous utiliserons des documents Gnuplot et LaTeX simplistes, donnés dans l’encadré 1.
    Un makefile est tout indiqué ici pour regrouper les trois étapes de la figure 1 en une seule commande. En se basant sur ce que nous avons vu précédemment, ce makefile pourrait s’écrire comme suit :

    /img-articles/lm/84/art-3/fig-1.jpg

    Fig. 1 : Déroulement des opérations pour obtenir le fichier cible rapport.pdf

    rapport.pdf: rapport.tex sinus.plt
             gnuplot sinus.plt
             epstopdf sinus.eps
             pdflatex rapport.tex

    Notre projet comporte en effet une cible (rapport.pdf) et deux sources (rapport.tex et sinus.plt). Cependant, avec cette structure, dès que l’un des fichiers sources est modifié, la totalité du processus est exécutée une nouvelle fois.
    Alors que si on ne modifie que rapport.tex, il n’y a pas besoin de générer de nouveau la figure Gnuplot. Un makefile plus intelligent serait donc le suivant :

    rapport.pdf: rapport.tex sinus.pdf
             pdflatex rapport.tex
    
    sinus.pdf: sinus.plt
             gnuplot sinus.plt
             epstopdf sinus.eps

    Lorsque plusieurs règles sont présentes dans un makefile, make exécute par défaut la première qui ne commence pas par un point. Dans cette configuration, c’est la règle " rapport.pdf " qui va donc être exécutée. Ses pré-requis sont les fichiers rapport.tex et sinus.pdf.
    Dans le cas de ce dernier, make trouve dans le makefile une règle permettant de le construire à partir de sinus.plt. make va donc commencer par vérifier que sinus.pdf est à jour (c’est-à-dire que sa date de modification est postérieure à celle de sinus.plt).
    Dans le cas contraire, il exécutera la règle " sinus.pdf ". Ensuite, make fait de même pour la règle " rapport.pdf ", qui sera exécutée de nouveau si rapport.tex ou sinus.pdf sont plus récents que rapport.pdf.
    On voit donc que les instructions du makefile permettent à make de construire un arbre de dépendances, un peu à la manière de celui de la figure 1.

    Note:

    Nous aurions pu créer trois règles : rapport.pdf: rapport.tex sinus.pdf, sinus.pdf: sinus.eps et sinus.eps: sinus.plt.
    Mais pour notre utilisation, la modification du fichier Gnuplot entraîne systématiquement la création du fichier eps et la conversion de ce fichier en pdf. Deux règles sont donc suffisantes.

    Nous pouvons encore perfectionner notre makefile, de façon à le rendre plus facilement réutilisable.

    Règles génériques

    Il est possible de définir des règles génériques, de manière à laisser make construire lui-même l’arbre de dépendances. L’exemple précédent devient alors :

    rapport.pdf: rapport.tex sinus.pdf
        pdflatex $<
    
    %.eps: %.plt
        gnuplot $<
    
    %.pdf: %.eps
        epstopdf $<

    Ici, les deux dernières règles ne sont que des méthodes génériques permettant à make de reconstruire son arbre de dépendances.

    Ces règles s’écrivent donc en utilisant un % en lieu et place du nom de fichier. Dans le corps de la règle, on dispose également de plusieurs variables :

    • $< qui correspond à la première source (dépendance) ;
    • $@ qui correspond à la cible ;
    • $* est équivalent à ce que recouvre le % lorsque l’on évalue la règle correspondante. Ici, il s’agit du nom du fichier (cible) sans extension.

    D’autres variables existent, mais nous ne nous en servirons pas ici. Vous pouvez les retrouver dans le manuel de make [1].

    Le principal intérêt du listing ci-dessus, c’est que si vous voulez ajouter une autre figure Gnuplot, disons cosinus.pdf, il vous suffit de l’ajouter à la fin de la première ligne du makefile.

    Et c’est tout ! De même, si vous faites un autre projet, il vous suffit d’y recopier ce makefile et de changer les noms de fichier de la première ligne. Facile, non ?

    Note:

    Comme dans le listing précédent, nous aurions pu ne définir que deux règles. Ceci fonctionnerait très bien si on n’avait à insérer dans le document que des figures générées par Gnuplot.
    Avec le listing proposé dans cette section, si vous souhaitez ajouter à votre document une figure produite par le module Draw d’OpenOffice au format eps, il vous suffit de modifier la première ligne en rapport.pdf: rapport.tex sinus.pdf ma_figure_OOdraw.pdf. La dernière règle du listing sera ainsi utilisée à la fois pour convertir les figures provenant de Gnuplot et celles provenant d’OpenOffice Draw.

    D’autres utilisations

    Nous avons vu l’utilisation de make pour compiler un projet LaTeX. Une autre tâche peut être automatisée : le nettoyage des fichiers temporaires.
    Lorsque votre projet est terminé, et que vous voulez l’archiver, vous avez tout intérêt à supprimer les fichiers utilisés par LaTeX durant la compilation (fichiers *.aux, *.toc, *.log, etc.). La règle suivante (placée à la suite du listing précédent) permet de le faire de façon simple :

    propre:
          @echo "suppression des fichiers de compilation"
          @rm -f *.log *.aux *.dvi *.toc *.lot *.lof

    Plusieurs points remarquables :

    • la cible a un nom qui ne correspond pas à un fichier. En fait, cela n’est pas obligé, et ça tombe bien, puisque cette règle ne produit pas de fichiers (elle les détruit) ;
    • il n’y a pas de fichier source. Lorsqu’elle est appelée, cette règle doit s’exécuter à tous les coups, sans vérifier l’antériorité de la source sur la cible ;
    • le caractère @ en début de ligne indique que la ligne n’est pas imprimée sur le terminal lors de l’exécution de make.

    On peut également noter la présence de la commande echo pour obtenir un message sur le terminal. Pour exécuter cette règle, il faut l’indiquer explicitement à make par :

     make -k propre

    L’option -k spécifie à make de ne pas s’arrêter sur les erreurs d’exécution. Elle n’a aucun effet ici. Remarquez que lorsque l’on exécute make -k propre, seule la règle nommée propre est traitée par make.
    Lorsque vous ne spécifiez pas de nom de règle, rappelons que si plusieurs règles sont présentes dans un makefile, make exécute par défaut la première qui ne commence pas par un point.
    Une autre règle que nous pouvons rajouter à notre makefile est la suivante :

     initial:propre
    	rm -f *.pdf

    Elle a pour but de supprimer tous les résultats de compilation, fichiers pdf y compris. Pour cela, elle fait appel à la règle " propre " (qui est placée ici comme pré-requis), puis supprime explicitement les fichiers pdf.
    La règle initial permet donc de ne garder que les fichiers sources. Cela peut être intéressant si vous utilisez un système de contrôle de version (comme par exemple subversion) ou pour archiver vos fichiers sans prendre trop de place.

    Make, pour gérer un projet complexe

    Si vous vous attelez à la rédaction d’un " gros " document LaTeX, il vous faudra adopter une structure plus complexe que celle que nous avons vue ci-dessus :

    • rédaction de la bibliographie à l’aide d’un fichier bibtex externe ;
    • arborescence séparée pour les figures, les fichiers LaTeX, etc. ;
    • utilisation d’autres programmes externes, comme par exemple subversion.

    Voyons comment prendre en compte ces éléments dans notre makefile.

    Bibliographie

    Nous avons vu dans l’article sur BibTeX qu’il est intéressant de lui confier la gestion de notre bibliographie. BibTeX étant un programme indépendant de LaTeX, il faut qu’il soit géré par notre makefile.
    Lorsque l’on ajoute une référence bibliographique dans un document LaTeX, la marche à suivre pour obtenir un document à jour est la suivante : une compilation LaTeX, puis une passe BibTeX, puis deux nouveaux appels à LaTeX.

    rapport.pdf: rapport.tex biblio.bib
    	pdflatex rapport.tex
    	bibtex rapport
    	pdflatex rapport.tex
    	pdflatex rapport.tex

    La solution la plus simple consiste donc à écrire ces quatre appels successifs dans le makefile, de la manière suivante :

    Cette méthode n’est pas satisfaisante, parce qu’elle impose trois passes de LaTeX chaque fois qu’on fait appel à make, même si on n’a pas rajouté de référence bibliographique.

    La solution consiste à regarder dans le fichier de sortie de LaTeX, qui nous indique si la compilation s’est bien déroulée ou s’il est nécessaire de recompiler et/ou d’appeler BibTeX.
    Une solution relativement complète peut s’écrire comme :

    1   SRC = rapport
    2   LATEX = pdflatex -interaction=batchmode
    3   BIBTEX = bibtex -terse
    4   RERUN = ‘(There were undefined references|Rerun to get (cross-references|the bars) right)’
    5   UNDEFINED = ‘((Reference|Citation).*undefined)|(Label.*multiply defined)’
    6
    7   %.pdf : %.tex
    8   	@echo “compilation du tex”
    9   	${LATEX} $<
    10  	@if [ -e ${SRC}.bbl ]; then ${BIBTEX} $* ; fi
    11  	@if egrep -q $(RERUN) $*.log ; then echo "passe LaTeX" \
    12  	&& $(LATEX) $<; fi
    13  	@if egrep -q $(RERUN) $*.log ; then echo "passe LaTeX" \
    14	&& $(LATEX) $<; fi
    15  	@echo “Citations ou références indéfinies:"
    16  	@egrep -i $(UNDEFINED) $*.log || echo "Aucune"

    Une solution élégante pour produire des documents contenant une bibliographie gérée par BibTeX.

    Les lignes 1 à 5 permettent de définir des variables qui seront utilisées dans la règle %.pdf : %.tex :

    • SRC contient le nom (sans extension) du fichier LaTeX source ;
    • LATEX est le nom de la commande appelant LaTeX. Cette manière de procéder permet d’échanger facilement LaTeX et pdflatex. Cela permet également de définir l’option batchmode, qui spécifie au compilateur de ne pas se mettre en mode interactif lorsqu’il rencontre une erreur et de ne pas afficher le fichier de sortie sur l’écran (il est directement écrit dans un fichier log) ;
    • BIBTEX fait de même pour BibTeX. L’option terse supprime les messages de sortie de BibTeX ;
    • les autres variables sont les chaînes de caractères que l’on va chercher dans le fichier log de LaTeX pour savoir quelles sont les actions à effectuer.

    Le fonctionnement de la règle proprement dite est le suivant :

    • ligne 9, on effectue une première passe de LaTeX ;
    • ligne 10, on vérifie qu’un fichier existe. Ce fichier est généré par LaTeX et contient les appels bibliographiques. S’il existe, c’est qu’on utilise BibTeX. Dans ce cas, on invoque BibTeX ;
    • on analyse ensuite (lignes 11 et 12) le fichier de sortie de LaTeX (à l’aide d’egrep), et si on y trouve la chaîne $(RERUN), on effectue un nouvel appel à LaTeX ;
    • lignes 13 et 14, on refait la même chose ;
    • enfin, on regarde s’il reste toujours des références bibliographiques inconnues (en cherchant la chaîne $(UNDEFINED)). Le cas échéant, on les affiche, sinon, on affiche " Aucune ".

    Remarquez que les appels des variables se font en les précédant d’un $, et en les entourant de parenthèses ou d’accolades pour tenir compte des éventuelles espaces qu’elles contiennent.
    Petite subtilité : BibTeX est systématiquement exécuté dans cette règle, que LaTeX ait signalé des références non définies ou pas. La raison est simple : lorsque l’on supprime des références bibliographiques dans le fichier tex, LaTeX ne génère aucun avertissement. Dans ce cas, si l’on ne force pas l’exécution de BibTeX, les références supprimées restent dans la bibliographie !
    Comme une passe BibTeX n’est pas longue, nous avons donc décidé de la rendre systématique. Remarquez tout de même que ce système n’est pas parfait, puisque la bibliographie sera mise à jour à la compilation suivante.

    Récursivité

    Lorsque l’on commence à avoir beaucoup de figures dans un document, il est bon de les mettre dans un (ou plusieurs) répertoire(s) séparé(s). Il est bien entendu possible de continuer à tout gérer avec un seul makefile situé dans la racine, mais make offre la possibilité de " cascader " les makefiles, ce qui offre une certaine souplesse. Ajoutons les lignes suivantes au makefile situé dans le répertoire racine de notre document (le listing complet est donné dans l’encadré n°2 en page suivante) :

    1   SRC = rapport
    2   REP= ./sources_gnuplot
    3
    4   .PHONY:all $(REP)
    5
    6   all: $(REP) ${SRC}.pdf
    7
    8   $(REP):
    9       @$(MAKE) -C $@ $(MAKECMDGOALS)

    Les deux premières lignes sont simplement des raccourcis. $REP contient la liste des répertoires que make devra parcourir (séparés par une espace). La ligne 4 définit une cible spéciale de make, .PHONY. Cette cible est utilisée pour signifier à make que lorsqu’il doit exécuter les règles all ou $(REP), il n’a pas à vérifier que des fichiers nommés all ou ./sources_gnuplot (contenu de la variable REP) existent et sont plus récents que leurs cibles respectives. Avec cette directive, make considère que all (ou ./sources_gnuplot) est un nom de règle, pas un fichier cible, et que cette règle doit être exécutée en totalité à chaque appel (make all). Pour comprendre l’intérêt de .PHONY, imaginons qu’un fichier nommé all se trouve (par hasard) dans votre répertoire.
    Comme ce fichier n’est pas modifié par notre makefile (admettons que le fichier all ne fait pas partie de notre projet), il sera toujours plus ancien que les fichiers cibles de la règle " all ", et donc make n’exécutera jamais cette règle. Maintenant que nous avons placé all dans le .PHONY, make exécutera la règle " all " indépendamment de la présence ou non d’un fichier nommé all. Dans le cas de all, ce mécanisme n’a que peu de chances de servir (la probabilité que l’on crée un fichier nommé all est faible). Par contre, dans le cas de $(REP), le répertoire ./sources_gnuplot (make ne fait pas de différence entre un fichier et un répertoire) se trouve bien sur le disque, et n’est pas modifié lors de l’exécution de make. Il est donc impératif de le placer dans le .PHONY, sous peine de ne jamais exécuter la règle associée. D’une manière générale, il faut placer dans .PHONY toutes les cibles qui ne sont pas des fichiers modifiés par make. Voyons maintenant à quoi servent ces règles. À la ligne 6, on définit une cible all, avec comme dépendances le fichier pdf et le répertoire contenant les fichiers Gnuplot. La cible pdf est classiquement exécutée par les règles %.pdf: %.tex vues plus haut (et non inclues dans cet extrait, voir le listing complet en encadré 3). Enfin, lignes 8 et 9, on définit la règle $(REP) (sans dépendances, puisqu’elle doit toujours être évaluée). Cette règle consiste à exécuter make (variable $(MAKE) prédéfinie) dans le répertoire ./fichiers_gnuplot, avec la cible qui a été passée lors de l’appel à make (contenue dans la variable $(MAKECMDGOALS)).
    De cette manière, si vous exécutez make propre (voir plus haut) pour nettoyer les fichiers de compilation, c’est également la cible propre du makefile situé dans le répertoire ./fichiers_gnuplot qui sera exécutée. Le makefile situé dans le répertoire ./fichiers_gnuplot peut être le suivant :

    1   FICHIERS_GNUPLOT = $(wildcard *.plt)
    2   FICHIERS_PDF = $(patsubst %.plt,%.pdf,  $(FICHIERS_GNUPLOT))
    3
    4   all: $(FICHIERS_PDF)
    5
    6   %.eps: %.plt
    7   	@ echo “compilation de “$<
    8   	@gnuplot $<
    9
    10  %.pdf: %.eps
    11  	@ echo “conversion de “$*”.eps”
    12  	@epstopdf $*.eps

    La seule spécificité de ce makefile réside dans ses deux premières lignes : dans la première, on utilise la fonction wildcard * qui agit exactement comme le caractère joker du bash (*).

    Ligne 1, on récupère la liste des fichiers plt contenus dans le répertoire courant. On effectue ensuite une copie de cette liste, mais en remplaçant l’extension plt par pdf. De cette manière, on obtient une liste des cibles.

    La ligne 4 définit une cible all, dont les dépendances sont les fichiers pdf listés dans $(FICHIERS_PDF). Si aucun fichier nommé all n’est présent dans le répertoire courant, cette règle est exécutée (notez que nous aurions pu utiliser la directive .PHONY pour ignorer un éventuel fichier nommé all). Comme l’exécution de cette règle ne crée pas de fichier all, elle est exécutée systématiquement.

    Les lignes 6 à 12 ne sont que les règles génériques permettant de générer un fichier pdf à partir d’un fichier Gnuplot, déjà vues plus haut.

    Deux points sont à remarquer dans ce makefile :

    • même s’il est appelé depuis le répertoire racine de notre document (par le makefile " maître "), make considère que le répertoire courant est celui du makefile qu’il exécute (ici ./fichiers_gnuplot). Pas besoin donc de spécifier le répertoire dans le makefile ;
    • ce makefile ne contient aucun nom de fichier spécifique : lorsque vous ajoutez un fichier Gnuplot dans le répertoire, il est automatiquement pris en compte !

    On pourrait encore ajouter à notre makefile les cibles spécifiques comme la suppression des fichiers de compilation, etc. Mais nous vous laissons faire, à titre d’exercice !
    Vous pouvez vous inspirer du listing de l’encadré n°3 qui vous propose, en plus des cibles propre et initial, une cible commit qui effectue une compilation complète du document (avec trois passes de LaTeX et une de BibTeX, pour être sûr d’avoir un document parfaitement à jour), efface les fichiers temporaires, puis effectue un commit subversion. Remarquez que les règles n’ayant pas de dépendance (comme complet, propre, snv) sont automatiquement évaluées, et n’ont pas besoin d’être placées dans le .PHONY.

    Conclusion

    Nous espérons vous avoir donné, au travers de cet article, un aperçu des possibilités offertes par les makefiles à un rédacteur

    Encadré n°2 : Documents servant d’illustration pour la création d’un makefile simple.

    sinus.plt
    # tracé de sinus x
    set term post eps enhanced
    set output "sinus.eps"
    plot sin(x)
    rapport.tex
    \documentclass[a4paper]{article}
    \usepackage[frenchle]{babel}
    \usepackage[latin1]{inputenc}
    \usepackage[T1]{fontenc}
    \usepackage[pdftex]{graphicx}
    \begin{document}
    \section{\’Etude de la fonction $sin(x)$}
    La fonction $sin(x)$ permet de faire de jolis tracés
    \begin{figure}[htbp]
      \centering
      \includegraphics{./sinus.pdf}
      \caption{$f=sin(x)$ }
      \label{fig-sinus_x}
    \end{figure}
    \end{document}

    de documents LaTeX. make est un programme très complet, dont nous sommes loin d’avoir fait le tour ici.
    Les personnes désireuses d’en savoir plus peuvent aller sur les liens donnés en bibliographie.
    Vous y découvrirez encore bien d’autres possibilités des makefiles, qui peuvent être très utiles au rédacteur de documents, comme par exemple la possibilité de définir un répertoire par défaut pour tel ou tel type de fichiers (pour mettre tous vos eps ensemble, et garder vos sources Gnuplot séparés), e rajouter un peu de programmation shell pour vous tailler un makefile sur mesure... Il y a de quoi remplir le magazine !

    encadré n°3 : Un exemple de makefile complet avec l’appel d’un autre makefile (dans ./sources_gnuplot) et plusieurs règles (nettoyage, recompilation complète, envoi des modifications à un référentiel subversion)

     SRC = rapport
    REP= ./sources_gnuplot
    LATEX = pdflatex -interaction=batchmode
    BIBTEX = bibtex -terse
    RERUN = ‘(There were undefined references|Rerun to get (cross-references|the bars) right)’
    UNDEFINED = ‘((Reference|Citation).*undefined)|(Label.*multiply defined)’
    .PHONY:all $(REP)
    all: $(REP) ${SRC}.pdf
    $(REP):
    	@$(MAKE) -C $@ $(MAKECMDGOALS)
    propre: $(REP)
    	@echo “suppression des fichiers de compilation”
    	@# fichiers de compilation latex
    	@rm -f *.log *.aux *.dvi *.toc *.lot *.lof
    	@# fichiers de bibtex
    	@rm -f *.bbl *.blg
    complet:
    	@echo “compilation complete”
    	@${LATEX} ${SRC}
    	@if [ -e ${SRC}.bbl ]; then ${BIBTEX} ${SRC} ; fi
    	@${LATEX} ${SRC}
    	@${LATEX} ${SRC}
    svn:
    	@echo „on fait le commit“
    	svn commit
    commit: complet propre svn
    initial: propre
    	@echo „suppression des fichiers cibles“
    	@rm -f ${SRC}.ps ${SRC}.pdf
    %.pdf : %.tex
    	@echo „compilation du tex“
    	${LATEX} $<
    	@if [ -e ${SRC}.bbl ]; then ${BIBTEX} $* ; fi
    	@if egrep -q $(RERUN) $*.log ; then echo "passe LaTeX" \
    	&& $(LATEX) $<; fi
    	@if egrep -q $(RERUN) $*.log ; then echo "passe LaTeX" \
    	&& $(LATEX) $<; fi
    	@echo “Citations ou références indéfinies:"
    	@egrep -i $(UNDEFINED) $*.log || echo "Aucune"

    Bibliographie:

    Retrouvez cet article dans : Linux Magazine 84

    Posté par (La rédaction) | Signature : Cyril Buttay & Florent Morel | Article paru dans

    Laissez une réponse

    Vous devez avoir ouvert une session pour écrire un commentaire.