Ich versuche zu verstehen, warum einige Makefiles Voraussetzungen mit haben %.txt
und andere *.txt
.
Ich habe dieses Ordnerlayout erstellt.
$ tree .
.
├── hi1.txt
├── hi2.txt
├── hi3.txt
└── Makefile
Zuerst habe ich dies versucht.
foo.txt: *.txt
echo $^
Und es macht, was ich erwarte.
$ make
echo hi1.txt hi2.txt hi3.txt
hi1.txt hi2.txt hi3.txt
Aber dann habe ich gesehen, dass einige Makefiles %.txt
als Platzhalter verwendet werden. Also habe ich das als nächstes versucht.
foo.txt: %.txt
echo $^
Dies führt jedoch zu einem Fehler.
$ make
make: *** No rule to make target '%.txt', needed by 'foo.txt'. Stop.
Kann jemand erklären, warum das passiert?
GNU Make 4.3
Antwort1
In make
wird das Prozentzeichen zur Musterübereinstimmung verwendet und es erfordert eines im Ziel sowie (mindestens) eines in den Voraussetzungen:
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
Mit diesem Makefile geben wir an, dass Sie, um etwas zu erstellen, dessen Dateiname mit endet .o
, eine Datei mit demselben Präfix benötigen, die dann aber mit endet und .c
nicht mit.o
Um diese Regeln erstellen zu können, müssen Sie natürlich sowohl auf das Ziel als auch auf die Voraussetzungen verweisen können. Hier kommen die Variablen $@
und ins Spiel. bedeutet „das Ziel dieser Regel“ und bedeutet „die erste aufgeführte Voraussetzung dieser Regel“. Wenn Sie einen Befehl erstellen müssen, der verwendet$<
$@
$<
alleVoraussetzungen (z. B. um eine ausführbare Datei zu verknüpfen), dann können Sie die Variable verwenden $^
:
%: %.o lib.o
$(CC) $(LDFLAGS) -o $@ $^
Wenn Sie die beiden obigen Beispiel-Makefile-Ausschnitte in einem Makefile kombinieren und Sie im selben Verzeichnis eine Datei „lib.c“ mit allgemeinem Code haben, den Sie in mehreren C-Programmen verwenden möchten, können Sie eine beliebige .c
Datei hinzufügen, sagen wir foo.c
, und sie in ein Programm kompilieren foo
, das auch den Code in verlinkt lib.c
, ohne dass Änderungen an Ihrem Makefile erforderlich sind.
Beachten Sie, dass es auch Muster mit demselben Ziel geben kann, solange die Voraussetzungen unterschiedlich sind. Folgendes funktioniert beispielsweise:
%.o: %.c
$(CC).....
%.o: %.cpp
$(CXX).....
Das heißt, es funktioniert wie erwartet, solange Sie in diesem Verzeichnis keine C++-Quelldateien haben, die zufällig denselben Namen (ohne Erweiterung) wie eine C-Quelldatei haben. Sollte dies der Fall sein, wird die C++-Version ignoriert und stattdessen die C-Quelle kompiliert (weil die C-Regel zuerst im Makefile aufgeführt ist).
Weitere Informationen finden Sie imrelevanter Abschnittim GNU-Make-Handbuch.