-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathmake.cli.txt
273 lines (245 loc) · 18.7 KB
/
make.cli.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
┏━━━━━━━━━━┓
┃ MAKE ┃
┗━━━━━━━━━━┛
automake ? autoconf ?
3.7 and 3.8
10.5.5 et 4.13
4.14
6.3.1 : voir 8.2
┌──────────┐
│ MAKE │
└──────────┘
make [TARGET] #Exécute la rule dont la target est TARGET de (dans l'ordre) :
# - ./GNUmakefile (checké seulement par GNU Make)
# - ./makefile
# - ./Makefile (préférer cette syntaxe)
#Exécute aussi les rules dont dépend cette rule.
#TARGET est par défaut la première TARGET de la première rule, en excluant les TARGET commençant par un
#point et ne contenant pas de /, et les rules dont les PREREQ... contiennent un %.
#Cette première TARGET est souvent appelée "all".
-f FILE
--file=FILE
--makefile=FILE #Utilise non pas ./Makefile, etc. mais FILE.
-IDIR
--include-dir=DIR #Rajoute DIR à l'include path pour directive "include"
-n
--just-print #Ne fait qu'imprimer les COMMANDE finalement à exécuter, mais ne les exécute pas.
-s
--silent #N'imprime pas les COMMANDE exécutées.
-j [NOMBRE] #Fait que NOMBRE recipes maximum pourront être exécutées en même temps (multithreading), si elles ne
--jobs [NOMBRE] #dépendent pas l'une de l'autre.
#Les recipes ne doivent pas alors pas utiliser stdin.
#Ne fonctionne pas si la phony target .NOTPARALLEL est définie.
#Si pas de NOMBRE, illimité.
-l NOMBRE
--max-load NOMBRE #Fait que si le load average est supérieur à NOMBRE, le comportement de -j est temporairement inhibé.
-i
--ignore-errors #Equivaut à mettre un - devant toutes les COMMANDES.
-k
--keep-going #Fait que si une commande échoue, la rule achève son exécution avant que make s'arrête.
┌──────────────┐
│ MAKEFILE │
└──────────────┘
#COMMENTAIRE
$$ #Les dollars doivent être ainsi échappés, par exemple $$VAR dans une recipe
TABULATIONS ==> #Les tabulations sont importants et non-remplaçables par des espaces : ne pas faire commencer quoi que
#soit (autre qu'une recipe) par une tabulation, et faire commencer recipes par tabulations.
#Pour utiliser autre chose que tabulation, modifier variable .RECIPEPREFIX
#Les newlines sont respectées : on peut cependant faire des trailing backslashes, mais la ligne
#suivante doit commencer par une tabulation également.
DIRECTIVES ==> #Elles sont à mettres en dehors des rules, de même que les déclarations de variables.
#Il y a include, vpath.
[-]include FILE... #Permet d'include (remplace directive par contenu de FILE) les makefiles FILE... (globbing et $(VAR)
#possibles).
#Si un des FILE... n'est pas trouvé, une erreur fatale a lieu, à moins que "-" précède "include"
#Si FILE... est un chemin relatif, il est recherché dans l'include path : /usr/local/include/,
#/usr/include/
#Attention, car un include au début du fichier peut modifier la default rule.
#Il est également possible de définir l'environment variable (et non Make variable) MAKEFILES, qui
#équivaut à faire un -include $(MAKEFILES) au début du fichier, sauf que cela ne modifie jamais la
#default rule.
TARGET...: [PREREQ...] #Make "rule"
[COMMANDE #Exécute COMMANDE... (la "recipe") pour chaque TARGET.
[COMMANDE]...] #La ligne du dessus indique que les rules de PREREQ... ("prerequisites") doivent être exécutées avant
#d'exécuter la rule courante (celle de TARGET).
#En général :
# - TARGET est le fichier compilé
# - PREREQ... les sources à compiler, les headers qu'ils include et les .o à lier
# - COMMANDE la compilation (avec -c sauf pour la compilation finale)
#Utiliser plusieurs TARGET... revient à écrire plusieurs rules différentes avec chaque TARGET et les
#mêmes PREREQ et COMMANDE...
MISE A JOUR ==> #COMMANDE sera exécuté si :
# a) TARGET n'existe pas
# b) ou un PREREQ n'existe pas
# c) ou un PREREQ a une mtime < TARGET
#Cela évite de tout recompiler à chaque fois. La condition c) ne prend pas en compte les PREREQ se
#situant à droite d'un |. Par exemple :
# - TARGET... : [PREREQ1...] | PREREQ2...
#Cela est utile par exemple si TARGET dépend de la construction d'un répertoire PREREQ, car sinon toute
#création/suppression d'un des fichiers contenus dans PREREQ mettant à jour la mtime du répertoire,
#même si ce fichier n'a rien à voir avec TARGET, TARGET serait recompilé.
#make regarde à nouveau toutes rules jusqu'à ce qu'il fasse une passe où toutes rules sont ignorées.
#make -q, -n et -t mettent à jour également.
ERREURS LORS DU MAKE ==>#Si COMMANDE renvoie un exit code != 0, make s'arrête.
#Pour éviter cela (par exemple au cas où la COMMANDE peut échouer parce que FILE existe déjà, où pour
#les commandes qui ont des exit code souvent != 0), écrire sous la forme -COMMANDE.
#De plus, si make s'arrête, la TARGET de la rule posant problème sera peut-être considérée comme mis à
#jour, si sa mtime a changé.
#Pour éviter cela, définir la phony target .DELETE_ON_ERROR, qui supprimera alors une TARGET dont
#la rule échoue.
MAKE SUBSHELLS ET ECHO #Les COMMANDE sont interprétées par /bin/sh. Elles peuvent contenir des structures, etc.
==> #Chaque COMMANDE est exécutée dans son propre subshell, sauf si l'on définit la phony target .ONESHELL
#(auquel cas 1 target = 1 subshell). Par conséquent, les structures, etc. doivent être sur une seule
#ligne/COMMANDE : utiliser donc des ; ou des newlines avec trailing backslashes.
#Echapper les $VAR : $$VAR
#Chaque COMMANDE est imprimée avant d'être exécutée, à moins d'être écrit sous la forme @COMMANDE. A ne
#faire qu'en face de la première COMMANDE si .ONESHELL.
TARGET MULTI-RULE ==> #Une rule ne peut pas avoir une TARGET utilisée par une rule précédente.
#Exceptions :
# - cette rule supplémentaire ne doit pas avoir de recipe.
# - cela a pour effet de redistribuer les prerequisites de la rule supplémentaire vers la rule
# précédente de chaque TARGET.
COMMANDE OMIS ==> #PREREQ n'étant pas omis :
# - COMMANDE est par défaut : cc -c PREREQ... -o ${PREREQ%.c}.o (cc pointe vers gcc)
# - TARGET.c, s'il existe et est absent de PREREQ, est rajouté à PREREQ.
COMMANDE ET PREREQ #Alors :
OMIS ==> # - rien ne se passe
# - mais cela permet d'utiliser TARGET comme prerequisite d'une autre rule pour l'exécuter quand
# TARGET est mis à jour (notamment un fichier source)
TARGT... : PTRN1: PTRN2 #Est expanded en une série de rules ayant chacune :
[COMMANDE] # - une TARGET (chaque TARGET)
# - des PREREQ... obtenus ainsi : la TARGET doit matcher PATTERN1 (globbing limité), qui doit
# contenir un seul %. Ce qui matche % est susbtitué au % de PATTERN2, qui forme le prerequisite
# pour la TARGET présente.
# - la même COMMANDE (si présente)
#Exemple :
# - a.o b.o : %.o: %.c
# [COMMANDE]
#devient :
# - a.o : a.c
# [COMMANDE]
# b.o : b.c
# [COMMANDE]
#Tout ceci est mieux qu'une implicit rule.
LIBRARIES ==> #un PREREQ peut être sous la forme : -lLIB
#-lLIB est remplacé en fonction de .LIBPATTERNS : il devient égal à .LIBPATTERNS, mais les % sont
#remplacés par LIB (.LIBPATTERNS est par défaut "lib%.so lib%.a")
#Par exemple, -lSDL est remplacé par "libSDL.so", puis si rien n'est trouvé par "libSDL.a". Ces
#fichiers sont recherchés dans le répertoire courant, puis dans le vpath, puis dans le lib path
#(/lib:/usr/lib:/usr/local/lib).
#-lLIB n'a pas besoin d'avoir sa propre rule.
#La variable $^ permet ensuite de les utiliser dans la recipe, par exemple :
#TARGET : PREREQ.c -lLIB
# $(CC) $^ -o $@
#On peut aussi utiliser les variables $(LFLAGS), etc.
VPATH ==> #VPATH est le leading path recherché pour les prerequisites et les targets, après avoir
#recherché dans le répertoire courant.
#Par défaut, VPATH est vide.
#Si les prerequisites ne sont pas trouvés, les autre rules sont exécutées dans l'espoir que le
#prerequisite recherché soit créé, et les prerequisites de la rule problématique sont à nouveau
#recherchés : si toujours pas trouvés, provoque erreur.
vpath [PATTERN] [DIRS] #PATTERN utilise le globbing limité.
#DIRS est une suite de répertoires séparés par : ou whitespaces.
#Rajoute DIRS au vpath pour files matchant PATTERN uniquement.
#Si DIRS absent, supprime ajouts au vpath pour PATTERN uniquement.
#Si DIRS et PATTERN absents, supprime ajouts au vpath pour tout PATTERN.
#Cela permet de ranger les fichiers dans des catégories prévues pour (headers dans include/,
#exécutables dans bin/, source dans src/, etc.), et non mettre les .c et .h dans le même répertoire,
#etc.
#Exemple : vpath %.h ./include/
#Utiliser $^, $@ et $< dans la recipe pour conserver le dir appended par vpath, et non simplement
#utiliser le filename.
PHONY TARGETS ==> #TARGET peut être non pas un fichier, mais un mot, afin de pouvoir faire make TARGET ("phony targets").
#Une phony target ne devrait pas être utilisée comme PREREQ d'une target non-phony.
#Phony targets courantes :
# - install : déplace les fichiers créés (exécutables, fichiers conf, ressources, etc.) vers les
# répertoires prévus pour dans le système hôte.
# - uninstall : supprime ces fichiers
# - clean : supprime les fichiers créés par make (devenus inutiles une fois copiés par make install)
# - check : fait un test de compilation
# - installcheck : teste si l'installation s'est bien déroulée.
#Cependant, si par malheur TARGET est le nom d'un fichier existant dans le répertoire courant, la rule
#ne sera pas exécutée, car considérée à jour. Pour éviter ce problème, il faut mettre juste avant
#toutes les phony targets :
# - .PHONY : TARGET...
#TARGET... étant l'ensemble des phony targets. Cela a pour effet de toujours exécuter la recipe lors
#d'un make TARGET (ne jamais la considérer à jour)
#On peut aussi faire (même résultat) :
# - TARGET: MOT
# COMMANDE
# MOT: ;
#MOT est souvent "FORCE". Car une rule d'un fichier n'existant pas, sans prerequisite ni recipe est
#toujours considérée comme nouvellement à jour, ce qui fait que les rules dépendant d'elles sont aussi
#mises à jour. Préférer utiliser ".PHONY"
EMPTY TARGET ==> #L'idée est d'avoir une TARGET étant un fichier vide, et de faire :
# - TARGET: PREREQ...
# COMMANDE
# touch TARGET
#Ainsi, make TARGET effectuera COMMANDE à chaque fois que la mtime de l'un des PREREQ... changera.
%: force
COMMANDE
force: ; #Exécute COMMANDE pour tout make
GLOBBING ==> #Le globbing est possible dans les rules (targets, prerequisites et recipes). nullglob n'est alors pas
#activé.
#Pour les définitions de variables, si VAL contient du globbing, il faut l'écrire sous la forme
#$(wildcard VAL) (nullglob activé, pas d'espace après les parenthèses)
GLOBBING LIMITE ==> #Le globbing limité est constitué d'une seule wildcard % qui équivaut au * du globbing normal.
#Possible dans les targets des rules normales (ni implicites ni avec patterns)
$^ #Est expanded en PREREQ...
$< #Est expanded dans le premier des PREREQ... (utile si PREREQ... est un source suivi d'header[s])
$@ #Est expanded en TARGET (si plusieurs TARGET..., est expanded en chaque TARGET, pour chaque TARGET)
$(VAR) #Expansion de variables, partout.
${VAR} #Les variables d'environnement sont disponibles.
#Cela marche par expansion/macro, VAL n'est pas directement évalué.
VAR = VAL #Définit une variable qui pourra être utilisée sous la forme $(VAR).
VAR := VAL #Différence :
# - := expand une fois VAL lors de la définition VAR := VAL
# - = expand infinimenent et récursivement VAL lors de son utilisation $(VAR)
#Par conséquent, = permet des références indirectes, mais := permet VAR := $(VAR) VAL, qui cause
#une infinite loop avec =
#Variables souvent utilisées :
# - CC : le compiler C (ex : gcc), par défaut cc
# - CXX : le compiler C++ (ex : g++)
# - CFLAGS : options de compilation C (ex: -Wall -pedantic)
# - CXXFLAGS : options de compilation C++
# - LFLAGS : options de linking (ex : -lSDL)
# - LXXFLAGS : options de linking C++
# - CPPFLAGS : options du preprocesseur C
# - OBJS : ensemble des fichiers objets à lier avec le main
#Autres variables possibles :
# - DISTCOMMON : fichiers souvent à la racine non source tel que COPYING ou README
# - commande d'installation, tel qu'install -cm 644
#VAL peut aussi être des commandes, que l'on exécute ensuite via $(VAR)
VAR += VAL #Append VAL à VAR, en utilisant = ou := selon celui utilisé précédemment pour VAR (si pas de
#définition précédente de VAR)
define VAR =
...
endef #Equivaut à VAR = ..., sauf que ... peut contenir des newlines.
VAR ?= VAL #Equivaut à VAR = VAL, si VAR n'a pas été jusqu'ici défini
[un]export VAR #Pour exporter vers subshells, dont make recursifs.
#Pour exporter toutes variables, faire simplement [un]export
MAKE RECURSIVE ==> #Un Makefile par répertoire.
#En général le Makefile parent fait $(MAKE) -C DIR du Makefile enfant, se trouvant dans DIR.
#-C DIR modifie le répertoire courant lors de l'invocation de $(MAKE) et définie une variable
#read-only $(CURDIR) égale à DIR pour cette invocation
#Pour pouvoir faire une exécution parallèle, on utilise une rule par subdir :
# SUBDIRS = a b c
# .PHONY: all $(SUBDIRS)
# all: $(SUBDIRS)
# $(SUBDIRS):
# $(MAKE) -C $@
#.PHONY est nécessaire, sinon SUBDIR existant, sa rule ne serait pas exécuté.
#Toujours utiliser $(MAKE) et non make.
#Pour faire en sorte que b ne soit made que lorsque a a fini de l'être :
# b: a
#Variables :
# - MAKELEVEL est égal au niveau de récursion (0 pour root)
# - MAKEFLAGS est égal aux flags passé au make initial, sans le tiret. Est exporté par défaut aux
# make enfants.
gcc -M a.c #Compilation avec mêmes options que d'habitudes (dont -I, etc.), mais -M en plus :
#imprime rule sans recipe :
# a.o: a.c HEADERS...
#Pour générer automatiquement les HEADERS PREREQ d'un fichier source et non updater le Makefile à la
#main à chaque changement des headers requis par a.c
SHELL #Shell utilisé, par défaut /bin/sh
.SHELLFLAGS #Arguments/options passées au shell, par défaut "-c"