0. Was ist make

Werbung
top;¬
make
0.
1.
2.
3.
;make.rtfd;0;¬Was ist make ?
;make.rtfd;1;¬Wie funktioniert make ?
;make.rtfd;2;¬Wie kann make benutzt werden ?
;make.rtfd;3;¬Was kann make sonst noch ?
3.1 ;make.rtfd;3.1;¬Implizite Regeln / .SUFFIXES
3.2 ;make.rtfd;3.2;¬Variablen
3.3 ;make.rtfd;3.3;¬Kommandozeilenoptionen
3.4 ;make.rtfd;3.4;¬Miscellaneous
0;¬0.
Was ist make ?
In einem Programmierprojekt mit mehreren Dateien, kann man leicht die šbersicht daröber verlieren,
welche Dateien aus welchen generiert wurden, d.h. welche Dateien aktualisiert werden mössen wenn sich
an einigen der Quellen etwas geÙndert hat. Das Programm make stellt einen einfachen Mechanismus zur
Verfögung diese AbhÙngigkeiten zu beschreiben, inklusive der Kommandofolgen die nðtig sind, um eine
Datei aus ihren Quellen zu generieren. Ein einfacher Aufruf des Kommandos make föhrt dann dazu, dass
alle Dateien mit minimalem Aufwand auf den aktuellen Stand gebracht, bzw. erzeugt werden.
1;¬1.
Wie funktioniert make ?
Im wesentlichen sucht make den Namen einer benðtigten Datei (ein target) aus der Beschreibung der
AbhÙngigkeiten (dem makefile) heraus und untersucht, ob alle Dateien von denen das target abhÙngt
existieren und auf dem aktuellen Stand sind. Ist das der Fall, wird das target mit Hilfe der im makefile daför
angegebenen Kommandofolgen erzeugt, sofern das target Ùlter ist als mindestens eine seiner Quellen
(genauer: wenn die modification-time einer Quelle grðsser ist als die des targets). Man kðnnte auch sagen:
Das makefile definiert einen Graphen von AbhÙngigkeiten und make macht eine depth-first search
(Tiefensuche ?) um herauszufinden was getan werden muss.
abb1;¬make.eps ¬
Abb. 1: Beispiel för einen Graphen von AbhÙngigkeiten den ein makefile definieren kðnnte.
2;¬2.
Wie kann make benutzt werden ?
Man erstellt ein makefile und föhrt dann jedesmal das Kommando make aus, wenn man mðchte, dass
eines der im makefile definierten targets auf den neuesten Stand gebracht wird. Das makefile för das
Projekt aus ;make.rtfd;abb1;¬Abb. 1 kðnnte z.B. folgendermassen aussehen:
# makefile
all:
Main.class doc.html
Main.class: Hello.class Main.java
<tab>
javac Main.java
Hello.class:
<tab>
Hello.java
javac Hello.java
doc.html:
<tab>
<tab>
Main.java Hello.java
javadoc Main.java Hello.java
test -e doc.html || ln -s tree.html doc.html
Die 3. Zeile z.B. besagt, dass das target "Main.class" von den Dateien "Main.java" und "Hello.class"
abhÙngt. Sind diese auf dem neuesten Stand kann "Main.class" durch den Befehl "javac Main.java"
erzeugt werden. (Fussnote) Die "<tab>" dörfen natörlich nicht im makefile stehen, sie sollen nur
verdeutlichen, dass es notwendig ist, dass die Zeilen mit den Kommandos mit einem Tab beginnen.
För das target "all" sind keine Kommandos angegeben und es hat auch keine korrespondierende Datei, es
ist aber "virtuell" bis zum Ende eines einzelnen make vorhanden, sobald "Main.class" und "doc.html"
aktualisiert sind. Das Zeichen '#' leitet einen Kommentar ein der bis zum Zeilenende geht.
Ist der Dateiname des makefile "makefile" oder "Makefile" so reicht nun ein einfacher Kommandoaufruf um
alle för das target "all" erforderlichen Operationen durchzuföhren:
plopp stephan 21: make
javac Hello.java
javac Main.java
javadoc Main.java Hello.java
Generating package.html
Generating documentation for class Main
Generating documentation for class Hello
Generating index
Sorting 3 items...done
Generating tree
test -e doc.html || ln -s tree.html doc.html
plopp stephan 22: make
make: Nothing to be done for `all'.
plopp stephan 23: rm doc.html
plopp stephan 24: make
javadoc Main.java Hello.java
Generating package.html
Generating documentation for class Main
Generating documentation for class Hello
Generating index
Sorting 3 items...done
Generating tree
test -e doc.html || ln -s tree.html doc.html
Ruft man make mit einem oder vielen targets als Argument auf, so werden diese targets und die von
denen sie abhÙngen aktualisiert, ohne ein target auf der Kommandozeile nimmt make einfach das erste
das im makefile vorkommt (und das nicht mit einem '.' beginnt). Unser makefile wird daher um folgende
Zeilen erweitert:
clean:
rm -f *.class *.html
Die Verwendung von '*' und '?' ist auch bei targets und dependents mðglich und hat dort die gleiche
Bedeutung wie in einer shell. Hier föhrt der Aufruf "make clean" dazu, dass alle Dateien mit den Endungen
.html oder .class gelðscht werden!
3;¬3.
Was kann make sonst noch ?
3.1;¬3.1 Implizite Regeln / .SUFFIXES
In unserem Beispiel werden .class-Dateien erzeugt, indem die entsprechende .java-Datei durch einen
Aufruf von "javac" kompiliert wird. Mit make kann man dies auch als allgemeine, implizite Regel
formulieren:
# makefile 3.1
# implicit rules, .SUFFIXES
# $<
.SUFFIXES:
.SUFFIXES: .class .java
.java.class:
javac $<
all:
Main.class doc.html
Main.class:
Hello.class
doc.html:
Main.java Hello.java
javadoc Main.java Hello.java
test -e doc.html || ln -s tree.html doc.html
clean:
rm -f *.class *.html
Die Zeichenfolge "$<" ist nur göltig bei einer impliziten Regel und steht för den Namen der Datei die die
jeweilige Ausföhrung verursacht hat. Die erste Zeile mit ".SUFFIXES" lðscht bereits definierte implizite
Regeln (Einige der vordefinierten Regeln findet man hier:;default.rules.txt;;¬).
3.2;¬3.2 Variablen
Um die Struktur des makefile noch ein wenig aufgerÙumter zu gestalten und die Wartung zu vereinfachen
kann man Variablen (manchmal macros genannt) vereinbaren:
#
#
#
#
makefile 3.2
macros, $<one-char>/$(<many-chars>)
special: $$, $@, $?, $*, $<
make JAVAC=jikes
targets=Main.class doc.$H
JAVAC=javac
JCFLAGS=
JAVADOC=javadoc
JDFLAGS=
H=html
# Suffix for html-files: htm on Windows, html on Unix
.SUFFIXES:
.SUFFIXES: .class .java
.java.class:
# delete current list of suffixes
$(JAVAC) $(JCFLAGS) $<
all:
$(targets)
Main.class:
Hello.class
doc.$H:
Main.java Hello.java
$(JAVADOC) $(JDFLAGS) Main.java Hello.java
test -e $@ || ln -s tree.html $@
clean:
rm -f *.class *.html
ZusÙtzlich kann man auch Variablen auf der Kommandozeile von make definieren, welche dann im
makefile eventuell vorhandene Definitionen öberschreiben.
Die Variablen $$, $@, $?, $*, $< haben folgende Sonderbedeutungen:
$$: Das Zeichen "$"
$@: Das target das gerade 'gemacht' wird
$?: Der String von dependents die jönger als das target sind
Nur in impliziten Regeln:
$*: Das gemeinsame Prefix von target und dependent
$<: Der Name des dependent der die Ausföhrung der Regel verursacht hat.
Ausserdem sind noch ein paar Variablen in den ;default.rules.txt;;¬default-rules vordefiniert.
3.3;¬3.3 Kommandozeilenoptionen
Folgende Kommandozeilenoptionen beeinflussen die Ausföhrung von make
-f <datei>
<datei> wird statt "makefile" als makefile genommen.
-i
Ein Fehler in der Ausföhrung eines Kommandos föhrt nicht dazu, dass make beendet wird.
Dies ist Ùquivalent zur Angabe von ".IGNORE:" im makefile.
Alternativ kann dies auch durch ein föhrendes "-" för einzelne Kommandozeilen festgelegt werden.
-k
Wie '-i' nur wird nicht versucht targets zu erzeugen die von dem fehlgeschlagenen abhÙngen.
-n
Die Kommandos werden nicht wirklich ausgeföhrt (Testmodus).
-q
Es wird nichts ausgeföhrt oder ausgegeben. Ein exitcode von 0 bedeutet, dass die angegebenen
targets alle aktuell sind (Question-mode).
-j
Erzeuge targets 'parallel' wenn sie nicht voneinander abhÙngen.
-s
Es werden keine Kommandozeilen vor der Ausföhrung ausgegeben.
Dies ist Ùquivalent zur Angabe von ".SILENT:" im makefile.
Alternativ kann dies auch durch ein föhrendes "@" för einzelne Kommandozeilen festgelegt werden.
3.4;¬3.4 Miscellaneous
Ein target kann auch mehrmals angegeben werden. Dabei ist zwischen zwei verschiedenen FÙllen zu
unterscheiden:
a) Maximal bei einer Angabe dieses targets stehen auch Kommandos dabei, dann werden diese
Kommandos ausgeföhrt wenn mindestens einer der dependents in irgendeiner dieser Zeilen jönger als das
target ist.
b) Stehen hinter jeder Angabe dieses targets zwei Doppelpunkte "::", so kann jede Angabe auch
zugehðrige Kommandos besitzen. Diese werden aber nur ausgeföhrt wen einer der zu dieser Angabe
gehðrenden dependents jönger ist.
Die Angabe von "include <datei>" im makefile föhrt dazu, dass <datei> an dieser Stelle in das makefile
eingefögt und mit verarbeitet wird.
Das Zeichen "\" direkt am Zeilenende föhrt dazu, dass das Zeilenende ignoriert wird, so dass man diese
Zeile in der nÙchsten fortsetzen kann.
Disclaimer: Diese kurze Einföhrung in make hat nicht den Anspruch in irgendeiner Weise vollstÙndig zu
sein oder ein spezielles make zu beschreiben. Ich garantiere nicht för irgendeine Form von 'Richtigkeit' der
gemachten Angaben. Wer es ganz genau wissen will muss die jeweilige Dokumentation schon selbst zu
Rate ziehen.
Herunterladen