Bitte denken Sie daran: Sie dürfen zwar die Online-Version ausdrucken, aber diesen Druck nicht fotokopieren oder verkaufen.
Wünschen Sie mehr Informationen zu der gedruckten Version des Buches "Linux - Wegweiser zur Installation & Konfiguration", dann klicken Sie hier.
Irgendwann in Ihrem Zusammenleben mit Linux werden Sie wahrscheinlich auf make stoßen -- selbst wenn Sie gar nicht programmieren möchten. Sicherlich werden Sie einmal den Kernel ändern und neu erstellen, und dazu brauchen Sie make . Wenn Sie Glück haben, müssen Sie sich nicht durch die Makefiles wühlen -- wir wollten uns mit diesem Buch allerdings auch an die Pechvögel wenden. In diesem Abschnitt wollen wir Ihnen deshalb so viel von der feinsinnigen make -Syntax vermitteln, daß ein Makefile Sie nicht mehr einschüchtern kann.
In einigen unserer Beispiele werden wir das aktuelle Makefile für den Linux-Kernel benutzen. Darin sind viele der mächtigen Erweiterungen enthalten, die zur GNU-Version von make gehören; das gibt uns Gelegenheit, sowohl einige dieser Erweiterungen als auch das Standard- make zu beschreiben. In Managing Projects with make von Andrew Oram und Steve Talbott finden Sie eine gute Einführung in make .
Die GNU-Erweiterungen werden in der Manual-Page zu GNU- make ausführlich beschrieben.
Die meisten Benutzer betrachten make als ein Hilfsmittel, um aus Quelltexten Objektdateien und Bibliotheken zu erzeugen sowie Objektdateien zu ausführbaren Dateien zu machen. Wenn man es abstrakter betrachtet, ist make ein vielseitiges Programm, das aus gewissen Abhängigkeiten (prerequisites) bestimmte Ziele (targets) erzeugt. Das Ziel kann eine ausführbare Datei sein, ein PostScript-Dokument oder was auch immer. Die Abhängigkeiten können C-Code, eine Textdatei im TEX-Format usw. sein.
Es ist nicht schwierig, einfache Shell-Skripts zu schreiben, die gcc -Befehle aufrufen, um ausführbare Programme zu erzeugen. make dagegen kann noch mehr: Es weiß, welche Ziele neu erstellt werden müssen und welche nicht. So muß beispielsweise eine Objektdatei nur dann erneut kompiliert werden, wenn die zugrundeliegende Quelldatei geändert wurde.
Ein Beispiel: Nehmen wir an, daß ein Programm aus drei C-Quelltexten besteht. Sie könnten nach jeder Änderung in einer der Quelldateien mit dem Befehl:
papaya$ gcc -o foo foo.c bar.c baz.c
alle drei Dateien erneut kompilieren, um eine neue ausführbare Datei zu erzeugen. Das wäre allerdings eine große Zeitverschwendung, da Sie ja nur eine Quelldatei geändert haben. (Dies gilt ganz besonders dann, wenn das fragliche Programm aus mehr als nur einer Handvoll von Quelldateien besteht.) Was Sie wirklich erreichen möchten, ist die Neukompilierung der einen geänderten Datei zu einer Objektdatei sowie das erneute Binden aller Objektdateien zur ausführbaren Datei. make kann diesen Vorgang für Sie automatisieren.
Grundsätzlich unterstützt make Sie dabei, eine Zieldatei in kleinen Schritten zu erzeugen. Wenn ein Programm aus vielen Quellcodedateien besteht, können Sie eine davon ändern und eine neue ausführbare Datei erzeugen, ohne alle Quelldateien neu kompilieren zu müssen. make erreicht diese Flexibilität, indem es sich merkt, welche Dateien zu Ihrem Ziel gehören.
Hier zeigen wir Ihnen ein triviales Makefile. Nennen Sie es makefile oder Makefile und speichern Sie die Datei in dem Verzeichnis ab, in dem auch die Quellcodedateien stehen.
edimh: main.o edit.o
gcc -o edimh main.o edit.o
main.o: main.c
gcc -c main.c
edit.o: edit.c
gcc -c edit.c
Dieses Makefile erzeugt aus den beiden Quelldateien main.c und edit.c ein Programm namens edimh . Sie können ein Makefile nicht nur für die C-Programmierung einsetzen; es können beliebige Befehle enthalten sein.
Das Makefile besteht aus drei Einträgen. Jeder davon enthält eine Abhängigkeiten -Zeile, aus der hervorgeht, wie eine Datei erzeugt wird. Die erste Zeile besagt also, daß edimh (der Name vor dem Doppelpunkt) aus den beiden Objektdateien main.o und edit.o (den Namen hinter dem Doppelpunkt) erzeugt wird. Für make bedeutet das, daß es die folgende gcc -Zeile immer dann ausführen soll, wenn eine dieser beiden Objektdateien geändert wurde. Die Zeilen, in denen Befehle stehen, müssen mit einem Tabulator beginnen (und nicht mit Leerzeichen).
Der Befehl:
papaya$ make edimh
führt die gcc -Zeile aus, wenn derzeit keine Datei namens edimh vorhanden ist. Diese Zeile wird aber auch dann ausgeführt, wenn edimh existiert, aber eine der Objektdateien neuer ist. In diesem Fall ist edimh das Ziel . Die Dateien hinter dem Doppelpunkt nennt man entweder Abhängigkeiten oder Vorbedingungen .
Die nächsten beide Einträge erfüllen denselben Zweck für die Objektdateien. Die Datei main.o wird erzeugt, wenn sie noch nicht existiert oder wenn die zugehörige Quelldatei main.c neuer ist. edit.o wird aus edit.c erzeugt.
Woher weiß make , ob eine Datei neu ist? Es liest den Zeitstempel, den das Dateisystem jeder Datei zuordnet. Mit dem Befehl ls -l können Sie sich den Zeitstempel anzeigen lassen. Da diese Zeiten auf eine Sekunde genau sind, kann make zuverlässig ablesen, ob Sie eine Quelldatei nach dem letzten Compilerlauf geändert haben, oder ob Sie eine Objektdatei kompiliert haben, nachdem die letzte Version der ausführbaren Datei erzeugt wurde.
Lassen Sie uns dieses Makefile testen und beobachten, was passiert:
papaya$ make edimh gcc -c main.c gcc -c edit.c gcc -o edimh main.o edit.o
Wenn wir jetzt main.c editieren und den Befehl noch einmal aufrufen, werden nur die notwendigen Dateien neu erzeugt und wir sparen etwas Zeit:
papaya$ make edimh gcc -c main.c gcc -o edimh main.o edit.o
Es spielt keine Rolle, in welcher Reihenfolge die drei Einträge im Makefile stehen. make findet heraus, welche Dateien von welchen anderen abhängig sind und führt die Befehle in der richtigen Reihenfolge aus. Es ist bequemer, den Eintrag für edimh an die erste Stelle zu setzen, weil das die Datei ist, die per Voreinstellung erzeugt wird. Mit anderen Worten: Wenn Sie make aufrufen, erhalten Sie dasselbe Ergebnis wie mit make edimh.
Sehen wir uns ein etwas längeres Makefile an. Versuchen Sie herauszubekommen, was darin passiert:
install: all
mv edimh /usr/local
mv readimh /usr/local
all: edimh readimh
readimh: read.o edit.o
gcc -o readimh main.o read.o
edimh: main.o edit.o
gcc -o edimh main.o edit.o
main.o: main.c
gcc -c main.c
edit.o: edit.c
gcc -c edit.c
read.o: read.c
gcc -c read.c
Als erstes sehen wir das Ziel install. Daraus wird nie eine Datei erzeugt werden; man nennt das ein unechtes Ziel (phony target), weil dieser Eintrag nur existiert, damit die Befehle darunter ausgeführt werden können. Bevor install ausgeführt wird, muß zuerst all aufgerufen werden, weil install von all abhängig ist. (Erinnern Sie sich, daß die Reihenfolge der Einträge keine Rolle spielt.)
Als nächstes wendet sich make also dem Ziel all zu. Dahinter stehen keine Befehle (das ist in Ordnung so), aber all ist abhängig von edimh und readimh. Dabei handelt es sich um echte Dateien; es sind zwei ausführbare Programme. make geht also die Liste der Abhängigkeiten solange durch, bis es zu den .c -Dateien kommt, die von nichts weiter abhängig sind. Anschließend wird make jedes einzelne Ziel gewissenhaft neu erzeugen.
Lassen Sie uns einen Testdurchlauf starten (eventuell brauchen Sie Root-Berechtigung, um die Dateien im Verzeichnis /usr/local installieren zu können):
papaya$ make install gcc -c main.c gcc -c edit.c gcc -o edimh main.o edit.o gcc -c read.c gcc -o readimh main.o read.o mv edimh /usr/local mv readimh /usr/local
Dieses Makefile bewältigt also einen kompletten Durchlauf zur Erzeugung und Installation aller Dateien. Es erzeugt zuerst die Dateien, die für edimh benötigt werden. Dann erzeugt es die Objektdatei, die zusätzlich für die Erzeugung von readmh gebraucht wird. Wenn diese beiden ausführbaren Dateien erstellt sind, ist das Ziel all erfüllt. Anschließend kann make mit dem Ziel install weitermachen, also die ausführbaren Dateien an ihren endgültigen Speicherort verschieben.
Viele Makefiles, darunter auch die, die Linux erzeugen, enthalten eine ganze Reihe unechter Ziele, mit denen Routineaufgaben erledigt werden. Das Makefile für den Linux-Kernel enthält z.B. Befehle, die temporäre Dateien löschen:
clean: archclean
rm -f kernel/ksyms.lst
rm -f core `find . -name '*.[oas]' -print`
.
.
.
Dort finden Sie auch Befehle, um eine Liste mit Objektdateien samt den Header-Dateien, von denen sie abhängig sind, zu erzeugen. (Dies ist eine komplizierte und wichtige Aufgabe -- wenn eine Header-Datei geändert wird, soll sichergestellt werden, daß die Objektdateien, die davon abhängig sind, neu kompiliert werden.)
depend dep:
touch tools/version.h
for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done >
.tmpdepend
.
.
.
Einige dieser Shell-Befehle werden ziemlich komplex; wir werden uns im Abschnitt » Mehrfach-Befehle « weiter unten in diesem Kapitel noch mit den Befehlen in Makefiles befassen.
Die größten Probleme rund um die Makefiles verursacht immer die Syntax -- jedenfalls für Neulinge. Also gut, wir sagen es geradeheraus: Die Syntax von make ist ganz einfach idiotisch. Wenn Sie Leerstellen einfügen, wo Tabulatoren stehen sollten (oder umgekehrt), geht das Ding in die Hose; die Fehlermeldungen dazu sind eher verwirrend.
Setzen Sie vor eine Befehlszeile immer einen Tabulator -- keine Leerstellen.
Setzen Sie niemals einen Tabulator vor irgendeine der anderen Zeilen.
Sie können an beliebiger Stelle in einer Zeile ein Nummer-Zeichen (#)
schreiben, um einen Kommentar einzuleiten. Alles hinter dem Zeichen wird
ignoriert.
Wenn Sie ein Backslash an das Ende einer Zeile setzen, wird die nächste
Zeile eine Fortsetzungszeile. Das funktioniert mit besonders langen Befehlen
ebenso wie für alle anderen Zeilen in Makefiles.
Lassen Sie uns einige der mächtigen Fähigkeiten von
make
betrachten, die insgesamt eine Art Programmiersprache darstellen.
Wenn Programmierer einen Dateinamen oder sonstigen String innerhalb eines
Makefiles mehr als einmal benutzen, tendieren sie dazu, daraus ein Makro zu
machen. Das ist einfach eine Zeichenfolge, die mit Hilfe von
make
zu einer anderen Zeichenfolge expandiert. Sie könnten z.B. den Anfang
unseres trivialen Makefiles so formulieren:
Wenn
make
loslegt, wird es einfach überall da main.o edit.o einsetzen, wo Sie
$(OBJECTS) angegeben haben. Wenn Sie dem Projekt eine weitere Objektdatei
hinzufügen möchten, brauchen Sie dies nur in der ersten Zeile der
Datei anzugeben. Die Zeile mit den Abhängigkeiten und die Befehle werden
dementsprechend angepaßt.
Vergessen Sie die Klammern nicht, wenn Sie $(OBJECTS) ansprechen. Makros sehen
vielleicht ein wenig wie Shell-Variablen aus (etwa $HOME oder $PATH), aber sie
sind doch anders.
Sie können ein Makro innerhalb einer anderen Makrodefinition einsetzen.
Ein Beispiel:
In diesem Fall wird HEADERS zum Verzeichnis
/usr/local/include
expandiert, und SOURCES wird zu
/usr/local/src
. Falls Sie ein Programmpaket auf Ihrem System installieren, das nicht in
/usr/local
stehen soll, müssen Sie nur ein anderes Verzeichnis finden und dieses in
der ROOT-Zeile eintragen.
Sie müssen übrigens für die Namen von Makros keine
Großbuchstaben verwenden, aber diese Konvention hat sich überall
durchgesetzt.
Ein Zusatz zum GNU-
make
gibt Ihnen die Möglichkeit, eine Makrodefinition zu erweitern. Benutzen
Sie dazu den String := statt des Gleichheitszeichens:
Die erste Zeile enthält eine normale Makrodefinition, die dem Makro
DRIVERS den Wert drivers/block/block.a zuweist. Die nächste Definition
erweitert das Makro um die Datei drivers/scsi/scsi.a; diese Erweiterung findet
allerdings nur dann statt, wenn auch CONFIG_SCSI definiert ist. Die komplette
Zuweisung lautet in diesem Fall:
Wie aber definieren Sie CONFIG_SCSI? Fügen Sie es einfach in das Makefile
ein und weisen Sie ihm einen beliebigen Wert zu:
Wahrscheinlich ist es aber einfacher, die Definition auf der Befehlszeile von
make
vorzunehmen -- und so wird's gemacht:
Eine Feinheit bei der Benutzung von Makros ist das undefinierte Makro. Wenn
ein Makro nicht definiert wird, bekommt es eine leere Zeichenfolge zugewiesen
(d.h., es steht nichts an der Stelle, an der das Makro stehen sollte). Damit
haben Sie aber auch die Möglichkeit, ein Makro als Environment-Variable
zu definieren. Wenn Sie also z.B. CONFIG_SCSI nicht im Makefile definieren,
könnten Sie folgendes in Ihre Datei
.bashrc
einfügen (wenn Sie
bash
benutzen):
Für die
csh
oder
tcsh
schreiben Sie folgendes in die Datei
.cshrc
:
Damit haben Sie für alle Compilerläufe das Makro CONFIG_SCSI
definiert.
Natürlich wollen Sie bei solchen Routineaufgaben wie der Erzeugung einer
Objektdatei aus einer Quelldatei in Ihrem Makefile nicht jede
Abhängigkeit einzeln definieren. Dazu besteht auch kein Grund. Die
UNIX-Compiler bestehen auf einer einfachen Vereinbarung (eine Datei mit der
Endung
.c
wird kompiliert, um eine Datei mit der Endung
.o
zu erzeugen);
make
benutzt Suffix-Regeln, um alle vorkommenden Dateien zu erfassen.
Sie könnten diese einfache Suffix-Regel in Ihr Makefile schreiben, um
eine C-Quelldatei zu kompilieren:
Die Zeile .c.o: bedeutet: »Mache aus einer
.c
-Datei eine
.o
-Datei«. Das Makro CFLAGS besteht aus den gewünschten
Compileroptionen -- etwa
-g
zum Debuggen oder
-O
für die Optimierung. Die Zeichenfolge $< steht für »die
Eingabedatei«. An dieser Stelle wird also der Name Ihrer
.c
-Datei eingesetzt, wenn
make
diese Anweisung ausführt.
Lassen Sie uns diese Suffix-Regel testen. Die Befehlszeile übergibt die
beiden Optionen
-g
und
-O
:
In Wirklichkeit brauchen Sie diese Suffix-Regel gar nicht in Ihr Makefile
einzubauen, weil
make
bereits etwas ganz Ähnliches enthält. Es benutzt außerdem die
CFLAGS, so daß Sie die Compileroptionen bestimmen können, indem Sie
einfach diese Variable definieren. Das Makefile, das bei der Kompilierung des
Kernels benutzt wird, enthält derzeit eine ganze Reihe von Optionen
für den
gcc
:
Da wir uns gerade mit Compileroptionen beschäftigen, wollen wir eine
besonders erwähnen, die man sehr häufig zu sehen bekommt -- das ist
die Option
-D
, mit der Symbole im Quellcode definiert werden. Es kann sein, daß Sie
eine ganze Menge solcher Optionen an Ihr Makefile übergeben müssen,
weil einige davon in den #ifdef-Zeilen recht häufig auftauchen; z.B.
-DDEBUG
oder
-DBSD
. Wenn Sie diese Optionen in der Befehlszeile übergeben, sollten Sie auf
jeden Fall die komplette Reihe der Optionen mit Anführungszeichen oder
Apostrophen klammern; daraufhin wird Ihre Shell alle Optionen als ein einziges
Argument an Ihr Makefile übergeben:
Das
make
von GNU benutzt außerdem etwas, das man Pattern-Regeln (Muster-Regeln)
genannt hat; damit haben Sie weitergehende Möglichkeiten als mit den
Suffix-Regeln. In einer Pattern-Regel ist das Prozentzeichen ein Platzhalter
für »einen beliebigen String«. Mit folgender Regel können
Sie also C-Quellen kompilieren:
In diesem Fall steht die Ergebnisdatei an erster Stelle und die Eingabedatei
erscheint hinter dem Doppelpunkt. Eine Pattern-Regel sieht also aus wie eine
normale Abhängigkeiten-Zeile, enthält aber Prozentzeichen statt der
Dateinamen.
Der String $< ist der Platzhalter für die Eingabedatei, und das $@
steht für die zu erzeugende Datei; hier wird also der Name der
.o
-Datei eingesetzt. Beide sind interne Makros, die
make
jedesmal definiert, wenn es eine Anweisung ausführt.
Ein anderes internes Makro ist $*, das den Namen der Eingabedatei ohne das
Suffix erzeugt. Wenn die Eingabedatei also
edit.c
heißt, wird der String $*.s zu
edit.s
expandiert (eine Assemblercodedatei).
Ein Beispiel für eine nützliche Anwendung, das mit der Pattern-Regel
aber nicht mit einer Suffix-Regel funktioniert: Hängen Sie die
Zeichenfolge _dbg an den Namen der Ausgabedatei an, damit Sie später noch
wissen, daß dieses Programm mit Debugging-Informationen kompiliert
wurde:
Jetzt können Sie alle Objektdateien einmal mit und einmal ohne
Debugging-Informationen kompilieren. Weil die Dateinamen unterschiedlich sind,
können Sie alle Versionen in einem Verzeichnis halten.
In einem Makefile können beliebige Shell-Befehle ausgeführt werden.
Die Lage wird allerdings dadurch kompliziert, daß
make
jeden Befehl in einer anderen Shell ausführt. So gelangen Sie also nicht
ans Ziel:
Weder der Befehl
cd
noch die Definition der Variablen HOST_DIR wirken sich auf die folgenden
Befehle aus. Sie müssen das Ganze zu einem einzigen Befehl
zusammenfassen. Die Shell benutzt das Semikolon als Trennzeichen zwischen
Befehlen; die Befehlszeile sieht dann so aus:
Noch eine Änderung: Wenn Sie innerhalb des Befehls eine Shell-Variable
definieren und benutzen, müssen Sie zwei Dollarzeichen voranstellen.
make
erkennt daran, daß hier eine Shell-Variable und nicht ein Makro gemeint
ist.
Vielleicht ist die Datei einfacher zu lesen, wenn Sie die einzelnen
Bestandteile eines Mehrfach-Befehls jeweils in eine neue Zeile schreiben;
schließen Sie dann jede Zeile mit einem Backslash ab, damit
make
das Ganze als eine zusammenhängende Zeile betrachtet:
Kompliziert, aber sinnvoll.
Manche Makefiles enthalten wiederum einen
make
-Befehl; das nennt man rekursives
make
. So sieht es aus:
Das Makro $(MAKE) ruft
make
auf. Es gibt mehrere Anwendungen für geschachtelte
make
s. Unser Beispiel zeigt eine Möglichkeit -- ein Compilerlauf, der sich
auf verschiedene Verzeichnisse erstreckt (dabei muß jedes dieser
Verzeichnisse ein eigenes Makefile enthalten). Eine andere Anwendung ist die
Definition von Makros in der Befehlszeile, so daß Compilerläufe mit
unterschiedlichen Makrodefinitionen stattfinden können.
GNU-
make
bietet als Erweiterung ein weiteres mächtiges Interface mit der
Befehlszeile. Sie können einen Shell-Befehl aufrufen und einem Makro das
Ergebnis des Aufrufs zuweisen. Im Makefile zum Linux-Kernel wird diese Methode
benutzt, aber wir wollen Ihnen hier ein einfaches Beispiel zeigen:
Damit weisen Sie dem Makro HOST_NAME den Namen Ihres Rechners im Netzwerk zu
(nämlich die Ausgabe des Befehls
uname -n
).
make
befolgt ein paar Konventionen, die manchmal ganz praktisch sind. So erreichen
Sie z.B. mit dem Klammeraffen (@) vor einem Befehl, daß
make
bei der Ausführung den Befehl selbst anzeigt:
Eine andere Möglichkeit besteht darin, einen Bindestrich vor einen Befehl
zu setzen; damit weisen Sie
make
an, selbst dann fortzufahren, wenn der Befehl nicht ausgeführt werden
konnte. Das kann z.B. dann nützlich sein, wenn
make
auch nach einem fehlgeschlagenen
mv
oder
cp
weiterarbeiten soll:
Bei großen Projekten hat man es oft mit vielen Makefiles zu tun. Das
erleichtert die gemeinsame Nutzung z.B. von Makrodefinitionen durch etliche
Makefiles in verschiedenen Verzeichnissen. Mit der Anweisung:
lesen Sie den Inhalt von
Dateiname
ein. Auch dies wird im Makefile des Linux-Kernels benutzt. Ein Beispiel:
Wenn Sie sich die Datei
.depend
anschauen, finden Sie dort einige Makefile-Einträge; genauer gesagt
Zeilen, in denen erklärt wird, daß Objektdateien von Header-Dateien
abhängen. (Es könnte übrigens sein, daß
.depend
noch nicht existiert -- diese Datei wird durch einen weiteren Eintrag im
Makefile erzeugt.)
Manchmal beziehen sich include-Zeilen auf Makros statt auf Dateinamen, etwa
so:
In diesem Fall muß INC_FILE entweder als Environment-Variable oder als
ein Makro definiert sein. Auf diese Weise können Sie noch genauer
bestimmen, welche Datei benutzt wird.
Makros
OBJECTS = main.o edit.o
edimh: $(OBJECTS)
gcc -o edimh $(OBJECTS)
ROOT = /usr/local
HEADERS = $(ROOT)/include
SOURCES = $(ROOT)/src
DRIVERS =drivers/block/block.a
ifdef CONFIG_SCSI
DRIVERS := $(DRIVERS) drivers/scsi/scsi.a
endif
drivers/block/block.a drivers/scsi/scsi.a
CONFIG_SCSI = yes
papaya$ make CONFIG_SCSI=yes ziel
export CONFIG_SCSI=yes
setenv CONFIG_SCSI yes
Suffix-Regeln und Pattern-Regeln
.c.o:
gcc -c ${CFLAGS} $<
papaya$ make CFLAGS="-O -g" edit.o
gcc -c -O -g edit.c
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe
papaya$ make CFLAGS="-DDEBUG -DBSD" ...
%.o: %.c
gcc -c -o $@ $(CFLAGS) $<
%_dbg.o: %.c
gcc -c -g -o $@ $(CFLAGS) $<
DEBUG_OBJECTS = main_dbg.o edit_dbg.o
edimh_dbg: $(DEBUG_OBJECTS)
gcc -o $@ $(DEBUG_OBJECTS)
papaya$ make edimh_dbg
gcc -c -g -o main_dbg.o main.c
gcc -c -g -o edit_dbg.o edit.c
gcc -o edimh_dbg main_dbg.o edit_dbg.o
Mehrfach-Befehle
target:
cd obj
HOST_DIR=/home/e
mv *.o $HOST_DIR
target:
cd obj ; HOST_DIR=/home/e ; mv *.o $$HOST_DIR
target:
cd obj ; \
HOST_DIR=/home/e ; \
mv *.o $$HOST_DIR
linuxsubdirs: dummy
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
HOST_NAME = $(shell uname -n)
@if [ -x /bin/dnsdomainname ]; then \
echo #define LINUX_COMPILE_DOMAIN \"`dnsdomainname`\"; \
else \
echo #define LINUX_COMPILE_DOMAIN \"`domainname`\"; \
fi >> tools/version.h
- mv edimh /usr/local
- mv readimh /usr/local
Andere Makefiles einbinden
include dateiname
include .depend
include ${INC_FILE}
Vorherige
Abschnitt
Nächste Abschnitt