UNIX-Werkzeuge
==============
2. make
=======
Hilfsprogramm zur Verwaltung von veränderlichem Gut
für vergessliche und faule Unix-Anwender.
|
| next | back | 2017 - 1 | Fri Apr 7 14:46:39 CEST 2017 |
Historisches
------------
Verfasser: Stuart I. Feldman für UNIX 1978
Dialekte:
imake - Projektmanagment für portable Software
(X-Window-Syste)
gmake - GNU-Make, Erweiterung von make
nmake - AT&T Erweiterung von make
Abgeschrieben für Windows-Welt:
nmake - Microsoft
make - Borland
Einsatzgebiet von "make"
------------------------
Hauptaufgabe von "make" ist die Verwaltung von großen und kleinen Projek-
ten. Derartige Projekte bestehen in der Regel aus vielen kleinen Quelltex-
ten, die nach bestimmten Regeln zu Objekten zusammengefügt werden. Diese
Abhängigkeitsregeln können in "make" formalisiert aufgeschrieben werden.
Dadurch kann "make" dann jederzeit alle Operationen durchführen, die für
die Herstellung eines vollständigen, korrekt erzeugten Projekts notwendig
sind. "make" berücksichtigt dabei die Zeitstempel der jeweiligen Quellen
und Ziel-Objekte, so daß nur die minimal notwendigen Aktionen durch "make"
veranlaßt werden. m1
|
| next | back | 2017 - 2 | Fri Apr 7 14:46:39 CEST 2017 |
Arbeitsweise von "make"
-----------------------
"make" verlangt für seine Arbeit eine Beschreibungsdatei genannt "Makefile".
Dieses Makefile wird, wenn es nicht explizit spezifiziert wurde, in der
aktuellen Directory unter den Namen "makefile" und "Makefile" gesucht.
Achtung: Reihenfolge: 1. makefile
2. Makefile
m2
Mit der Option -f kann der Anwender das Makefile explizit bestimmen.
z.B.: make -f mein-makefile all
Bei der Arbeit protokolliert "make" alle Aktionen, die ausgeführt werden,
auf der Standardausgabe. Durch das Voranstellen von "@" vor ein Kommando
im Makefile wird die Ausgabe des entsprechenden Kommandos unterdrückt.
Derartig maskierte Kommandos werden durch die Option -n sichtbar, die
aber die Ausführung aller Kommandos unterdrückt.
Durch die Option -s wird "make" veranlaßt, keinerlei Ausgaben zu machen.
m3
Bei Fehlern (Exit-Kode eines ausgeführten Kommandos ungleich 0) bricht
"make" die Arbeit sofort ab. Dies kann durch das Voranstellen eines
Minuszeichen unmittelbar vor dem auszuführenden Kommando verhindert
werden. Das Minuszeichen kann auch beliebig mit "@" kombiniert werden.
Die Option -i bewirkt generell das Ignorieren von Fehlern.
m4
|
| next | back | 2017 - 3 | Fri Apr 7 14:46:39 CEST 2017 |
Was erzeugt "make"?
Beim Aufruf von "make" kann ein Objekt(Ziel) angegeben werden. Dann werden
alle Aktionen ausgeführt, die zur Bildung des angegeben Objekts notwendig
sind. Die Aktionen für die Bildung von Objekten (Zielen) werden im
Makefile beschrieben. Wird kein Ziel angegeben, so wird das erste zu
bildende Objekt, das im Makefile beschrieben ist, gebildet.
Das Makefile
------------
Das Makfile besteht im wesentlichen aus Regeln. Diese Regeln haben
folgende einfache Syntax:
<Make-Regel>::=
<Zielobjekt> ":" { <Quellobjekt> } [";" <Kommando> ] { <NL>
<TAB> <Kommando> } |
<Zielobjekt> "::" { <Quellobjekt> } [";" <Kommando> ] { <NL>
<TAB> <Kommando> }
<Zielobjekt> - ist das Objekt, das erzeugt werden soll
<Quellobjekt> - ist ein Objekt, von dem das Zielobjekt in irgendeiner
Form abhängig ist. Mehrere Quellobjekte sind zulässig.
Ein <NL>-Zeichen in der Liste der Quellobjekte muß
durch "\" maskiert werden. Die Abhängigkeitsinformationen
müssen in einer Zeile stehen.
<Kommando> - Kommandos deren Abarbeitung, für die Bildung des
Zielobjektes aus den Quellobjekten notwendig sind.
In der Regel Compilerläufe, Formatierungskommandos
und Kopieroperationen.
|
| next | back | 2017 - 4 | Fri Apr 7 14:46:39 CEST 2017 |
Ein Zielobjekt kann mehrfach auf der linke Seite auftreten (von
verschieden Quellobjekten abhängen), allerdings darf nur einmal
ein Kommandoteil folgen. Als Trennzeichen zwischen Zielobjekt und
Quellobjekt ist der ":" zu verwenden. Soll ein Zielobjekt mehrfach
durch verschiedene Kommandoteile gebildet werden, so sind Zielobjekt
und Quellobjekte durch "::" zu trennen.
Kommentare: Kommentare beginnen mit "#" und enden am Zeilenende. Sie
können anstelle von Make-Regeln oder am Ende jeder Zeile stehen.
Beispiel:
c_sock: # Client erzeugen
c_sock: c_sock.c inet.h
gcc -c c_sock.c
gcc -o c_sock c_sock.o ${LIB} ${LIB1}
Tabulator!!!!!!!!!!!
libcom:: # 1.LIB-Modul erzeugen
libcom:: c_sock.c inet.h
gcc -c c_sock.c
ar -r $@ c_sock.o
libcom:: # 2.LIB-Modul erzeugen
libcom:: s_sock.c inet.h
gcc -c s_sock.c
ar -r $@ s_sock.o
Tabulator!!!!!!!!!!!
m5
|
| next | back | 2017 - 5 | Fri Apr 7 14:46:39 CEST 2017 |
Es gibt zwei Philosophien für das Aussehen des ersten Ziels innerhalb
des Makefiles:
1. Die Regel:
all: <Liste aller zu bildenden Objekte des Porjekts>
2. Die Regel:
help: ;@egrep '^[^:;=.]*::?[ ]*#' [mM]akefile
und alle Startregeln ordentlich Kommentieren.
xyx: # erzeugen von xyz
m6
Makro-Mechanismus
-----------------
"make" unterstützt innerhalb des Makefiles einen Makro-Mechanismus zur
einfacheren und übersichtlicheren Schreibweise des Files.
<Makrodefinition>::= <Makroname> "=" <String>
Makrodefinitionen können vor und zwischen den Make-Regeln innerhalb des
Makefiles auftreten. Der Makroname besteht aus Buchstaben, Ziffern und
Unterstrichen.
|
| next | back | 2017 - 6 | Fri Apr 7 14:46:39 CEST 2017 |
Der Zugriff auf ein Makro kann durch:
"$("<Makroname>")"
oder
"${"<Makroname>"}"
erfolgen.
Bei der Definition von Makros ist der Zugriff auf vorher definierte Makros
erlaubt.
Im Makefile kann auf folgende 4 Makroarten zugegriffen werden:
- im Makefile vom Nutzer definierte Makros
- Umgebungsvariablen der Shell können ebenfalls innerhalb des Makefiles
wie Makros benutzt werden.
- beim Aufruf von "make" können in der Kommandozeile mittels
Schlüsselwortparameter Makros definiert werden, z.B.
make CC=cc all
- intern vordefinierte Makros:
env - make -p -f /dev/null | egrep -e "^[a-zA-Z_-]* ="
m7/int-vor-make
MAKE = $(MAKE_COMMAND)
COFLAGS =
CO = co
FC = f77
CC = cc
CXX = g++
|
| next | back | 2017 - 7 | Fri Apr 7 14:46:39 CEST 2017 |
AR = ar
CWEAVE = cweave
YACC = yacc
MAKEFLAGS = p
OUTPUT_OPTION = -o $@
TANGLE = tangle
LD = ld
MFLAGS = -p
GET = get
PC = pc
AS = as
TEX = tex
LINT = lint
RM = rm -f
WEAVE = weave
CPP = $(CC) -E
LEX = lex
ARFLAGS = rv
CTANGLE = ctangle
MAKEINFO = makeinfo
Reihenfolge der Benutzung der Makros im Makefile durch "make":
ohne -e Option mit -e Option
1. Schlüsselwortparameter 1. Schlüsselwortparameter
2. Definitionen im Makefile 2. Umgebungsvariable
3. Umgebungsvariable 3. Definitionen im Makefile
4. intern vordefinierte 4. intern vordefinierte
Makros Makros
m7
|
| next | back | 2017 - 8 | Fri Apr 7 14:46:39 CEST 2017 |
Interne Makros:
$@, $(@D), $(@F)
Name des ungültigen Zielobjektes (das Objekt, das erzeugt
werden soll). $(@D) steht für den Path-Name und $(@F) für den Filenamen.
$?
Liste der Namen aller neuen Quellen, neuer als das Zielobjekt
$<, $(<D), $(<F)
Name des transformierbaren Objektes (das Objekt, das übersetzt
werden soll). $(<D) steht für den Path-Name und $(<F) für den Filenamen.
$*, $(*D), $(*F)
Name des ungültigen Zielobjektes ohne Suffix, das die Transformation
ursprünglich ausgelöst hat.
$(*D) steht für den Path-Name und $(*F) für den Filenamen.
m8
$%, $(%D), $(%F)
Wenn das Zielobjekt eine Bibliothek ist (lib.a(file.o)), so beschreibt
$% die Datei file.o und $@ die Bibliothek lib.a.
$(%D) steht für den Path-Name und $(%F) für den Filenamen der
Datei.
m9
|
| next | back | 2017 - 9 | Fri Apr 7 14:46:39 CEST 2017 |
Suffixregeln
------------
"make" hat eingebaute Abhängigkeitsregeln - Suffixregeln, die es für die
Bildung von Objekten benutzt, wenn keine expliziten Bildungsvorschriften für
ein Ojekt angegeben sind. Man kann diese vollständig mittels:
env - make -pf /dev/null | sed -e "/^#/d" -e "/^$/d" | more
besichtigen.
Mit
env - make -pf /dev/null | sed -e "/^#/d" -e "/^$/d" | grep .SUFFIXES:
m9/get-sufix
erhält man alle intern unterstützten Suffixe
.SUFFIXES : .out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S \
.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch \
.web .sh .elc .el
Für die Suffixe sind dann auch noch zusätzliche Bildungsregeln definiert.
Mittels
#!/bin/sh
env - make -pf /dev/null | awk ' /^\.[a-zA-Z]\.[a-zA-Z]:/ { \
print $0 ; getline ; getline; \
getline; getline; \
getline; print $0 ; \
getline; print $0 ; \
} ' m9/getreg2
erhält man eine kurze Übersicht über die internen Bildungsregeln.
|
| next | back | 2017 - 10 | Fri Apr 7 14:46:39 CEST 2017 |
.c.o: $(COMPILE.c) $(OUTPUT_OPTION) $< .y.c: $(YACC.y) $< mv -f y.tab.c $@ .s.o: $(COMPILE.s) -o $@ $< .F.f: $(PREPROCESS.F) $(OUTPUT_OPTION) $< .S.s: $(PREPROCESS.S) $< > $@ .F.o: $(COMPILE.F) $(OUTPUT_OPTION) $< .p.o: $(COMPILE.p) $(OUTPUT_OPTION) $< .r.f: $(PREPROCESS.r) $(OUTPUT_OPTION) $< .l.r: $(LEX.l) $< > $@ mv -f lex.yy.r $@ .r.o: $(COMPILE.r) $(OUTPUT_OPTION) $< .C.o: $(COMPILE.C) $(OUTPUT_OPTION) $< .l.c: @$(RM) $@ $(LEX.l) $< > $@ .f.o: $(COMPILE.f) $(OUTPUT_OPTION) $< |
| next | back | 2017 - 11 | Fri Apr 7 14:46:39 CEST 2017 |
Selbstverständlich enthält "make" auch interne Regeln zum Bilden von
ausführbaren Objekten direkt aus dem Quelltext ohne zwischendurch
Objektmodule zu bilden:
env - make -pf /dev/null | awk ' /^\.[a-zA-Z]:/ { print $0 ; \
getline ; \
getline ; \
getline ; \
getline ; print $0 ; \
getline ; print $0 ; \
} '
m9/getreg
z.B.:
.c:
# commands to execute (built-in):
$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@
.s:
# commands to execute (built-in):
$(LINK.s) $^ $(LOADLIBES) $(LDLIBS) -o $@
.F:
# commands to execute (built-in):
$(LINK.F) $^ $(LOADLIBES) $(LDLIBS) -o $@
.f:
# commands to execute (built-in):
$(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@
.o:
# commands to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
| next | back | 2017 - 12 | Fri Apr 7 14:46:39 CEST 2017 |
.p:
# commands to execute (built-in):
$(LINK.p) $^ $(LOADLIBES) $(LDLIBS) -o $@
.r:
# commands to execute (built-in):
$(LINK.r) $^ $(LOADLIBES) $(LDLIBS) -o $@
.C:
# commands to execute (built-in):
$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $@
.S:
# commands to execute (built-in):
$(LINK.S) $^ $(LOADLIBES) $(LDLIBS) -o $@
.o - Objektmodule
.c - C-Quelltext
.f - Fortran-Quelle
.s - Assembler-Text
.l - lex-Quelltext
.y - yacc-Quelltext
.h - Heder-Dateien
.sh - Shellscript
|
| next | back | 2017 - 13 | Fri Apr 7 14:46:39 CEST 2017 |
Der Anwender kann aber auch zusätzliche eigene Suffix-Regeln definieren:
.SUFFIXES:.o.c.s
Hierdurch wird festgelegt, daß im aktuellen Makefile nur Abhängigkeiten
für Objektmodule, C-Quelltexte und Assemblertexte existieren.
Dabei müssen dann auch noch Bildungsregeln festgelegt werden.
Hierfür gibt es folgende Syntax:
"."<von>"."<nach>":"
<TAB> <Kommando> # für spezielle Sachverhalte
bzw.
"."<von>":"
<TAB> <Kommando> # für das Erzeugen von fertigen Objekten
.c:
$(CC) $(CFLAGS) $< $(LDFLAGS) -o $@
.c.o:
$(CC) $(CFLAGS) -O2 -c -o $@ $<
Durch
.SUFFIXES:
werden die vordefinierten Suffixregeln gelöscht.
m10
|
| next | back | 2017 - 14 | Fri Apr 7 14:46:39 CEST 2017 |
Spezielle Zielangaben:
.SUFFIXES: - Definition neuer Suffixe
.DEFAULT: - Das Scheinobjekt .DEFAULT wird immer dann benutzt,
wenn "make" ein Objekt erzeugen soll und es keine Regel
für die Bildung diese Objekts gibt. Ohne das
Scheinobjekt .DEFAULT wird "make" abgebrochen.
m11
.DEFAULT:
cp ../m1/$@ .
- Definition des Verhaltens, wenn benötigte Objekte
nicht vorhanden sind
.IGNORE: - Fehler ignorieren
.SILENT: - Ausgabe auf Standardausgabe abschalten
m12
.PRECIOUS: - Definition von Zielobjekten, die bei Fehlern
nicht gelöscht werden (für Bibliotheken).
include-Anweisung:
include <Dateiname>
Rekursiver Make-Aufruf mit pseudo-Ziel
Make
|
| next | back | 2017 - 15 | Fri Apr 7 14:46:39 CEST 2017 |
Syntax: make [Optionen] [Target] ...
Optionen:
-b, -m Aus Kompatibilitätsgründen ignoriert..
Alte Beschreibungsdateien
-C VERZEICHNIS, --directory=VERZEICHNIS
Wechsle in das VERZEICHNIS bevor etwas anderes
ausgeführt wird.
-d Gebe viele Informationen zur Fehlersuche aus.
--debug[=FLAGS] Gebe verschiedene Arten von Debug-Information
aus.
-e, --environment-overrides
Umgebungsvariablen überschreiben "make"-
Steuerdateien.
-f DATEI, --file=DATEI, --makefile=DATEI
Lese die Datei DATEI als "make"-Steuerdatei.
-h, --help Gib diese Nachricht aus und beende.
-i, --ignore-errors Ignoriere Fehler in den Kommandos.
-I VERZEICHNIS, --include-dir=VERZEICHNIS
Durchsuche das VERZEICHNIS nach eingebundenen
"make"-Steuerdateien.
-j [N], --jobs[=N] Erlaube N Jobs gleichzeitig; unbegrenzte Anzahl
von Jobs ohne Argument..
-k, --keep-going Weiterlaufen, auch wenn einige Targets nicht
erzeugt werden konnten.
-l [N], --load-average[=N], --max-load[=N]
Nur bei Belastung unterhalb N mehrere Prozesse
starten.
|
| next | back | 2017 - 16 | Fri Apr 7 14:46:39 CEST 2017 |
-n, --just-print, --dry-run, --recon
Kommandos nur anzeigen, nicht ausführen.
-o DATEI, --old-file=DATEI, --assume-old=DATEI
Betrachte DATEI als sehr alt und erzeuge sie
nicht neu.
-p, --print-data-base Gib die interne Datenbank von "make" aus.
-q, --question Keine Kommandos ausführen; der Exit-Status gibt
an, ob die Dateien aktuell sind.
-r, --no-builtin-rules Deaktivieren der eingebauten impliziten Regeln.
-R, --no-builtin-variables Deaktivieren der eingebauten Variablenbe-
legungen..
-s, --silent, --quiet Gebe die Kommandos nicht aus.
-S, --no-keep-going, --stop
Schaltet -k ab..
-t, --touch Die Targets werden nur als aktualisiert
markiert,
nicht tatsächlich erneuert.
-v, --version Gib die Versionsnummer von "make" aus und
beende.
-w, --print-directory Gib das aktuelle Verzeichnis aus.
--no-print-directory Schalte -w aus, selbst wenn es implizit
eingeschaltet wurde.
-W DATEI, --what-if=DATEI, --new-file=DATEI, --assume-new=DATEI
Betrachte die DATEI stets als neu.
--warn-undefined-variables Gib eine Warnung aus, wenn eine undefinierte
Variable referenziert wird.
|
| back | 2017 - 17 | Fri Apr 7 14:46:39 CEST 2017 |