make kann überall dort genutzt werden, wo nach der Änderung einer Datei ein oder mehrere Arbeitsschritte erforderlich sind. make überprüft bei der Ausführung des Programmes ob eine der Quelldateien geändert wurde und so die Zieldatei ebenfalls aktualisiert werden muss. Außerdem können Abhängigkeiten von Dateien untereinander berücksichtigt werden. Hierzu wertet make verschiedene Regeln, die sich in einer separaten Datei, dem Makefile, befinden aus. Hauptsächlich wird make innerhalb der Software-Entwicklung genutzt, aber es sind auch andere Einsatzmöglichkeiten denkbar.
Im weiteren Verlauf wird der Aufbau eines Makefiles aufgezeigt, welches der Übersetzung von LaTeX-Dateien dient. Die Beispiele wurden unter NetBSD (BSD-make) getestet, Unterschiede zur GNU-Variante (GNU-make) werden gesondert aufgezeigt. Die einzelnen Beispiele wurden bewußt so allgemein wie möglich gehalten und sollten auf den meisten Systemen ohne größere Anpassungen laufen.
Aus den LaTeX-Quelldateien lassen sich bekanntermaßen verschiedene Ausgabeformate erzeugen, beispielsweise DVI, PostScript, PDF oder auch HTML. Je nach Umfang und Struktur der LaTeX-Datei werden bei der Bearbeitung der Datei datei.tex folgende Dateien angelegt:
Darüber hinaus können noch Hilfsdateien für Tabellen- (datei.lot) und Abbildungsverzeichnisse (datei.lof) oder Index- (datei.idx) und (datei.glo) Glossare angelegt werden. Die bei der Übersetzung erzeugten Hilfsdateien werden bei einer weiteren, sich anschliessenden Übersetzung verwendet und die Eintragungen in dem Ausgabedokument eingefügt. Da sich beispielsweise das Inhaltsverzeichnis meist auf den ersten Seiten befindet, kann dieses im ersten Durchlauf nicht vollständig sein, da unter anderem Titel und Seitenzahlen der folgenden Kapitel noch nicht bekannt sein können. Diese werden deshalb zunächst in einer Hilfsdatei vermerkt, die bei einem zweiten Lauf ausgelesen wird und deren Inhalt an der entsprechenden Stelle im Ausgabedokument eingefügt wird.
Aus diesem Grund ist daher der Aufruf latex datei.tex zum Übersetzen der LaTeX-Quellen mindestens zweimal (es gibt auch Situationen die drei Durchläufe erfordern) zu tätigen.
Beim Aufruf von make sucht das Programm im aktuellen Verzeichnis nach einer Datei mit der Bezeichnung GNUmakefile, makefile oder Makefile. Diese Dateien enthalten Anweisungen, die von make bei der Ausführung berücksichtigt werden sollen. Diese Steuerungsdateien werden in der angegebenen Reihenfolge berücksichtigt. Sind mehrere Dateien vorhanden, wird nur die zuerst gefundene Datei ausgewertet. Ist keine der drei Dateien im aktuellen Verzeichnis vorhanden, erfolgt der Abbruch des Programms.
Ein Makefile besteht aus ein oder mehreren Regeln, die beschreiben, wie aus ein oder mehreren Quellen ein Ziel unter Nutzung verschiedener Befehle erzeugt wird. Um die Lesbarkeit zu erhöhen, können die Regeln durch Kommentare (werden mit einem # eingeleitet) ergänzt werden.
Um beispielsweise aus der Quelle datei.tex das Ziel datei.dvi zu generieren, kann folgendes Makefile genutzt werden:
# Makefile zum Uebersetzen von LaTeX-Datei(en)
#
datei.dvi: datei.tex
latex datei.tex
latex datei.tex
Hier wird zunächst das Ziel datei.dvi festgelegt und dass dieses von datei.tex abhängt. Die Zieldatei wird immer dann aktualisiert, wenn die Quelldatei geändert wurde.In den zwei folgenden Zeilen wird festgelegt, mit welchen Arbeitsschritten dieses Ziel erzeugt wird.
Beim Aufbau einer Regel ist folgendes zu beachten:
Der Aufruf
$ make .... Output written on datei.dvi (1 page, 348 bytes). Transcript written on datei.log. $
erzeugt die Zieldatei datei.dvi, wenn die Quelldatei aktueller ist als die Zieldatei. Andernfalls erfolgt ein entsprechender Hinweis.
$ make `datei.dvi' is up to date. $
Die entstandene Datei kann wiederum als Quelldatei für weitere Arbeitsschritte dienen. So kann die generierte DVI-Datei nunmehr in ein weiteres Format beispielsweise PostScript überführt werden. Die PostScript-Datei wird immer dann erzeugt, wenn die DVI-Datei eine Änderung erfahren hat.
datei.dvi: datei.tex
latex datei.tex
latex datei.tex
datei.ps: datei.dvi
dvips -o datei.ps datei.dvi
Besteht das Eingangsdokument aus mehreren LaTeX-Dateien können diese wie folgt aufgeführt werden:
datei.dvi: datei.tex kap01.tex kap02.tex kap03.tex kap04.tex ....
oder auch
datei.dvi: datei.tex \
kap01.tex \
kap02.tex \
kap03.tex \
kap04.tex \
....
Hierbei ist zu beachten, daß unmittelbar nach dem Backslash der Zeilenumbruch erfolgen muss.
Hierbei reicht die Änderung einer der Quelldateien aus, damit die Zieldatei beim Aufruf von make aktualisiert wird.
Das bisherige Makefile läßt sich beliebig um weitere Ziele erweitern, beispielsweise zum Erzeugen von PDF- und HTML-Dateien:
datei.pdf: datei.ps
ps2pdf datei.ps datei.pdf
datei.html: datei.tex
latex2html datei.tex
Die nicht mehr benötigten Dateien lassen sich über die folgende Regel löschen:
clean:
-rm -f datei.aux datei.dvi datei.lof datei.log datei.lot datei.toc *~
Durch die Angabe -rm werden Fehler ignoriert und die Ausführung fortgesetzt. Falls beispielsweise eine Datei gelöscht werden soll, die überhaupt nicht existiert, wird das Programm weiter ausgeführt und nicht mit einem Fehler abgebrochen. Das gleiche Verhalten kann auch beim Aufruf von make über die Option -i erreicht werden.
Hieraus ergibt sich das folgende Makefile:
# Makefile zum Uebersetzen von LaTeX-Datei(en)
#
datei.ps: datei.dvi
dvips -o datei.ps datei.dvi
datei.dvi: datei.tex
latex datei.tex
latex datei.tex
datei.pdf: datei.ps
ps2pdf datei.ps datei.pdf
datei.html: datei.tex
latex2html datei.tex
clean:
-rm -f datei.aux datei.dvi datei.lof datei.log datei.lot datei.toc *~
Da das erste Ziel das Erzeugen der PostScript-Datei definiert, kann hierzu wahlweise make oder make datei.ps aufgerufen werden. Alle anderen Ziele sind beim Aufruf namentlich zu benennen, also beispielsweise make datei.html für die HTML-Dateien.
Ein kurzer Blick genügt um zu erkennen, daß die Bezeichnung datei relativ häufig auftaucht und sich jeweils nur durch die Endung unterscheidet. Falls die Quelldatei einen anderen Namen bekommen soll, geht der Spaß los. An jeder Stelle des Makefiles ist datei mit der neuen Dateibezeichnung zu ersetzten. Das diese Vorgehensweise nicht sonderlich effektiv ist, versteht sich von selbst. Wie so oft heißt auch hier die Lösung Variable.
Hierzu wird zunächst die Variable benannt und ihr ein Wert zugewiesen:
DATEI = datei
Auf definierte Variablen kann jederzeit durch vorangestelltes $-Zeichen gefolgt von wahlweise runder $(DATEI) oder geschweifter ${DATEI} Klammerung zugegriffen werden.
$(DATEI).ps: $(DATEI).dvi
....
Die Befehle zum Abarbeiten der Ziele können sich bei unterschiedlichen Systemen in unterschiedlichen Verzeichnissen befinden. Aus diesem Grund kann es sinnvoll sein die betreffenden Kommandos am Anfang eines Makefiles ebenfalls über Variable festzulegen.
BINDIR = /usr/pkg/bin LATEX = $(BINDIR)/latex DVIPS = $(BINDIR)/dvips ....
Ausser der einfachen Zuweisung eines Wertes an eine Variable über das Zeichen = können Variablen auch über die folgenden Operatoren Werte zugewiesen werden:
$ cat Makefile
GRUSS = Hallo
GRUSS += Welt
all:
@echo $(GRUSS)
$ make
Hallo Welt
$
$ cat Makefile
GRUSS = Hallo
GRUSS ?= Guten Tag
NAME = Welt
all:
@echo $(GRUSS) $(NAME)
$ make
Hallo Welt
$ cat Makefile
GRUSS ?= Guten Tag
NAME = Welt
all:
@echo $(GRUSS) $(NAME)
$ make
Guten Tag Welt
$
$ cat Makefile
GRUSS = Hallo
GRUSS := Welt
all:
@echo $(GRUSS)
$ make
Welt
$
$ cat Makefile
VERZ != pwd
all:
@echo $(VERZ)
$ make
/home/tl
$
Hierbei handelt es sich um ein Beispiel für die BSD-Variante, unter GNU erfolgt die Zuweisung über:
VERZ := $(shell pwd)
all:
@echo $(VERZ)
Unter Nutzung von Variablen kann das bisherige Makefile wie folgt umgeschrieben werden:
# Makefile zum Uebersetzen von LaTeX-Datei(en)
#
DATEI = datei
BINDIR = /usr/pkg/bin
LATEX = $(BINDIR)/latex
DVIPS = $(BINDIR)/dvips
PS2PDF = $(BINDIR)/ps2pdf
LATEX2HTML = $(BINDIR)/latex2html
DVIOPT = -o
RM ?= /bin/rm -f
$(DATEI).ps: $(DATEI).dvi
$(DVIPS) $(DVIOPT) $(DATEI).ps $(DATEI).dvi
$(DATEI).dvi: $(DATEI).tex
$(LATEX) $(DATEI).tex
$(LATEX) $(DATEI).tex
$(DATEI).pdf: $(DATEI).ps
$(PS2PDF) $(DATEI).ps $(DATEI).pdf
$(DATEI).html: $(DATEI).tex
$(LATEX2HTML) $(DATEI).tex
clean:
$(RM) $(DATEI).aux \
$(DATEI).dvi \
$(DATEI).lof \
$(DATEI).log \
$(DATEI).lot \
$(DATEI).toc \
*~
Der Aufbau bietet keine größeren Überraschungen, die Variable RM ist vereinzelt bereits vordefiniert (Systemeinstellungen oder als Shell-Variable), deshalb wurde hier der Operator ?= genutzt.
Eine weitere Möglichkeit die Änderung der Bezeichnung von Datei(en) an einer zentralen Stelle vorzunehmen, besteht in der Nutzung von Ersetzungen. Hierzu wird zunächst die Bezeichnung der LaTeX-Datei festgelegt und anschliessend eine Ersetzung der Dateikennungen vorgenommen:
TEXFILE = datei.tex DVIFILE = $(LATEX:%.tex=%.dvi) PSFILE = $(LATEX:%.tex=%.ps)
Somit haben die Variablen DVIFILE und PSFILE die Werte datei.dvi bzw. datei.ps.
Den einzelnen Variablen können beim Aufruf von make abweichende Werte (als die im Makefile angegebenen) zugewiesen werden. Damit der Ein- und Ausgabedatei ein anderer Namen zu gewiesen wird, ist der Aufruf
$ make DATEI=test
auszuführen. Hierbei wird der Variablen DATEI der Wert test übergeben, der den gesetzten Wert im Makefile »überschreibt«.
Bei der Nutzung von Variablen ergibt sich die folgende Reihenfolge der Auswertung:
Wird make mit der Option -e aufgerufen ergibt sich eine Änderung der Reihenfolge dahingehend, dass 2. und 3. die »Plätze tauschen«.
Bei den bisherigen Zielen wurde beim Aufruf von make der Name der zu erzeugenden Datei als Argument bei Aufruf des Programmes angegeben. Als einzige Ausnahme wurde bislang zum »Aufräumen« clean als Ziel angegeben.
Darüber sind einige der folgenden Ziele häufiger anzutreffen:
Darüber hinaus können noch weitere Ziele beliebig angelegt werden. Auf das bisherige Beispiel bezogen, kann so beispielsweise das Ziel html definiert werden (statt der namentlichen Benennung der Zieldatei),
html:
$(LATEX2HTML) $(DATEI).tex
um so über den Aufruf
$ make html
die HTML-Dateien zu generieren.
Unter bestimmten Voraussetzungen lassen sich die Regeln in ihrer Schreibweise zusammenfassen. Wenn Dateien eines Typs stets auf die gleiche Art bearbeitet werden, so braucht in der Regel im Makefile nur die Dateiendung der Ziel- und Quelldatei angegeben werden.
Die allgemeine Syntax dieser sogenannten Suffix-Regeln lautet:
.quelle.ziel:
befehl
Diese Regel besagt nichts weiter, als dass Dateien mit der Endung .ziel immer aus Dateien mit der Endung .quelle über den befehl generiert werden. Da die Bearbeitung der Quellen stets auf die gleiche Art zum Ziel führen, müssen diese nicht namentlich benannt werden, es reicht die Angabe der (Datei-) Endung.
So werden beispielsweise LaTeX-Dateien stets unter Nutzung des Programmes latex in das DVI-Format übersetzt. Die entsprechende Suffix-Regel hierzu lautet:
.tex.dvi:
$(LATEX) $<
Wie ersichtlich ist hier nur die Endung der Ziel- und Quelldatei (mit führendem Punkt und ohne Leerzeichen), statt des vollen Dateinamens angegeben. Diese Regel gilt somit für sämtliche Quelldateien mit der Endung *.tex und nicht für eine »namentlich benannte Liste«.
In der Befehlszeile sind die folgenden »Kurzformen« zulässig:
$< Quelldatei (darf ausschliesslich hier genutzt
werden)
$@ Zieldatei $* Dateiname ohne EndungDamit make die Suffix-Regeln als solche erkennt, müssen die relevanten Dateiendungen nach dem Ziel .SUFFIXES angegeben werden. Das Beispiel ist demnach um folgenden Eintrag, am Anfang des Makefiles zu ergänzen:
.SUFFIXES: .tex .dvi
make kann bereits eine Liste mit Dateiendungen vorgegeben sein. Diese Liste kann in der GNU-Variante über die Option -p und bei BSD über -dv abgefragt werden.
Suffix-Regeln bieten sich in der Regel für die »Freunde kompakter Makefiles« an. Auf der anderen Seite sind sie - mitunter - schwieriger zu lesen.
Bei der Erzeugung von PostScript- aus LaTeX-Dateien werden Bilder und Graphiken im EPS-Fromat benötigt. Oftmals liegen diese Dateien jedoch in einem anderen Format vor, so dass diese zunächst in das neue Format konvertiert werden müssen. Aufgrund ihrer Flexibilität bietet sich hierzu die Anwendung der Suffix-Regeln an.
Folgende Regel konvertiert beispielsweise Graphiken von GIF nach EPS:
.gif.eps:
giftopnm $*.gif | pnmtops -equalpixels -noturn > $*.eps
Nachdem das Makefile um die Angaben zu
.SUFFIXES: .gif .eps
ergänzt wurde, kann es beispielsweise wie folgt aufgerufen werden:
$ make pic1.eps giftopnm pic1.gif | pnmtops -equalpixels -noturn > pic1.eps giftopnm: Reading Image Sequence 0 pnmtops: writing color PostScript... $
Diese Regel läßt sich entsprechend auch auf andere Graphik-Formate anwenden.
Literatur- und Stichwortverzeichnisse werden in LaTeX meist unter Nutzung von Zusatzprogrammen generiert.
Für die Verwaltung von Literaturangaben findet häufig das Programm BibTEX seine Anwendung. Dabei werden die Angaben für das Literaturverzeichnis aus ein oder mehreren Datenbankdateien (mit der Endung *.bib) ausgelesen und an den angegebenen Stellen im Ausgabedokument eingefügt. Um das Literaturverzeichnis generieren zu können sind mehrere Durchläufe erforderlich. Zuerst wird das Dokument mit LaTeX bearbeitet, anschliessend erfolgt der Aufruf von BibTeX, also beispielsweise
$ latex datei.tex $ bibtex datei
Das Programm bibtex generiert das formatierte Literaturverzeichnis datei.bbl. Nach zwei weiteren LaTeX-Durchläufen befinden sich die Literaturangaben an den Stellen im Text, an der die entsprechenden Befehle stehen.
Ein entsprechender Eintrag im Makefile für die ersten zwei Durchläufe könnte wie folgt aussehen:
$(DATEI).bbl: $(DATEI).tex
latex $(DATEI).tex
bibtex $(DATEI)
Die Abarbeitung dieser Regel müsste vor den beiden sich sowieso anschliessenden LaTeX-Durchläufen erfolgen.
Ein Stichwortverzeichnis (bzw. Index) kann mit dem Programm makeindex erzeugt werden. Hierzu wird die bei einem LaTeX-Lauf erzeugte Hilfsdatei, mit der Endung *.idx ausgewertet.
Diese kann über den Aufruf
$ makeindex datei.idx
weiter bearbeitet werden. Das Resultat dieses Aufrufs ist die Datei datei.ind, aus der wiederum der Index generiert wird. Der Index kann an jeder beliebigen Stelle im Eingabetext über den entsprechenden Befehl eingefügt werden, wozu das Dokument ein weiteres Mal von LaTeX zu übersetzen ist.
Auch hier bietet die Regel im Makefile keine größeren Überraschungen:
$(DATEI).ind: $(DATEI).idx
latex $(DATEI).tex
makeindex $(DATEI).idx
Die Abarbeitung der Regel sollte gleichfalls vor den anschliessenden LaTeX-Durchläufen erfolgen.
Über den Aufruf von make ist auch die Ausführung von Shell-Kommandos möglich, normalerweise /bin/sh. Abweichende Einstellungen sind über die Variable .SHELL bzw. SHELL möglich.
Bei der Ausführung ist zu beachten, dass jede Befehlszeile als eigenständiger Befehl ausgeführt wird. So führt beispielsweise
chdir:
@pwd
@cd tmp
@pwd
in der GNU-Variante von make zu folgendem Resultat:
$ make chdir /home/tl /home/tl $
Um den gewünschten Verzeichniswechsel zu vollziehen, ist folgende Änderung im Makefile erforderlich:
chdir:
@pwd; \
cd tmp; \
pwd
bzw.
chdir:
@pwd; cd tmp; pwd
In diesem Beispiel steht die Befehlsfolge in einer Zeile und wird entsprechend ausgeführt:
$ make chdir /home/tl /home/tl/tmp $
Das der Befehlsfolge vorangestellte Zeichen @ verhindert die Ausgabe des Befehls vor der Ausführung. Der gleiche Effekt läßt sich auch über die Option -s bzw. über das Ziel .SILENT realisieren.
Beim Aufruf von make können verschiedene Optionen (nicht Ziele) angegeben werden, die das Programmverhalten während der Ausführung beeinflußen. Dazu gehören unter anderem:
Je nach Umfang und Flexibilität sollte ein Makefile an einer »zentralen Stelle« gespeichert werden. Sollen auf dieser Grundlage weitere LaTeX-Dokumente übersetzt werden, sind in dem entsprechenden Verzeichnis nur noch der folgende »Zweizeiler« erforderlich:
DATEI = dateiname include $(HOME)/docs/Makefile