Da die Kommandos in einer eigenen (Unter-) Shell ausgeführt werden,
stehen alle Möglichkeiten einer Shell wie Wildcards,
Ein-/Ausgabe-Umlenkung, ... zur Verfügung.
Wildcards (im Deutschen auch als Jokerzeichen bezeichnet) können
innerhalb von Kommandos verwendet werden, aber auch in den
Abhängigkeiten einer Regel auftauchen:
Leider haben diese Wildcards eine leicht unterschiedliche Bedeutung:
das erste Wildcard *.c innerhalb der Abhängigkeit wird von make
aufgelöst, das Wildcard im Kommando (lpr *.c) von der Shell. Während
bei der Shell die Hidden Files (das sind diejenige Dateien wie
zum Beispiel .bashrc, die mit einem . anfangen) nicht dazugehören,
ist hier das make-Kommando anderer Auffassung.
|
Jede Zeile im Aktions-Teil wird in einer eigenen Unter- Shell
gestartet. Will man mehrere Kommados auf einmal absetzen, werden diese
hintereinander aufgereiht und jeweils durch einen Strichpunkt (;)
voneinander getrennt:
Bei diesem Beispiel ist zu bedenken, dass das zweite Kommando (rm *.o)
auch dann ausgführt wird, wenn der erste Teil (cd obj) nicht geklappt
hat. Deswegen können Kommandos auch über && (UND) verknüpft werden:
Vorteil der UND-Verknüpfung: Schlägt das erste Kommando (cd obj) fehl,
wird das zweite Kommando (rm *.o) auf keinen Fall ausgeführt.
Man kann die Kommandos auch auf mehrere Zeilen verteilen, indem man
sie mit dem Backslash (\) als allerletztes Zeichen in der Zeile verbindet:
clean :
cd obj && \
rm *.o
|
Dabei ist darauf zu achten, dass der Backslash (\) wirklich das letzte
Zeichen in der Zeile ist -- er hebt nämlich die Bedeutung des nächsten
Zeichens (in diesem Fall das Zeilenende) auf. Steht hier ein
Leerzeichen, wird die (nicht vorhandene) Sonderbedeutung des
Leerzeichens aufgehoben.
|
Für komplexere Aufgaben kann man eigene Skripte schreiben oder aber
auch direkt im Makefile Programmierkonstrukte der (Bourne-)Shell
verwenden (das indent-Kommando formartiert C-Quellen nach den
GNU-C-Konventionen):
indent :
for file in $(C_FILES) ; do \
indent $$file ; \
done
|
Hier ist darauf zu achten, dass die einzelnen Konstrukte durch einen
Strichpunkt (;) voneinander getrennt werden. Erstrecken sich die
Kommandos über mehrere Zeilen, ist dies durch ein Backslash (\) am
Zeilenende zu kennzeichnen.
Der Zugriff auf Shell-interne Variablen wird durch ein zusätzliches
Dollar-Zeichen ($) bewerkstelligt (siehe $$file im Beispiel).
|
Wenn ein Kommando einen Fehlercode zurückliefert, wird make an dieser
Stelle abgebrochen. Dabei ist unter Unix alles, was einen Rückgabewert
ungleich 0 zurückliefert, ein Fehlercode.
Meistens ist dieses Verhalten ja gewünscht, zum Beispiel beim Kompilieren
(was der Normalfall sein dürfte). Aber es gibt auch Situationen, in dem
der Rückgabewert eines Kommandos egal ist, zum Beispiel in
clean :
- rm core
- rm *.o
|
ist es nicht weiter tragisch, wenn rm core nicht erfolgreich war
(weil es nicht existiert). Der Abbruch im Fehlerfall wird durch ein
vorangestelltes Minus (-) vermieden.
Manche Kommandos, wie zum Beispiel das rm-Kommando, können meist über die
Option -f gezwungen werden, fehlende Dateien oder andere Ungereimtheiten
zu ignorieren. Damit lässt sich das vorige Beispiel auch folgendermassen
formulieren:
clean :
rm -f core
rm -f *.o
|
|
Normalerweise wird jedes Kommando, das ausgeführt wird, vorher
ausgegeben. Mit einem vorangestellten @ kann man das unterdrücken:
statistic :
@ echo ""
@ echo " S T A T I S T I C S"
@ echo ""
@ echo " Lines Words Bytes Modul"
@ echo " --------------------------------"
@ wc ${SRC_FILES}
@ echo ""
|
Vor Allem beim echo-Kommando macht es keinen Sinn, dass vor der
eigentlichen Ausgabe das echo-Kommando samt Ausgabe-String ausgegeben
wird.
|
|