Detaillierte Erklärung zum Schreiben und Verwenden von Makefile unter Linux

Detaillierte Erklärung zum Schreiben und Verwenden von Makefile unter Linux

Makefile

Eine Projektdatei kann viele Quelldateien enthalten und verschiedene Funktionen und Module befinden sich in unterschiedlichen Verzeichnissen. Die herkömmliche Kompilierung kann solche Probleme nicht mehr effizient bewältigen. Um dieses Problem zu lösen, wird Makefile verwendet.

Sobald das Makefile geschrieben ist, wird nur ein Make -Befehl benötigt, um alle in der Makefile-Datei geschriebenen Anweisungen auszuführen und so die gesamte Projektdatei zu kompilieren, was die Effizienz erheblich verbessert .

make ist ein Befehlstool zum Interpretieren der Befehle im Makefile.

Makefile-Benennung und Regeln

Dateibenennung

Es kann entweder Makefile oder Makefile verwendet werden.

Makefile-Regeln

Die Befehlsregeln im Makefile lauten wie folgt:

xxx (Zieldatei): xxx (abhängige Datei)
( Tabulator ) Befehl (Shell-Befehl)
Unter diesen ist die Zieldatei die Datei, die am Ende generiert werden soll (außer Pseudozielen), die abhängige Datei ist die Datei, die zum Generieren der Zieldatei erforderlich ist, und der Befehl ist der Shell-Befehl.

Beachten Sie, dass vor dem Befehl ein Tabulatoreinzug stehen muss.

Zum Beispiel:

#Makefile
app: ac bc #Ziel: Hängt von gcc ab ac bc -o app #Beachten Sie die Einrückung am Anfang dieser Zeile

Nach dem Erstellen des obigen Makefile werden ac und bc im Verzeichnis in die Zieldatei app kompiliert.

Wie Makefiles funktionieren

Vor der Ausführung der Befehle im Makefile wird geprüft, ob die erforderlichen Abhängigkeitsdateien vorhanden sind.

Wenn es existiert : Führen Sie den Befehl aus

Wenn es nicht existiert : Überprüfen Sie andere Regeln, um festzustellen, ob es andere Regeln gibt, die die von der aktuellen Regel geforderten Abhängigkeiten erzeugen. Wenn ja, führen Sie die Befehle in der Regel aus.

Zum Beispiel:

#Makefile
App: Ao Bo
	gcc ao bo -o app
ao: ac
	gcc -c ac -o ao
bo: bc
	gcc -c bc -o bo

Wenn im obigen Makefile die App-Regel ausgeführt wird, wird festgestellt, dass die erforderlichen abhängigen Dateien ao und bo im aktuellen Verzeichnis nicht vorhanden sind. Daher wird nach unten geschaut, ob es andere Regeln zum Generieren dieser Datei gibt. Wenn die Regel ao gefunden wird, stellt sich heraus, dass es sich um die erforderliche Datei handelt. Daher wird gcc -c ac -o ao ausgeführt, und dasselbe gilt für bo.

Beim Ausführen der Befehle in den Regeln vergleicht Makefile die Änderungszeit der Zieldatei und der abhängigen Datei .<br /> Wenn die abhängige Datei neuer ist als die Zieldatei, d. h. wenn die abhängige Datei nach der letzten Zielgenerierung geändert wurde , wird die Zieldatei neu generiert.
Wenn die abhängige Datei vor dem Änderungszeitpunkt der Zieldatei liegt, das heißt, die abhängige Datei wurde seit der letzten Zielgenerierung nicht geändert , wird der entsprechende Befehl nicht ausgeführt.
Wenn Sie beispielsweise make zweimal für ein Makefile verwenden, wird beim zweiten Mal die Meldung make: "app" is already up to date angezeigt.

Wenn wir diese Funktion nutzen, können wir Abhängigkeiten und Ziele schrittweise generieren, also das zweite Makefile oben. Auf diese Weise führt make, wenn wir nur die ac-Datei ändern, nur die ao-Regeln und die app-Regeln erneut aus. Die bo-Regel wird nicht ausgeführt, da bc nicht geändert wurde. Dies kann die Ressourcenverschwendung erheblich reduzieren.

Makefile-Variablen

Obwohl durch das Obige die Duplizierung des kompilierten Codes reduziert werden kann, wird das Schreiben eines Makefiles sehr viel Zeit verschwenden, wenn ein Projekt 1.000 .c .h-Dateien enthält. Daher müssen wir einige Variablen berücksichtigen, um die Effizienz zu verbessern.

Variablen abrufen <br /> Wir verwenden $(Variablenname), um Variablen zu verwenden.

Benutzerdefinierte Variablen <br /> Wir verwenden Variablenname = Variablenwert, z. B. var = hallo, um die benötigten Variablen anzupassen.
Beispielsweise kann das erste Makefile oben wie folgt umgeschrieben werden:

#Makefile
rsc = ac bc
app: $(rsc) #Ziel: Hängt von gcc ab $(rsc) -o app #Beachten Sie die Einrückung am Anfang dieser Zeile

Vordefinierte Variablen <br /> Einige Variablen sind vom System vordefiniert und wir können sie direkt verwenden.
AR: Der Name des Archivpflegeprogramms. Der Standardwert ist ar
CC: Der Name des C-Compilers, der Standardwert ist cc
CXX: Der Name des C++-Compilers, der Standardwert ist g++
$@: Der vollständige Name des Ziels
$<: Der Name der ersten Abhängigkeitsdatei
$^: die Namen aller abhängigen Dateien
<br /> Um das Verständnis der folgenden Beispiele zu erleichtern, erklären wir kurz die Musterübereinstimmung im Makefile.
In %.o:%.c ist % ein Platzhalterzeichen , das mit einer Zeichenfolge übereinstimmt, während zwei % mit derselben Zeichenfolge übereinstimmen.
Beispielsweise kann das zweite Makefile oben wie folgt umgeschrieben werden:

#Makefile
rcs = ao bo
App: $(rcs)
	$(CC) $(rcs) -o $@
%.o: %.c #Die obige Regel führt diese Regel zweimal aus $(CC) -c $< -o $@

Makefile-Funktionen

Wir können sehen, dass das obige Makefile relativ einfach ist, aber es löst immer noch nicht das Problem der vielen Dateien im Projekt. Um rcs zu erhalten, müssen wir immer noch jede Datei eingeben, die kompiliert werden muss. Dann müssen wir Funktionen verwenden, um diese abhängigen Dateien für uns zu schreiben.

$(Platzhalter MUSTER. . .)
Die Funktion dieser Funktion besteht darin, Dateien eines bestimmten Typs in einem bestimmten Verzeichnis abzurufen.
Der Parameter PATTERN ist eine Datei eines bestimmten Typs in einem bestimmten Verzeichnis. Mehrere Verzeichnisse und mehrere Typen können durch Leerzeichen getrennt werden.
Der Rückgabewert ist eine Dateiliste mit mehreren Dateien, wobei die Dateinamen durch Leerzeichen getrennt sind.

Zum Beispiel:

$(wildcard ./*.c) gibt alle Dateien mit der Endung c im aktuellen Verzeichnis zurück.

$(patsubst Muster, Ersetzung, Text)
Die Aufgabe dieser Funktion besteht darin, herauszufinden, ob das Wort im Text dem Muster entspricht. Wenn ja, wird es durch Ersetzung ersetzt.
Das Muster kann Platzhalterzeichen % enthalten. Wenn der Ersetzungsvorgang auch % enthält, dann entspricht der %-Wert im Ersetzungsvorgang dem %-Wert im Muster.
Der Rückgabewert ist die ersetzte Zeichenfolge.

Zum Beispiel:

$(patsubst %.c, %.o, ac, bc) gibt ao, bo zurück.

Auf diese Weise kann unser obiges Beispiel wie folgt umgeschrieben werden:

#Makefile
rcs = $(Platzhalter ./*.c)
objs = (patsubst %.c, %.o, $(src))
App: $(Objekte)
	$(CC) $(Objs) -o $@
%.o: %.c #Die obige Regel führt diese Regel zweimal aus $(CC) -c $< -o $@

Regel zum Bereinigen von Makefiles

Nachdem wir den Befehl make ausgeführt haben, stellen wir fest, dass sich im aktuellen Verzeichnis viele Dateien mit der Endung o befinden, wir jedoch nur die endgültige Zieldatei app benötigen und die anderen redundant sind. Wie sollen wir damit umgehen? Die saubere Regel wird uns helfen, mit ihnen umzugehen.

sauber

Wir müssen nur die Bereinigungsregel am Ende des Makefiles hinzufügen, und die Befehle in der Bereinigungsregel können nach Abschluss jeder Kompilierung ausgeführt werden. wie:

#Makefile
rcs = $(Platzhalter ./*.c)
objs = (patsubst %.c, %.o, $(src))
App: $(Objekte)
	$(CC) $(Objs) -o $@
%.o: %.c #Die obige Regel führt diese Regel zweimal aus $(CC) -c $< -o $@
sauber:
	rm $(objs) -f #rm Befehl löschen -f iteratives Löschen

Sie werden jedoch feststellen, dass sich im aktuellen Verzeichnis eine zusätzliche saubere Zieldatei befindet. Die Makefile-Strategie wird weiterhin verwendet. Durch Vergleichen der Änderungszeit führen wir Clean oft rechtzeitig aus, können die Datei aber trotzdem nicht löschen. Dann benötigen wir die nächste Operation.

Wir definieren clean als Pseudoziel, also .PHONY:clean, dann wird die Zieldatei nicht generiert, es findet kein Vergleich statt und es wird jedes Mal ausgeführt.

Zum Beispiel:

#Makefile
rcs = $(Platzhalter ./*.c)
objs = (patsubst %.c, %.o, $(src))
App: $(Objekte)
	$(CC) $(Objs) -o $@
%.o: %.c #Die obige Regel führt diese Regel zweimal aus $(CC) -c $< -o $@
.PHONY: sauber #Pseudoziel sauber:
	rm $(objs) -f #rm Befehl löschen -f iteratives Löschen

Dies ist das Ende dieses Artikels über das Schreiben und Verwenden von Makefile unter Linux. Weitere relevante Inhalte zum Schreiben und Verwenden von Linux-Makefiles finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den verwandten Artikeln weiter unten. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Was ist Makefile in Linux? Wie funktioniert es?
  • Definition und Verwendung von Makefile-Befehlspaketen in Linux
  • Verständnis von Makefile unter Linux

<<:  Bootstrap 3.0 - Schaltflächenstil für Lernnotizen

>>:  Detaillierte Erläuterung der Vue + Axios-Anforderungsschnittstellenmethode und der Parameterübergabemethode

Artikel empfehlen

Was bedeutet Eingabetyp und wie kann die Eingabe begrenzt werden?

Gängige Methoden zur Begrenzung der Eingabe 1. Um ...

Verwendung des Docker-Systembefehlssatzes

Inhaltsverzeichnis Docker-System df Docker-System...

MySQL-Unterabfrage und Details zur Verknüpfungstabelle

Inhaltsverzeichnis 1. Was ist eine Unterabfrage? ...

So wählen Sie zwischen MySQL CHAR und VARCHAR

Inhaltsverzeichnis VARCHAR- und CHAR-Typen Abschl...

Detaillierte Erklärung des Skript-Debugging-Mechanismus in Bash

Ausführen des Skripts im Debugmodus Sie können da...

mysql5.7.21 UTF8-Kodierungsproblem und -Lösung in der Mac-Umgebung

1. Ziel: Ändern Sie den Wert des character_set_se...

MySQL-Kodierung utf8 und utf8mb4 utf8mb4_unicode_ci und utf8mb4_general_ci

Referenz: MySQL-Zeichensatzübersicht utf8mb4 wurd...

Mit CSS3 implementierter Gradienten-Folieneffekt

Ergebnisse erzielen Code html <div Klasse=&quo...

Vue3 basierend auf der Skript-Setup-Syntax $refs-Verwendung

Inhaltsverzeichnis 1. Vue2-Syntax 2. Nutzung von ...

Einfache Kapselung von Axios und Beispielcode zur Verwendung

Vorwort Als ich kürzlich ein Projekt erstellte, d...