|
Man kann auch Variablen innerhalb von Makefiles verwenden. Sie werden
dort als Makros bezeichnet und meistens gross geschrieben. Mit
wird ein Makro CC mit dem Wert gcc angelegt. Der Wert darf dabei
auch aus mehreren Wörtern bestehen (Beispiel: CC = gcc -O). Die
Definition darf sich auch über mehrere Zeilen erstrecken, wenn die
Zeile mit \ aufhört (Achtung: bitte darauf achten, dass das \
tatsächlich das letzte Zeichen in der Zeile ist und kein Tabulator-
oder Leerzeichen dahintersteht!).
Der Aufruf des Makros CC kann mit
erfolgen.
|
make kennt schon eine Reihe von vordefinierten Makros. So ist zum Beispiel die
Makrodefinition CC = cc dem make-Kommando bereits bekannt. Mit
user@linux $
make -p -f /dev/null
|
können die internen Makros und Regeln abgefragt werden. Ist man nur an
den Makros interessiert, kann man diese mit Hilfe des grep- und
sort-Kommandos ausfiltern und sortieren:
user@linux $
make -p -f /dev/null | grep " = " | sort
|
|
Makros können schon vordefiniert sein, Makros können im Makefile
gesetzt werden, Makros können aber auch beim Aufruf von make
übergeben werden:
user@linux $
make love CC=gcc
|
Soll das Makro aus mehreren Wörtern bestehen, so muss es beim Aufruf
gequotet (d.h. mit einfachen oder doppelten Anführungszeichen
umgeben) werden:
user@linux $
make love CFLAGS="-O -DNDEBUG"
|
|
Umgebungs-Variablen werden innerhalb eines Makefiles genauso wie ein
Makro angesprochen. Damit kann man zum Beispiel eine Variable CXX setzen, die
den GNU-C++-Compiler enhalten soll:
Bash:
user@linux $
export CXX=g++
|
C-Shell:
user@linux $
setenv CXX g++
|
Die Umgebungs-Variable CXX steht damit im Makefile als Makro zur
Verfügung, was in der folgenden Regel ausgenutzt wird:
hello : hello.cpp
$(CXX) hello.cpp -o hello
|
|
Wenn man dasselbe Makro auf verschiedene Weisen definieren kann, ist es
wichtig, zu wissen, welches Makro im Falle eines Konfliktes
gewinnt. Makros werden nach folgender Reihenfolge aufgelöst:
-
vordefinierte Makros
-
Umgebungs-Variablen
-
interne Makros
-
Makros über die Kommandozeile
Die Priorität ist aufsteigend, das heisst Makros, die über die Kommandozeile
gesetzt werden, gewinnen immer.
|
Makros dürfen sich auf andere Makros beziehen. Betrachten wir dazu
folgendes Beispiel:
C_FILES = daddy.c mummy.c
H_FILES = children.h
SRC_FILES = $(C_FILES) $(H_FILES)
OBJ_FILES = daddy.o mummy.o
|
Das Mako SRC_FILES bezieht sich dabei auf die beiden Makros
C_FILES und H_FILES. Vergleichen wir jetzt das Makro C_FILES mit
OBJ_FILES, so stellen wir fest, dass sie bis auf die Endung (.c
bzw. .o) identisch sind. Damit wir nicht jedes Mal die OBJ_FILES
anpassen müssen, wenn sich C_FILES ändert, gibt es die
String-Substitution:
OBJ_FILES = $(C_FILES:.c=.o)
|
Damit hängt OBJ_FILES direkt von C_FILES ab, das heißt wenn in C_FILES eine
neue .c-Datei aufgenommen wird, müssen wir OBJ_FILES nicht ändern.
|
Neben den vordefinierten Makros gibt es eine Reihe von internen
Makros, die manche Regel vereinfachen können:
$@
|
Name des aktuellen Zieles
|
$?
|
Name der abhängigen Dateien, die neuer als das Ziel sind
|
$<
|
Name der abhängigen Dateien, die neuer als das Ziel sind. (mit Endung)
|
$*
|
Name der abhängigen Dateien, die neuer als das Ziel sind. (ohne Endung)
|
$%
|
Name der entsprechenden Objekt-Datei (.o), falls das Ziel eine Bibliothek ist.
|
Beispiel:
children: $(OBJ_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $@
|
In diesem Beispiel wird von make $@ durch den Namen des Ziels
(children) ersetzt.
Will man auf den Dateinamen oder Verzeichnisnamen zugreifen, kann man
dies (ausser bei $?) über die Modifier F (wie File) oder D (wie
Directory).
Beispiel:
|
|
|