Wenn Sie eine Aufgabe ausführen oder aktualisieren möchten, wenn bestimmte Dateien aktualisiert werden, muss die Datei make Dienstprogramm kann sich als nützlich erweisen. Das make Dienstprogramm erfordert eine Datei, Makefile (oder makefile ), die eine Reihe von auszuführenden Aufgaben definiert. Möglicherweise haben Sie make verwendet um ein Programm aus dem Quellcode zu kompilieren. Die meisten Open-Source-Projekte verwenden make um eine endgültige ausführbare Binärdatei zu kompilieren, die dann mit make install installiert werden kann .
In diesem Artikel untersuchen wir make und Makefile mit einfachen und fortgeschrittenen Beispielen. Bevor Sie beginnen, stellen Sie sicher, dass make auf Ihrem System installiert ist.
Einfache Beispiele
Beginnen wir damit, den Klassiker „Hello World“ auf dem Terminal auszudrucken. Erstellen Sie ein leeres Verzeichnis myproject enthält eine Datei Makefile mit diesem Inhalt:
say_hello:
Echo "Hallo Welt"
Führen Sie nun die Datei aus, indem Sie make eingeben innerhalb des Verzeichnisses myproject . Die Ausgabe wird sein:
$ make
echo "Hallo Welt"
Hallo Welt
Im obigen Beispiel say_hello verhält sich wie ein Funktionsname, wie in jeder Programmiersprache. Dies wird als Ziel bezeichnet . Die Voraussetzungen oder Abhängigkeiten dem Ziel folgen. Der Einfachheit halber haben wir in diesem Beispiel keine Voraussetzungen definiert. Der Befehl echo "Hello World" wird das Rezept genannt . Das Rezept verwendet Voraussetzungen um ein Ziel zu machen . Das Ziel, die Voraussetzungen und die Rezepte ergeben zusammen eine Regel .
Zusammenfassend ist unten die Syntax einer typischen Regel:
Ziel:VoraussetzungenRezept
Beispielsweise könnte ein Ziel eine Binärdatei sein, die von Voraussetzungen abhängt (Quelldateien). Andererseits kann eine Voraussetzung auch ein Ziel sein, das von anderen Abhängigkeiten abhängt:
final_target:sub_target final_target.c
Recipe_to_create_final_target
sub_target:sub_target.c
Recipe_to_create_sub_target
Das Ziel muss keine Datei sein; es könnte auch nur ein Name für das Rezept sein, wie in unserem Beispiel. Wir nennen diese "falschen Ziele".
Zurück zum obigen Beispiel, wenn make ausgeführt wurde, der gesamte Befehl echo "Hello World" wurde angezeigt, gefolgt von der eigentlichen Befehlsausgabe. Das wollen wir oft nicht. Um das Echo des eigentlichen Befehls zu unterdrücken, müssen wir echo starten mit @ :
say_hello:
@echo "Hallo Welt"
Versuchen Sie nun, make auszuführen wieder. Die Ausgabe sollte nur Folgendes anzeigen:
$ make
Hallo Welt
Lassen Sie uns ein paar weitere falsche Ziele hinzufügen:generate und clean zum Makefile :
say_hello:
@echo "Hello World"
generate:
@echo "Leere Textdateien erstellen..."
touch file-{1. .10}.txt
clean:
@echo "Aufräumen..."
rm *.txt
Wenn wir versuchen, make auszuführen nach den Änderungen nur noch das Ziel say_hello wird durchgeführt. Das liegt daran, dass nur das erste Ziel im Makefile das Standardziel ist. Wird oft als Standardziel bezeichnet , das ist der Grund, warum Sie all sehen werden als erstes Ziel in den meisten Projekten. Es liegt in der Verantwortung von all andere Ziele anzurufen. Wir können dieses Verhalten überschreiben, indem wir ein spezielles falsches Ziel namens .DEFAULT_GOAL verwenden .
Fügen wir das am Anfang unseres Makefiles ein:
.DEFAULT_GOAL := generate
Dadurch wird das Ziel generate ausgeführt als Standard:
$ make
Leere Textdateien erstellen...
touch file-{1..10}.txt
Wie der Name schon sagt, das falsche Ziel .DEFAULT_GOAL kann nur ein Ziel gleichzeitig ausführen. Aus diesem Grund enthalten die meisten Makefiles all als Ziel, das so viele Ziele wie nötig aufrufen kann.
Nehmen wir das falsche Ziel all auf und entfernen Sie .DEFAULT_GOAL :
all:say_hello generate
say_hello:
@echo "Hello World"
generate:
@echo "Leere Textdateien werden erstellt.. ."
touch file-{1..10}.txt
clean:
@echo "Cleaning up..."
rm *.txtVor dem Ausführen von
make, fügen wir ein weiteres spezielles falsches Ziel ein,.PHONY, wo wir alle Ziele definieren, die keine Dateien sind.makeführt sein Rezept aus, unabhängig davon, ob eine Datei mit diesem Namen existiert oder wann sie zuletzt geändert wurde. Hier ist das komplette Makefile:.PHONY:alle say_hello generieren sauber
all:say_hello generieren
say_hello:
@echo "Hello World"
generate:
@echo "Leere Textdateien erstellen..."
touch file-{1..10}.txt
clean:
@echo "Cleaning hoch..."
rm *.txtDas
makesolltesay_helloaufrufen undgenerate:$ make
Hallo Welt
Leere Textdateien werden erstellt...
touch file-{1..10}.txtEs empfiehlt sich,
cleannicht aufzurufen inalloder setzen Sie es als erstes Ziel.cleansollte manuell aufgerufen werden, wenn eine Reinigung als erstes Argument fürmakeerforderlich ist :$ make clean
Aufräumen...
rm *.txtNachdem Sie nun eine Vorstellung davon haben, wie ein einfaches Makefile funktioniert und wie man ein einfaches Makefile schreibt, wollen wir uns einige fortgeschrittenere Beispiele ansehen.
Erweiterte Beispiele
Variablen
Weitere Linux-Ressourcen
- Spickzettel für Linux-Befehle
- Spickzettel für fortgeschrittene Linux-Befehle
- Kostenloser Online-Kurs:RHEL Technical Overview
- Spickzettel für Linux-Netzwerke
- SELinux-Spickzettel
- Spickzettel für allgemeine Linux-Befehle
- Was sind Linux-Container?
- Unsere neuesten Linux-Artikel
Im obigen Beispiel sind die meisten Ziel- und Voraussetzungswerte hartcodiert, aber in echten Projekten werden diese durch Variablen und Muster ersetzt.
Der einfachste Weg, eine Variable in einem Makefile zu definieren, ist die Verwendung von = Operator. Zum Beispiel, um den Befehl gcc zuzuweisen in eine Variable CC :
CC = gcc
Dies wird auch als rekursive erweiterte Variable bezeichnet , und es wird in einer Regel wie unten gezeigt verwendet:
Hallo:hallo.c
${CC} hello.c -o hallo
Wie Sie vielleicht erraten haben, wird das Rezept wie folgt erweitert, wenn es an das Terminal übergeben wird:
gcc hello.c -o hello
Beide ${CC} und $(CC) sind gültige Verweise auf den Aufruf von gcc . Wenn man jedoch versucht, eine Variable sich selbst neu zuzuweisen, führt dies zu einer Endlosschleife. Lassen Sie uns das überprüfen:
CC =gcc
CC =${CC}
alle:
@echo ${CC}
Ausführen von make ergibt:
$ make
Makefile:8:*** Rekursive Variable 'CC' verweist (eventuell) auf sich selbst. Stopp.
Um dieses Szenario zu vermeiden, können wir den := verwenden -Operator (dies wird auch als einfach erweiterte Variable bezeichnet ). Wir sollten kein Problem haben, das folgende Makefile auszuführen:
CC :=gcc
CC :=${CC}
alle:
@echo ${CC}
Muster und Funktionen
Das folgende Makefile kann alle C-Programme kompilieren, indem es Variablen, Muster und Funktionen verwendet. Sehen wir es uns Zeile für Zeile an:
# Verwendung:
# make # alle Binärdateien kompilieren
# make clean # ALLE Binärdateien und Objekte entfernen
.PHONY =all clean
CC =gcc # zu verwendender Compiler
LINKERFLAG =-lm
SRCS :=$(Wildcard *.c)
BINS :=$(SRCS:%. c=%)
alle:${BINS}
%:%.o
@echo "Überprüfe...."
${CC} ${LINKERFLAG} $<-o $@
%.o:%.c
@echo "Objekt erstellen.."
${CC} -c $<
clean:
@echo "Aufräumen..."
rm -rvf *.o ${BINS}
-
Zeilen beginnend mit
#sind Kommentare. -
Zeile
.PHONY = all cleandefiniert falsche Zieleallundclean. -
Variable
LINKERFLAGdefiniert Flags, die mitgccverwendet werden sollen in einem Rezept. -
SRCS := $(wildcard *.c):$(wildcard pattern)ist eine der Funktionen für Dateinamen . In diesem Fall alle Dateien mit dem.cErweiterung wird in einer VariablenSRCSgespeichert . -
BINS := $(SRCS:%.c=%):Dies wird als Substitutionsreferenz bezeichnet . Wenn in diesem FallSRCShat Werte'foo.c bar.c',BINSwird'foo bar'haben . -
Zeile
all: ${BINS}:Das falsche Zielallruft Werte in${BINS}auf als individuelle Ziele. -
Regel:
%:%.o
@echo "Überprüfe...."
${CC} ${LINKERFLAG} $< -o $@Schauen wir uns ein Beispiel an, um diese Regel zu verstehen. Angenommen
fooist einer der Werte in${BINS}. Dann%entsprichtfoo(%kann mit jedem Zielnamen übereinstimmen). Unten ist die Regel in ihrer erweiterten Form:foo:foo.o
@echo "Überprüfe...."
gcc -lm foo.o -o fooWie gezeigt,
%wird durchfooersetzt .$<wird durchfoo.oersetzt .$<ist so strukturiert, dass es den Voraussetzungen und$@entspricht entspricht dem Ziel. Diese Regel wird für jeden Wert in${BINS}aufgerufen -
Regel:
%.o:%.c
@echo "Objekt erstellen.."
${CC} -c $<Jede Voraussetzung in der vorherigen Regel wird als Ziel für diese Regel betrachtet. Unten ist die Regel in ihrer erweiterten Form:
foo.o:foo.c
@echo "Objekt erstellen.."
gcc -c foo.c -
Schließlich entfernen wir alle Binärdateien und Objektdateien im Ziel
clean.
Unten ist die Umschreibung des obigen Makefiles, vorausgesetzt, es befindet sich in dem Verzeichnis mit einer einzigen Datei foo.c:
# Verwendung:
# make # alle Binärdateien kompilieren
# make clean # ALLE Binärdateien und Objekte entfernen
.PHONY =all clean
CC =gcc # zu verwendender Compiler
LINKERFLAG =-lm
SRCS :=foo.c
BINS :=foo
all :foo
foo:foo.o
@echo "Überprüfe...."
gcc -lm foo.o -o foo
foo.o :foo.c
@echo "Objekt erstellen.."
gcc -c foo.c
clean:
@echo "Aufräumen..."
rm -rvf foo.o foo
Weitere Informationen zu Makefiles finden Sie im GNU Make-Handbuch, das eine vollständige Referenz und Beispiele bietet.
Sie können auch unsere Einführung in GNU Autotools lesen, um zu erfahren, wie Sie die Generierung eines Makefiles für Ihr Programmierprojekt automatisieren können.