Mit Programmen, Diplomarbeiten und anderen Projekten, bei denen aus mehreren Dateien letzten Endes eine entstehen soll, ist es wie mit Handarbeiten: Für den Topflappen nimmt man noch das Nadelspiel zur Hand, aber wenn´s an den Pullover geht, gibt es nicht umsonst Strickmaschinen – wie make.
Das Tool make wurde ursprünglich von Stuart I. Feldman entwickelt, um dem programmschaffenden Volke ein effektives Werkzeug zur Generierung von Programmen an die Hand zu geben. Dass dies sehr gut gelungen ist, belegt wohl die Tatsache, dass das ursprünglich unter und für Unix geschriebene make auf die meisten heute existierenden Plattformen portiert wurde. Sein Einsatzgebiet beschränkt sich aber schon lange nicht mehr ausschließlich auf die Programmierung.
Was ist make?
Die Standardsituation: Eine Programmiererin abeitet an einem beträchtlichen Haufen Quelldateien, die übersetzt und schließlich zu einem ausführbaren Programm zusammen gelinkt werden müssen. Jedes Mal, wenn eine Änderung an einer Datei vorgenommen wird, muss diese Datei neu übersetzt und dann das ganze Programm erneut gelinkt werden.
Dabei wird sehr schnell ein bedeutendes Problem sichtbar: Die Programmiererin muss sich jeweils alle Dateien merken, die sie modifiziert hat, und zweitens sollte sie auch alle Dateien im Kopf haben, die von diesen modifizierten Dateien abhängig sind.
Genau hier setzt make an. Das make-Tool kompiliert alle modifizierten Dateien sowie alle, die von diesen abhängig sind, und linkt dann alles fein säuberlich zum ausführbaren “Executable” zusammen. Um dieses Wunder zu vollbringen, folgt make haargenau den Anweisungen, die in einer Datei mit dem Namen Makefile festgehalten sind. Praktisch alle Programme, deren Quellcode veröffentlicht ist, und die z.B. auf dem heimischen Rechner übersetzt werden können, werden mittels Makefiles organisiert. Oft hat man dann nicht mehr zu tun, als den Befehl make einzutippen, einen Kaffee trinken zu gehen und dann das frisch übersetzte Programm zu starten.
Wie funktioniert make?
Das Prinzip, nach dem make arbeitet, ist recht einfach. Um die Dateien zu bestimmen, welche neu zu übersetzen sind, schaut make nach, ob schon eine Version des zu erzeugenden Programms existiert. Wenn nicht, werden alle Dateien nach den Anweisungen im Makefile kompiliert. Existiert schon eine alte Programmversion, dann nimmt sich make den “Timestamp” (“Zeitstempel”) dieser Version her und vergleicht ihn mit den Timestamps aller Dateien, die in der Abhängigkeitszeile angegeben sind. Ist der Timestamp einer solchen Datei aktueller als jener der alten Programmversion, dann werden diese Datei und alle von ihr abhängigen Dateien neu kompiliert.
Ein Makefile
Zur besseren Anschauung soll ein kleines, aus den Dateien foo.c und bar.c bestehendes Programm namens foo übersetzt werden.
gcc -c bar.c
übersetzt den C-Code in der Datei bar.c in eine Objektdatei namens bar.o. Dasselbe gilt für foo.c:
gcc -c foo.c
Schließlich werden die beiden erzeugten Objektdateien zu einem ausführbaren Programm namens foo zusammengelinkt:
gcc -o foo foo.o bar.o
Listing 1
Das erste Makefile
1: # Makefile 2: 3: foo: foo.o bar.o 4: gcc -o foo foo.o bar.o 5: 6: foo.o: foo.c 7: gcc -c foo.c 8: 9: bar.o: bar.c 10: gcc -c bar.c
In einem Makefile würde man das ungefähr wie in Listing 1 formulieren. Es beginnt mit einem Kommentar in der ersten Zeile: Ein # bedeutet make – wie unter Linux u.a. Unixbetriebssysteme üblich –, sich um den in der Zeile folgenden Text nicht zu kümmern. In Zeile 3 folgt eine Target/Dependency Line oder auf deutsch eine Abhängigkeitsdarstellung. Der dazu gehörige Anweisungsblock, hier nur eine Zeile, folgt in Zeile 4. Eine solche Kombination von Abhängigkeitsdarstellung und Anweisungsblock folgt dann nochmal in den Zeilen 6, 7 sowie 9 und 10.
Eine Target/Dependency Line definiert ein Ziel (“target”) für den darauf folgenden Anweisungsblock und gibt durch einen Doppelpunkt getrennt die Dateien an, aus welchen das Target erzeugt werden soll, also, von welchen Dateien es abhängig (“dependent”) ist. Allgemein formuliert sieht eine Target/Dependency Line so aus:
ziel: objekt1 objekt2 ...
Ein Programm kann aus einer ganz erheblichen Menge Quelldateien bestehen. Wenn man die alle in eine Zeile schreiben würde, verliert man schnell den Überblick. Deshalb darf eine solche Erklärung über mehrere Zeilen verteilt werden. Dazu setzt man ans Ende jeder Zeile das Fortsetzungszeichen \:
ziel: objekt 1 \
objekt 2 \
... \
objekt n
Im Makefile aus Listing 1 sind, neben foo, zwei weitere Ziele angegeben, nämlich foo.o und bar.o. Per Voreinstellung nimmt sich make immer der ersten Target/Dependency Line an. Wünscht man einmal ein anderes Ziel, dann ist es möglich, make dies als Kommandozeilenoption mit auf den Weg zu geben:
make foo.o
Dieser Befehl weist make an, sich nur um das Ziel foo.o zu kümmern und alle weiteren Ziele außer Acht zu lassen.
Auf die Aufzählung der Abhängigkeiten folgt ein Anweisungsblock, der aus beliebig vielen, untereinander geschriebenen und jeweils mit einem Tabulator eingerückten Anweisungen bestehen kann:
ziel: objekt1 objekt2 ...
anweisung1
anweisung2
...
Hat man trotzdem das dringende Bedürfnis, alle Anweisungen in eine Zeile zu schreiben, steht dem nichts im Wege – vorausgesetzt, man trennt die einzelnen Befehle durch Semikolons:
ziel: objekt1 objekt2 ...
anweisung1 ; anweisung2 ; ...
Einen Tabulator zum Einrücken der Anweisung zu verwenden ist hierbei genauso zwingend wie das Einrücken selbst. Sollte make mal streiken, liegt es zu 90 Prozent an einem vergessenen Tabulator.
Pseudotargets
Ein häufiger Sonderfall ist es, wenn eine Abhängigkeitsdarstellung keine Dependencies enthält, d.h., wenn nach dem Doppelpunkt keine Dateien stehen. Dies bezeichnet man als Pseudotargets. So etwas eignet sich z.B. hervorragend, um kleine Aufräumaktionen zu definieren:
cleanup:
rm datei1
rm datei2
...
Nun kann man mit der Anweisung
make cleanup
nach einem Kompiliervorgang schön sauber machen, indem man die Dateien (im Beispiel datei1 und datei2 genannt), die man nicht mehr braucht, von make löschen lässt. Ein Pseudotarget wird immer ausgeführt, denn es gibt ja keine Dateien mit Timestamps, an denen sich make orientieren könnte. Viele Pseudotargets sind bereits von make vordefiniert und können als Schalter für bestimmte Einstellungen verwendet werden. Dies bezeichnet man als “Predefined Pseudotargets”. So weist z.B.
.SILENT:
make an, die Kommandos, die es gerade ausführt, nicht explizit auf dem Bildschirm auszugeben. Dies ist äquivalent zur Kommandozeilenoption make -s .
Predefined Pseudotargets beginnen mit einem Punkt (.), werden immer groß geschrieben und stehen der Fairness wegen am Anfang eines Makefiles – am Anfang deswegen, damit man mit einem Blick erfassen kann, welche Pseudotargets verwendet werden. Es kann einen noch etwas Unerfahrenen in den Wahnsinn treiben, wenn beim Kompilieren keine Ausschrift auf dem Monitor erscheint, nur weil irgendwo im Makefile die Anweisung .SILENT: “versteckt” ist.
Suffix-Regeln
Bei allen Betriebsystemen, so auch unter Linux, existieren gewisse Konventionen, was Dateiendungen angeht. Das bedeutet z.B., dass der Name von Dateien, die C-Quelltexte enthalten, auf .c enden muss, Assemblerquelltexte auf .s und LaTeX-Dateien auf .tex. Dies ermöglicht es nicht nur dem geübten Auge, von der Dateiendung auf den Inhalt zu schließen, sondern auch KDE und z.B. make.
Intern besitzt make eine Datenbank, in der bestimmten Dateiendungen bestimmte Befehlsfolgen zugeordnet sind. make weiß auch sonst noch Einiges, z.B. dass beim Kompilieren einer C-Quelltextdatei (.c) eine Objektdatei (.o) entsteht, bzw. umgekehrt, dass eine C-Quelldatei existieren muss, wenn eine Objektdatei gebraucht wird.
make registriert also, wenn Objektdateien in einer Abhängigkeitserklärung stehen und geht nach einem Blick in die eigene Datenbank automatisch davon aus, dass die dazugehörigen C-Quelltext-Dateien vorhanden sind und übersetzt werden können. Unser Makefile aus Listing 1 lässt sich somit auch etwas kürzer formulieren (Listing 2).
Listing 2
Es geht auch kürzer…
# Makefile
foo: foo.o bar.o
gcc -o foo foo.o bar.o
Die C-Quelltext-Dateien brauchen nun mit keiner Silbe mehr erwähnt werden. make registriert die Objektdateien in der Target/Dependency Line, und der Rest passiert automatisch.
Welche Suffix-Regeln die auf dem aktuellen System ansässige make-Version kennt, erfährt man nach Eingabe des Befehls
make -p > make_default
Existiert für eine bestimmte Dateiendung noch keine Suffix-Regel oder möchte man eigentlich etwas ganz anderes, als der vorgesehene Befehl tun würde, ist es natürlich auch möglich, seine eigenen Suffix-Regeln zu definieren. Eine Regel ist dabei grundsätzlich folgendermaßen aufgebaut:
.von.nach
anweisung1
anweisung2
...
Als Beispiel erweitern wir das Makefile aus Listing 2 um eine Definition für .c.o (Listing 3). Wir sagen make also, was es tun soll, wenn es Objektdateien in Abhängigkeitsbeschreibungen findet, aber keine C-Quelltextdateien explizit angegeben wurden.
Listing 3
Was passiert mit den Objektdateien?
# Makefile
foo: foo.o bar.o
gcc -o foo foo.o bar.o
.c.o
gcc -c $<
Das “Von” ist in diesem Falle eine C-Datei (.c), das “Nach” eine Objektdatei (.o), und die Anweisung zwar nicht sonderlich originell aber wirkungsvoll gcc -c $<. Bei $< handelt es sich um ein sogenanntes internes Makro. Es enthält jeweils den Namen des dependend file, also der Datei, die in der Target/Dependency Line hinter dem Doppelpunkt steht (hier das jeweilige .c-File). Dabei darf $< nur bei der Definition von Suffix-Regeln verwendet werden – warum und wieso steht im nächsten Abschnitt.
Findet make nun die Objektdatei foo.o in der Abhängigkeitsbeschreibung, schaut es in seine interne Datenbank und findet heraus, dass da, wo eine Objektdatei entstehen soll, irgendwo eine C-Datei rumstehen muss. Wie sich der Übergang von C-Datei zu Objektdatei vollziehen soll, beschreibt die Anweisung in Listing 3.
Makros
make kennt natürlich auch Makros. Dabei sind grundsätzlich drei Arten zu unterscheiden: zum Ersten vom Benutzer definierte Makros, zum Zweiten von make mit Werten vorbelegte Makros, die aber vom Nutzer geändert werden können, und zum Dritten Makros, die von make situationsbedingt mit Werten belegt werden, vom Nutzer aber nicht geändert werden können.
Beginnen wollen wir hier mit den Eigenschaften, die alle drei gemeinsam haben. Da wäre z.B. die Konvention, dass Makros ausschließlich mit Großbuchstaben bezeichnet werden:
NAME = blah blah
Will man auf die Makros zugreifen, stellt man ein $-Zeichen voran und fasst, wenn der Makroname aus mehr als einem Zeichen besteht, den Namen in Klammern:
... $(NAME) ...
Dabei ist es Ihrem guten Geschmack überlassen, ob Sie runde () oder geschweifte Klammern {} verwenden. Es ist also auch möglich,
... ${NAME} ...
zu schreiben. make macht mit solchen Makros nichts weiter, als sie an der Stelle, an der sie stehen, zu expandieren, sprich: durch ihren (aktuellen) Inhalt zu ersetzen. Wie unser Makefile mit ein paar Makros aussieht, zeigt Listing 4.
Listing 4
Makefile mit Makros
ZIEL = foo
OBJS = foo.o bar.o
OPT = -o
CC = gcc
$(ZIEL): $(OBJS)
$(CC) $(OPT) $(ZIEL) $(OBJS)
Hier haben wir vier Makros definiert, nämlich ZIEL, OBJS, OPT und CC. make expandiert diese in den beiden Zeilen darunter, so dass dort nichts Anderes steht als die Target/Dependency Line und darunter die Anweisung:
foo: foo.o bar.o gcc -o foo foo.o bar.o
CC fällt dabei schon in die oben erwähnte zweite Kategorie vorbelegter Makros. Das heißt, sein Wert ist meist auf einen auf dem System installierten Compiler gesetzt und kann vom Nutzer nach dessen Wünschen überschrieben werden. Dies hat einen bedeutenden Vorteil: Die Verwendung solcher Makros erhöht die Portierbarkeit, da alle Festlegungen, Optionen und Schalter, die bei der Kompilierung verwendet werden sollen, am Anfang des Makefiles stehen. Damit legt der Programmierer im Makefile einige Standardpfade und Optionen sowie vielleicht einen Compiler fest. So braucht man sich, wenn man ein Programm übersetzen möchte, z.B. keine Gedanken um den Compiler machen, da bei der Verwendung von CC der Standardcompiler des Systems verwendet wird.
Neben den eben beschriebenen einfachen und vordefinierten Makros kennt make auch sogenannte interne Makros. Interne Makros werden dynamisch beim Lesen einer Abhängigkeitsbeschreibung immer wieder neu definiert. Durch die Verwendung interner Makros werden Makefiles nicht nur vereinfacht, sondern können auch leichter geändert werden. An dieser Stelle sollen nur zwei interne Makros vorgestellt werden.
Da ist zum Einen $@. $@ enthält immer den Namen des aktuellen Ziels. make schaut beim Auftreten von $@ in die Target/Dependency Line und ersetzt $@ durch den Ausdruck vor dem Doppelpunkt.
Zum Zweiten ist $? sehr beliebt. $? enthält die Namen aller neueren Objekte, oder besser ausgedrückt, alles was in der Target/Dependency Line hinter dem Doppelpunkt steht. Ein illustrierendes Beispiel steht in Listing 5.
Listing 5
Makefile mit internen Makros
ZIEL = foo
OBJS = foo.o bar.o
OPT = -o
$(ZIEL): $(OBJS)
$(CC) $(OPT) $@ $?
Darin fassen wir nochmal alles über Makros zusammen. Zu Beginn des Makefiles definieren wir drei Makros mit den Namen ZIEL, OBJS sowie OPT. Diese werden in der Target/Dependency Line zu
foo: foo.o bar.o
expandiert. In der darunter stehenden Anweisung verwenden wir das vordefinierte Makro CC, welches den auf dem aktuellen System installierten C-Compiler enthält. Dieses brauchen wir also im Allgemeinen gar nicht erst explizit zu definieren. Abschließend expandiert make noch die beiden internen Makros $@ und $? zum aktuellen Ziel bzw. zu den dazugehörigen Objektdateien. Damit ergibt sich folgende Anweisung:
gcc -o foo foo.o bar.o
… natürlich nur, wenn der gcc der auf dem System ansässige C-Compiler ist.
Das war …
… natürlich bei Weitem noch nicht alles, was es zu make zu sagen gäbe. Wer mit diesem sehr nützlichen Werkzeug intensiveren Kontakt sucht, dem seien z.B. die beiden Bücher in der Info-Box ans Herz gelegt. Dabei ist das Buch von Tondo, Nathanson und Yount eine kurze und schmerzlose englische Einführung in make-Versionen verschiedener Hersteller, wohingegen sich das Werk von Herold etwas ausgiebiger mit Details beschäftigt.
Musterwechsel:
make
außerhalb der Programmier-Welt
Wie bereits erwähnt, ist make keineswegs nur für einen Einsatz in der Programmier-Welt geeignet. Listing 6 zeigt an einem kleinen Beispiel, wie make zusammen mit dem Textsatz-Programm LaTeX genutzt werden kann.
Es spielt dabei keine Rolle, wie das eigentliche Dokument aufgebaut ist, solange alles in einer zentralen Datei zusammengefasst ist, die es nun zu übersetzen gilt. Die Variable FILE setzt man auf eben diesen Namen, allerdings ohne das Suffix .tex, und dann kann es schon losgehen. Das Makefile im EinzelnenZuerst teilen wir make mit, welche Suffixe wir für wichtig halten.
.SUFFIXES: .tex .dvi .ps
Das erhöht zum einen die Übersichtlichkeit, denn schon beim Blick in die erste Zeile weiß man, mit welchen Suffixen in diesem Makefile gearbeitet wird. Zum Zweiten weiß make, dass es bei Dateien, deren Dateiendung hinter dem Doppelpunkt aufgezählt ist, zuerst im Makefile nach einer Suffix-Regel suchen soll und erst dann in der internen Suffix-Datenbank.
Dann setzen wir die Variable FILE auf den Namen der zu übersetzenden Datei und verwenden im Anschluss daran ausschließlich diese Variable.
############################################# FILE = book ############################################# DVIFILE = $(FILE).dvi PSFILE = $(FILE).ps
Das spart Schreibarbeit, wenn sich der Name der Datei ändert. Anschließend geben wir die Befehle an, mit denen gearbeitet werden soll und legen für diese noch einige Optionen fest:
TEX = latex DVIPS = dvips DVIOPT = -q -D600
Nun kommen wir zur eigentlichen Arbeit. Die folgende Suffix-Regel legt fest, wie make aus einer .tex-Datei eine .dvi-Datei machen soll.
.tex.dvi:
echo "$< wird übersetzt ..."
$(TEX) $<
$(TEX) $<
Da es besser ist, immer klar zu wissen, was make eigentlich tut, sorgen wir mit dem echo-Befehl dafür, dass wir erfahren, dass book jetzt übersetzt wird. Die Anweisung $(TEX) $< soll zweimal ausgeführt werden, da Verweise, Indexeinträge u.a. erst beim zweiten Übersetzen aufgelöst werden. Nun kommt der Kern des Makefiles:
$(PSFILE): $(DVIFILE)
echo "$@ wird erzeugt ..."
$(DVIPS) $(DVIOPT) $?
$(MAKE) -i cleanup
Dieser Befehlsblock sagt explizit: Um die oben angegebene PostScript-Datei zu erzeugen, nimm die DVI-Datei, welche durch die Suffix-Regel implizit erzeugt wird, und führe damit die Kommandozeile $(DVIPS) $(DVIOPT) $? aus. Diese wird wiederum zu folgender Anweisung expandiert:
dvips -q -D600 book.dvi
dvips erzeugt aus der Datei book.dvi eine PostScript-Datei. Dabei besagt die Option -q, dass keine Bildschirmausgaben gemacht werden soll (“quiet”), und -D600 sorgt dafür, dass das PostScript-Dokument mit einer Auflösung von 600 dpi erzeugt wird.
Das Pseudo-Target cleanup: macht anschließend noch schön sauber:
cleanup:
echo "Verzeichnisse werden aufgeräumt!";
rm -rf *~ *.*~ *.log *.aux *.dvi *.idx *.toc
Alle Sicherungskopien (deren Namen auf ~ enden), Protokolldateien (*.log), Hilfsdateien (*.aux), DVI-Files, Index-Dateien (*.idx) und Hilfsdateien zur Erzeugung des Inhaltsverzeichnisses (*.toc) werden dabei im aktuellen Verzeichnis gelöscht.
Listing 6
Ein Makefile für LaTeX
.SUFFIXES: .tex .dvi .ps
#############################################
FILE = book
#############################################
DVIFILE = $(FILE).dvi
PSFILE = $(FILE).ps
TEX = latex
DVIPS = dvips
DVIOPT = -q -D600
#############################################
.tex.dvi:
echo "$< wird übersetzt ..."
$(TEX) $<
$(TEX) $<
$(PSFILE): $(DVIFILE)
echo "$@ wird erzeugt ..."
$(DVIPS) $(DVIOPT) $?
$(MAKE) -i cleanup
cleanup:
echo "Verzeichnisse werden aufgeräumt!";
rm -rf *~ *.*~ *.log *.aux *.dvi *.idx *.toc
Glossar
-
Quelldateien
-
Die Dateien, in denen ein Programmierer seine Ideen schriftlich mit den Mitteln einer Programmiersprache (z.B. C) festhält.
-
übersetzt
-
Der Schritt, bei dem die Anweisungen, die in einer Quelldatei stehen, in eine maschinenlesbare Form gebracht werden. Beim Übersetzen wird aus einer Quelldatei eine Objektdatei erzeugt.
-
gelinkt
-
Beim Linken (dt.: “binden”) werden die durch den Kompilierungsvorgang erzeugten Objektdateien mit dem Code aus den Bibliotheken gelinkt. Eine Bibliothek ist eine Sammlung häufig gebrauchter Funktionen mit einem Inhaltsverzeichnis. Wenn ein Programmierer den Namen einer Funktion in seiner Quelldatei verwendet (z.B. die C-Funktion printf()), dann schaut der Linker im Inhaltsverzeichnis der Standard-C-Bibliothek nach, wo der Code für diese Funktion steht, nimmt selbigen und setzt diesen an die Stelle, an der die Funktion in der Quelldatei des Programmierers steht. Anschließend werden noch einige Initialisierungsfunktionen dazugebunden, die dafür sorgen, dass aus dem Objektfile ein ausführbares Programm wird.
-
kompiliert
-
Das Gleiche wie Übersetzen, nur vom englischen to compile abgeleitet.
-
abhängig
-
Wenn man in der Headerdatei foo.h zwei Funktionen foo() und bar() deklariert (und damit festlegt, wie und mit welchen Argumenten sie aufgerufen werden), foo() in der Quelldatei foo.c implementiert (sprich: programmiert) und bar() in der Datei bar.c, dann sind sowohl foo.c als auch bar.c von foo.h abhängig. Das hat zur Folge, dass nach einer Änderung der Funktionsdeklaration von foo() in foo.h nicht nur foo.c, sondern auch bar.c neu übersetzt werden muss, da bar.c nicht “weiß”, worauf sich die Änderung von foo.h bezieht.
-
Timestamp
-
Der Timestamp – oder auf deutsch die Zeitmarke – einer Datei gibt das Datum und die Uhrzeit der letzten Änderung dieser Datei an.
-
foo
-
Warum ausgerechnet die beiden Begriffe
fooundbarim Hacker-/Programmierer-Slang ständig als Beispielnamen für Dateien, Funktionen u.ä. herhalten müssen, lässt sich nicht genau sagen. Das Jargon File listet unter http://www.lysator.liu.se/hackdict/split2/foo.html gleich eine ganze Anzahl möglicher Ursprünge auf. -
Objektdatei
-
Objektdateien enthalten den Programmcode, den der Programmierer in die Quelldateien geschrieben hat, in maschinenlesbarer Form.
-
gcc
-
Die Option -c weist den Compiler gcc an, aus der vorliegenden Quelldatei eine Objektdatei zu machen; mit -o teilt man ihm mit, dass er die darauf folgende Zeichenkette als Namen für die zu erzeugende Datei verwenden soll. Im obigen Beispiel heißt die zu erzeugenden Datei also foo. Genauere Erklärungen erhält man bei der Betrachtung der Manualpage des gcc. Diese wird mit man gcc aufgerufen.
-
Assembler
-
Im Gegensatz zu problemorientierten Programmiersprachen wie z.B. C oder Java eine sehr maschinennahe Programmiersprache. Mit dem Befehlssatz von Assembler ist es möglich, direkt die Hardware zu manipulieren.
-
LaTeX
-
Im Zusammenspiel mit TeX ein freies, sehr mächtiges Textsatzprogramm. Hierbei werden Anweisungen einer Formatierungssprache (engl.: “typesetting language”) wie z.B. Fettdruck oder Unterstreichungen direkt in den Text geschrieben. Anschließend “kompiliert” man den Text mit dem Programm latex sozusagen in seine endgültige Form. LaTeX wird gern zum Verfassen wissenschaftlicher Arbeiten verwendet, da z.B. selbst komplizierteste mathematische oder chemische Formeln sehr einfach aufgeschrieben werden können.
-
>
-
Dieses “Größer-als”-Zeichen ist eine Ausgabeumleitung. Unter Unix bzw. Linux gibt es eine Standardausgabe, normalerweise das Terminal, also der Bildschirm. Das heißt, dass alle Ausgaben eines Programmes standardmässig auf dem Bildschirm ausgegeben werden (etwa die Auflistung aller Dateien durch den Befehl ls). Das
>-Zeichen sorgt nun dafür, dass diese Ausgabe woanders hin umgeleitet wird – in unserem Falle in die Dateimake_default, die dabei praktischerweise gleich angelegt wird, wenn sie noch nicht vorhanden ist. -
Makros
-
Im Prinzip dasselbe wie Variablen, also Bezeichner, die mit einem Wert belegt werden. Werden diese Bezeichner im Text verwendet, werden sie intern durch ihren jeweiligen Inhalt ersetzt.
-
DVI
-
Eine vom Ausgabegerät unabhängige – DeVice Independent – Datei enthält eine binäre Darstellung des formatierten Textes, in dem für jedes zu druckende Zeichen Schriftart und Position auf der Seite gespeichert sind. Um das Ergebnis visuell darstellen zu können, muss die .dvi-Datei mittels eines .dvi-Treibers (der wahrscheinlich bekannteste ist dvips) in ein brauchbares Ausgabeformat gebracht werden (z.B. PostScript). .dvi-Dateien können z.B. mit dem Programm xdvi betrachtet werden.
-
PostScript
-
Eine geräte- und auflösungsunabhängige Seitenbeschreibungssprache. Sie stellt Methoden zur Verfügung, um das Erscheinungsbild einer auszudruckenden Seite inklusive Text, Linien und Grafiken zu beschreiben. PostScript-Dateien können mit einen Previewer wie z.B. gv oder ghostview betrachtet werden. Gute Drucker sind meist in der Lage, PostScript-Dateien direkt zu verarbeiten.
Infos
[1] C.L. Tondo, A. Nathanson, E. Yount: “Mastering Make – A guide to building programs on DOS and UNIX(TM) systems”, Prentice Hall, 1992
[2] H. Herold: “make und nmake – Software-Managment unter UNIX(TM) und MS-DOS”, Addison-Wesley, 1994




