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.make
fü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
make
solltesay_hello
aufrufen undgenerate
:$ make
Hallo Welt
Leere Textdateien werden erstellt...
touch file-{1..10}.txtEs empfiehlt sich,
clean
nicht aufzurufen inall
oder setzen Sie es als erstes Ziel.clean
sollte manuell aufgerufen werden, wenn eine Reinigung als erstes Argument fürmake
erforderlich 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 clean
definiert falsche Zieleall
undclean
. -
Variable
LINKERFLAG
definiert Flags, die mitgcc
verwendet werden sollen in einem Rezept. -
SRCS := $(wildcard *.c)
:$(wildcard pattern)
ist eine der Funktionen für Dateinamen . In diesem Fall alle Dateien mit dem.c
Erweiterung wird in einer VariablenSRCS
gespeichert . -
BINS := $(SRCS:%.c=%)
:Dies wird als Substitutionsreferenz bezeichnet . Wenn in diesem FallSRCS
hat Werte'foo.c bar.c'
,BINS
wird'foo bar'
haben . -
Zeile
all: ${BINS}
:Das falsche Zielall
ruft 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
foo
ist 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 durchfoo
ersetzt .$<
wird durchfoo.o
ersetzt .$<
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.