makefile Tutorial
Erste Schritte mit Makefile
Suche…
Bemerkungen
Ein Makefile ist eine Textdatei, die den Betrieb des make
Programms steuert. Das make
Programm wird normalerweise zum Verwalten der Erstellung von Programmen aus den Quelldateien verwendet. Es kann jedoch allgemeiner für die Verarbeitung von Prozessen verwendet werden, bei denen Dateien (oder Ziele ) nach dem Ändern anderer Dateien (oder Voraussetzungen ) neu erstellt werden müssen. Das Makefile beschreibt die Beziehung zwischen Zielen und Voraussetzungen und gibt außerdem die Befehle an, die erforderlich sind, um das Ziel auf den neuesten Stand zu bringen, wenn sich eine oder mehrere der Voraussetzungen geändert haben. Die einzige Möglichkeit, die make
für "out of date-ness" hält, besteht im Vergleich der Änderungszeit von Zieldateien und deren Voraussetzungen.
Makefiles sind in mancher Hinsicht einzigartig, was anfangs verwirrend sein kann.
Erstens besteht ein Makefile aus zwei völlig verschiedenen Programmiersprachen in derselben Datei. Der Großteil der Datei ist in einer Sprache geschrieben, make
verständlich ist: Diese bietet variable Zuweisung und Erweiterung, einige Präprozessorfunktionen (einschließlich anderer Dateien, bedingtes Parsing von Abschnitten der Datei usw.) sowie die Definition der Ziele und ihrer Ziele Voraussetzungen. Darüber hinaus kann jedem Ziel ein Rezept zugeordnet werden, das angibt, welche Befehle aufgerufen werden sollen, um das Ziel auf den neuesten Stand zu bringen. Das Rezept wird als Shellskript geschrieben (standardmäßig POSIX sh). Das make
Programm analysiert dieses Skript nicht: Es führt eine Shell aus und übergibt das Skript an die Shell, die ausgeführt werden soll. Die Tatsache, dass Rezepte nicht nach make
analysiert werden, sondern von einem separaten Shell-Prozess verarbeitet werden, ist für das Verständnis von Makefiles von zentraler Bedeutung.
Zweitens ist ein Makefile keine prozedurale Sprache wie ein Skript: Wenn make
das Makefile analysiert, erstellt es intern einen gerichteten Graphen, in dem Ziele die Knoten des Graphen sind und die vorausgesetzten Beziehungen die Kanten sind. Erst nachdem alle Makefiles vollständig analysiert worden sind und die Graph abgeschlossen wird make
einen Knoten (Ziel) auswählen und versuchen, auf dem neuesten Stand zu bringen. Um sicherzustellen, dass ein Ziel auf dem neuesten Stand ist, muss es zunächst sicherstellen, dass alle Voraussetzungen dieses Ziels auf dem neuesten Stand sind, und so weiter, und zwar rekursiv.
Versionen
Name | Auch bekannt als | Erste Version | Ausführung | Veröffentlichungsdatum |
---|---|---|---|---|
POSIX machen | 1992 | IEEE Std 1003.1-2008, Ausgabe 2016 | 2016-09-30 | |
NetBSD machen | bmake | 1988 | 20160926 | 2016-09-26 |
GNU machen | gmake | 1988 | 4.2.1 | 2016-06-10 |
SunPro machen | dmake | 2006 | 2015-07-13 | |
MSVS nmake | 2003 | 2015p3 | 2016-06-27 |
Grundlegendes Makefile
Erwägen Sie, eine "Hallo Welt" zu schreiben. Programm in c. Nehmen wir an, unser Quellcode befindet sich in einer Datei namens source.c. Um unser Programm auszuführen, müssen wir es kompilieren. Normalerweise müssen Sie unter Linux (mithilfe von gcc) $> gcc source.c -o output
wo die Ausgabe erfolgt ist der Name der zu generierenden ausführbaren Datei. Für ein Basisprogramm funktioniert dies gut, aber wenn Programme komplexer werden, kann unser Kompilierungsbefehl auch komplexer werden. Hier kommt ein Makefile ins Spiel . Mit Makefiles können wir ziemlich komplexe Regeln für das Kompilieren eines Programms ausarbeiten und es einfach durch Eingabe von make in der Befehlszeile kompilieren. Zum Beispiel ist hier ein mögliches Beispiel-Makefile für das Hallo-Beispiel oben.
Grundlegendes Makefile
Lassen Sie uns ein einfaches Makefile erstellen und in unserem System im selben Verzeichnis wie unser Quellcode mit dem Namen Makefile speichern. Beachten Sie, dass diese Datei Makefile genannt werden muss, das Capitol M ist jedoch optional. Es ist jedoch relativ üblich, ein Capitol M zu verwenden.
output: source.c
gcc source.c -o output
Beachten Sie, dass sich vor dem Befehl gcc in der zweiten Zeile genau eine Registerkarte befindet (dies ist wichtig für Makefiles). Sobald dieses Makefile jedes Mal geschrieben wird, wenn der Benutzer make (in demselben Verzeichnis wie das Makefile) make macht, wird überprüft, ob source.c geändert wurde (prüft den Zeitstempel), ob es vor der Ausführung geändert wurde die Kompilierungsregel in der folgenden Zeile.
Variablen in Makefiles
Je nach Projekt möchten Sie möglicherweise einige Variablen in Ihre Make-Datei einfügen. Hier ist ein Beispiel-Makefile mit vorhandenen Variablen.
CFLAGS = -g -Wall
output: source.c
gcc $< $(CFLAGS) -o $@
Lasst uns jetzt erkunden, was hier passiert ist. In der ersten Zeile haben wir eine Variable namens CFLAGS deklariert, die mehrere allgemeine Flags enthält, die Sie möglicherweise an den Compiler übergeben möchten. Beachten Sie, dass Sie in dieser Variablen beliebig viele Flags speichern können. Dann haben wir die gleiche Zeile wie vorher und sagen, dass make.c überprüfen soll, ob es sich in letzter Zeit geändert hat als die Ausgabe. Wenn dies der Fall ist, wird die Kompilierungsregel ausgeführt. Unsere Kompilierungsregel ist größtenteils dieselbe wie zuvor, wurde jedoch durch Verwendung von Variablen verkürzt. Die Variable $<
ist in make integriert (wird als automatische Variable bezeichnet. Siehe https://www.gnu.org/software/make/manual/ html_node / Automatic-Variables.html ) und es steht immer für die Quelle, also in diesem Fall source.c . $(CFLAGS)
ist unsere Variable, die wir zuvor definiert haben. Beachten Sie jedoch, dass wir die Variable in Klammern mit einem $ wie diesem $(someVariable)
. Dies ist die Syntax, mit der Sie Make sagen können, um die Variable auf das zu erweitern, was Sie zuvor eingegeben haben. Schließlich haben wir noch das $ @ -Symbol. Dies ist wiederum eine in make eingebaute Variable. Sie steht einfach für das Ziel des Übersetzungsschritts und steht in diesem Fall für die Ausgabe .
Sauber
Bereinigen ist ein weiteres nützliches Konzept, um das Erstellen von Dateien zu erlernen. Lass das Makefile von oben verändern
CFLAGS = -g -Wall
TARGETS = output
output: source.c
gcc $< $(CFLAGS) -o $@
clean:
rm $(TARGETS)
Wie Sie sehen, haben wir unserem Makefile einfach eine weitere Regel hinzugefügt und eine weitere Variable, die alle unsere Ziele enthält. Dies ist eine etwas gängige Regel für Makefiles, da Sie alle von Ihnen erzeugten Binaries schnell entfernen können, indem Sie einfach $> make clean
eingeben. Wenn Sie make clean eingeben, weisen Sie das make-Programm an, die Clean-Regel auszuführen, und dann führt make den Befehl rm aus, um alle Ziele zu löschen.
Ich hoffe, dieser kurze Überblick über die Verwendung von make hilft Ihnen dabei, Ihren Workflow zu beschleunigen. Makefiles können sehr komplex werden. Mit diesen Ideen sollten Sie jedoch in der Lage sein, make zu verwenden und ein besseres Verständnis dafür zu haben, was in anderen Makefiles für Programmierer geschieht . Weitere Informationen zur Verwendung von make finden Sie unter https://www.gnu.org/software/make/manual/ .
Regeln definieren
Schnellstart
Eine Regel beschreibt, wann und wie bestimmte Dateien ( Regelziele ) erstellt werden. Sie kann auch dazu dienen, eine Zieldatei zu aktualisieren, wenn eine der Dateien, die für ihre Erstellung benötigt werden ( Voraussetzungen des Ziels), neuer als das Ziel ist.
Regeln folgen der folgenden Syntax: (Beachten Sie, dass Befehle, die einer Regel folgen, durch einen Tabulator eingerückt werden.
targets: prerequisites
<commands>
Dabei sind Ziele und Voraussetzungen Dateinamen oder spezielle reservierte Namen und Befehle (falls vorhanden), die von einer Shell ausgeführt werden, um veraltete Ziele zu erstellen oder neu zu erstellen.
Um eine Regel auszuführen, können Sie einfach den Befehl make
im Terminal von demselben Verzeichnis aus ausführen make
in dem sich das Makefile befindet. Wenn Sie make
ohne Angabe des Ziels ausführen, wird die erste im Makefile definierte Regel ausgeführt. Normalerweise wird die erste Regel im Makefile häufig als all oder default bezeichnet . In der Regel werden alle gültigen Build-Ziele als Voraussetzungen aufgeführt.
make
führt die Regel nur aus, wenn das Ziel nicht mehr aktuell ist. Dies bedeutet, dass es nicht existiert oder die Änderungszeit älter ist als eine der Voraussetzungen. Wenn die Liste der Voraussetzungen leer ist, wird die Regel nur ausgeführt, wenn sie zum ersten Mal zum Erstellen der Ziele aufgerufen wird. Wenn die Regel jedoch keine Datei erstellt und das Ziel eine Dummy-Variable ist, wird die Regel immer ausgeführt.
Musterregeln
Musterregeln werden verwendet, um mehrere Ziele anzugeben und aus Zielnamen erforderliche Namen zu erstellen. Sie sind allgemeiner und leistungsfähiger als gewöhnliche Regeln, da jedes Ziel seine eigenen Voraussetzungen haben kann. In Musterregeln wird eine Beziehung zwischen einem Ziel und einer Voraussetzung auf der Grundlage von Präfixen einschließlich Pfadnamen und Suffixen oder beiden erstellt.
Stellen Sie sich vor, wir wollen die Ziele foo.o
und bar.o
, indem Sie die C-Skripts foo.c
bzw. bar.c
kompilieren. Dies kann unter Verwendung der folgenden normalen Regeln durchgeführt werden:
foo.o: foo.c
cc -c $< -o $@
bar.o: bar.c
cc -c $< -o $@
Dabei ist die automatische Variable $<
der Name der ersten Voraussetzung und $@
der Name des Ziels (eine vollständige Liste der automatischen Variablen finden Sie hier ).
Da die Ziele dasselbe Suffix verwenden, können die obigen beiden Regeln nun durch die folgende Musterregel ersetzt werden:
%.o: %.c
cc -c $< -o $@
Implizite Regeln
Implizite Regeln geben an make
wie mit üblichen Methoden bestimmte Arten von Zieldateien erstellt werden, die sehr häufig verwendet werden. make
verwendet den Namen der Zieldatei, um zu bestimmen, welche implizite Regel aufgerufen werden soll.
Das Musterregelbeispiel, das wir im vorherigen Abschnitt gesehen haben, muss nicht wirklich in einem Makefile deklariert werden, da make
eine implizite Regel für die C-Kompilierung hat. In der folgenden Regel werden daher die Voraussetzungen foo.o
und bar.o
unter Verwendung der impliziten Regel für die C-Kompilierung erstellt, bevor foo
.
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
Einen Katalog impliziter Regeln und der von ihnen verwendeten Variablen finden Sie hier .
generische Regel, um eine Datei zu komprimieren
Wenn ein Verzeichnis 2 Dateien enthält:
$ ls
makefile
example.txt
und makefile
enthalten den folgenden Text
%.gz: %
gzip $<
Dann können Sie example.txt.gz
indem Sie die Shell eingeben
$ make -f makefile example.txt.gz
die Make - Datei von nur einer Regel bestehen, machen anweisen , wie eine Datei , deren Name Ende mit gz zu erstellen , wenn eine Datei mit dem gleichen Namen , aber das gz Suffix ist.
makefile Hallo Welt
C: \ makefile:
helloWorld :
[TAB]echo hello world
Laufergebnisse:
C:\>make
echo hello world
hello world
Hinweis: [TAB] sollte durch eine tatsächliche Registerkarte ersetzt werden. Stackoverflow ersetzt Registerkarten durch Leerzeichen. Leerzeichen werden nicht wie Registerkarten in einem Makefile verwendet.