make toto |
Néanmoins, la plupart du temps, on a besoin d'un Makefile : soit pour indiquer les dépendances entre les différents fichiers, soit car les commandes à lancer pour la compilation ne sont pas très standard. Voici un exemple de Makefile. La première ligne comporte le nom du « but », suivi de deux points. Les lignes suivantes (qui doivent impérativement commencer par une tabulation --- make est un logiciel vraiment archaïque) contiennent les commandes à lancer pour atteindre ce but. Pour lancer la compilation, on tapera make ou make all (le nom all n'a rien de particulier : c'est juste le premier but qui apparait dans le fichier).
all: latex 1 dvips -E -o 1.ps 1.dvi |
On peut indiquer les dépendance entre les différents fichiers : dans l'exemple suivant, on veut obtenir un fichier 1.ps, qui provient d'un fichier 1.dvi qui provient d'un fichier 1.tex. La commande make va comparer les dates de dernière modification de ces fichiers (s'ils existent) et ainsi juger s'il est nécessaire de recréer tout ou partie de ces fichiers.
all: 1.ps 1.ps: 1.dvi dvips -E -o 1.ps 1.dvi 1.dvi: 1.tex latex 1 |
Les commandes doivent tenir sur une ligne. Si on a besoin de plusieures lignes, on mettra un antislash à la fin. (Trouver un exemple utile...)
all: latex qksjfdlqkshdf.tex ; bibtex qksjfdlqkshdf ; latex qksjfdlqkshdf.tex ; latex qksjfdlqkshdf.tex ; dvips -o qksjfdlqkshdf.ps qksjfdlqkshdf.dvi |
all: latex qksjfdlqkshdf.tex ; \ bibtex qksjfdlqkshdf ; \ latex qksjfdlqkshdf.tex ; \ latex qksjfdlqkshdf.tex ; \ dvips -o qksjfdlqkshdf.ps qksjfdlqkshdf.dvi |
Dans les deux exemples (équivalents) précédents, tout était lancé en une seule fois, à l'aide d'une unique commande system(). Par contre, dans l'exemple suivant, on lance une commande à la fois.
all: latex qksjfdlqkshdf.tex bibtex qksjfdlqkshdf latex qksjfdlqkshdf.tex latex qksjfdlqkshdf.tex dvips -o qksjfdlqkshdf.ps qksjfdlqkshdf.dvi |
Comme le caractère $ est interprété par make, il faut le doubler si on veut qu'il le soit par le shell. (Nous reverrons plus loin commen réécrire plus proprement cet exemple.)
all: for i in `find . -name "*.tex"` ;\ do ;\ latex $$i ;\ done |
On peut rajouter certains signes cabalistiques devant les commandes qui seront données au shell. Un @ signifie que la commande ne sera pas affichée.
all: @echo Je commence latex 1.tex @echo J\'ai terminé |
Un - demande de continuer même s'il y a des erreurs.
all: @echo Expect this to go wrong -python 1.py @echo Nonetheless, we are going on |
make -n |
make -k |
make -j 5 |
make -f Makefile.linux all |
TEX = 1.tex LATEX = latex -interaction=nonstopmode -shell-escape all: $(LATEX) $(TEX) |
On peut utiliser une variable dans la définition d'une autre variable.
MORE = A.tex B.tex TEX = 1.tex 2.tex 3.tex 4.tex $(MORE) |
L'exemple suivant est équivalent (mais ne le copiez pas pour autant).
TEX = 1.tex 2.tex 3.tex 4.tex $(MORE) MORE = A.tex B.tex |
Par conséquent, l'exemple suivant provoque une boucle récursive infinie...
TEX = 1.tex TEX = $(TEX) A.tex B.tex |
Si on tient à ce que le symbole = se comporte comme on s'y attend, on peut le remplacer par :=. L'exemple précédent peut se corriger ainsi.
TEX := 1.tex TEX := $(TEX) A.tex B.tex |
Quand make sait comment créer un fichier à partir d'un autre sans qu'on lui dise (par exemple, un fichier *.o à partir d'un fichier *.c), on peut quand même contrôler son comportement à l'aide de certaines variables.
CC = gcc CXX = g++ CPP = $(CC) -E CFLAGS = -Wall -O2 -I/usr/X11R6/include CXXFLAGS = LDFLAGS = |
Il y a d'autres variables qui sont souvent utilisées dans les Makefiles (mais pas dans les règles par défaut).
LDLIBS= -L/usr/X11R6/lib -lXaw3d -lXmu -lXt -lSM -lICE -lXext -lX11 -lm |
On peut changer la valeur des variables du Makefile depuis la ligne de commande.
make CC=gcc all make CC="gcc -Wall" all |
%.dvi : %.tex ; latex $< %.ps : %.dvi ; dvips -E -f $< > $@ %.gif : %.ps ; pstogif -scale 2 $< all: 1.ps |
TEX_FILES = $(wildcard *.d) |
Maintenant, on aimerait bien avoir le nom des fichiers PostScript correspondants, i.e., ceux que l'on aimerait créer. La fonction patsubst fait ce genre de chose.
%.dvi : %.tex ; latex $< %.ps : %.dvi ; dvips -E -f $< > $@ %.gif : %.ps ; pstogif -scale 2 $< TEX = $(wildcard *.tex) PS = $(patsubst %.tex,%.ps, $(TEX)) GIF = $(patsubst %.tex,%.gif, $(TEX)) all: $(GIF) -rm -f -- *.aux *.log clean: rm -f -- $(PS) $(GIF) *.log *.dvi *.aux *\~ |
On peut même lancer des commandes du shell. La commande suivante essaye d'obtenir la liste des répertoires contenus dans le répertoire courrant.
DIR = $(shell find . -type d -print) |
La fonction filter-out permet d'enlever certains éléments d'une liste : en particulier, ici, on ne veut ni le répertoire courrant, ni le répertoire Template.
DIR = $(filter-out . ./Template,$(shell find . -type d -print)) |
all: $(DIR) clean: $(DIR) .PHONY: $(DIR) $(DIR): $(MAKE) -C $@ $(MAKECMDGOALS) |
ifdef FOOBAR TEX := $(TEX) foobar.tex endif |
La fonction wildcard permet de ne retenir, dans une liste de noms de fichiers, que ceux qui sont effectivement là.
SCSI_SRCS = $(wildcard $(patsubst %.o,%.c, $(L_OBJS))) |
Pour inclure un fichier, s'il existe.
ifeq (.config,$(wildcard .config)) include .config else OPTIONS = endif |