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

CSS-Tipps zur Implementierung der Chrome-Tab-Leiste

Dieses Mal schauen wir uns ein Navigationsleisten...

CSS erreicht hochadaptiven Vollbildmodus

Beim Schreiben meiner eigenen Demo möchte ich dis...

React implementiert Import und Export von Excel-Dateien

Inhaltsverzeichnis Präsentationsschicht Geschäfts...

Detaillierte Erläuterung der TCPdump-Befehlsbeispiele in Linux

Vorwort Einfach ausgedrückt ist tcpdump ein Paket...

So stellen Sie Confluence und Jira-Software in Docker bereit

Version: centos==7.2 jdk==1.8 Zusammenfluss == 6....

JS implementiert einfache Addition und Subtraktion von Warenkorbeffekten

In diesem Artikelbeispiel wird der spezifische JS...

Implementierung einer kreisförmigen CSS-Aushöhlung (Gutschein-Hintergrundbild)

In diesem Artikel werden hauptsächlich kreisförmi...

Schritt-für-Schritt-Anleitung zum Erstellen einer Kalenderkomponente mit React

Inhaltsverzeichnis Betriebswirtschaftlicher Hinte...

Tutorial zur Installation und Konfiguration von VMware Tools für Ubuntu

Vor einiger Zeit hat der Blogger das Ubuntu-Syste...

W3C Tutorial (3): W3C HTML Aktivitäten

HTML ist eine Hybridsprache, die zum Veröffentlic...

Warum ich Nginx als Backend-Server-Proxy empfehle (Gründeanalyse)

1. Einleitung Unsere realen Server sollten nicht ...

Vue definiert private Filter und grundlegende Nutzung

Die Methoden und Konzepte privater und globaler F...