Was ist der Unterschied zwischen Prozent und Asterisk (Stern) Makefile Voraussetzung

Was ist der Unterschied zwischen Prozent und Asterisk (Stern) Makefile Voraussetzung

Ich versuche zu verstehen, warum einige Makefiles Voraussetzungen mit haben %.txtund 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 %.txtals 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 makewird 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 .cnicht 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 .cDatei 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.

verwandte Informationen