Frage Was ist der Zweck von .PHONY in einem Makefile?


Was macht .PHONY meinst du in einem Makefile? Ich bin durchgegangen Diesaber es ist zu kompliziert.

Kann mir das jemand in einfachen Worten erklären?


1207
2018-01-27 09:08


Ursprung


Antworten:


Makefile-Ziele sind standardmäßig "Dateiziele" - sie werden verwendet, um Dateien aus anderen Dateien zu erstellen. Make nimmt an, dass sein Ziel eine Datei ist, und das macht das Schreiben von Makefiles relativ einfach:

foo: bar
  create_one_from_the_other foo bar

Manchmal möchten Sie jedoch, dass Ihr Makefile Befehle ausführt, die keine physischen Dateien im Dateisystem darstellen. Gute Beispiele dafür sind die gemeinsamen Ziele "sauber" und "alles". Wahrscheinlichkeiten sind das nicht, aber du kann Möglicherweise haben Sie eine Datei namens clean in deinem Hauptverzeichnis. In einem solchen Fall wird Make verwirrt sein, da standardmäßig die clean target würde mit dieser Datei verknüpft sein und Make wird nur dann ausgeführt, wenn die Datei bezüglich ihrer Abhängigkeiten nicht auf dem neuesten Stand zu sein scheint.

Diese speziellen Ziele werden aufgerufen falsch und Sie können explizit angeben, dass sie nicht mit Dateien verknüpft sind, z.

.PHONY: clean
clean:
  rm -rf *.o

Jetzt make clean wird wie erwartet ausgeführt, auch wenn Sie eine Datei namens haben clean.

In Bezug auf Make ist ein falsches Ziel einfach ein Ziel, das immer veraltet ist, also immer wenn du fragst make <phony_target>, es wird ausgeführt, unabhängig vom Status des Dateisystems. Einige üblich make Ziele, die oft falsch sind, sind: all, install, clean, distclean, TAGS, info, check.


1341
2018-01-27 09:11



Nehmen wir an, Sie haben install Ziel, das in Makefiles sehr häufig vorkommt. Wenn Sie tun nicht benutzen .PHONYund eine Datei mit dem Namen install existiert im selben Verzeichnis wie das Makefile make install Wird besorgt nichts. Dies liegt daran, dass Make die Regel so interpretiert, dass "das Rezept so und so ausgeführt wird, um die genannte Datei zu erstellen install"Da die Datei bereits vorhanden ist und sich ihre Abhängigkeiten nicht geändert haben, wird nichts unternommen.

Aber wenn du das machst install Ziel PHONY, es wird dem make-Tool mitteilen, dass das Ziel fiktiv ist und dass make nicht erwarten sollte, dass es die eigentliche Datei erstellt. Daher wird es nicht prüfen, ob die install Datei existiert, was bedeutet: a) ihr Verhalten wird nicht verändert, wenn die Datei existiert und b) extra stat() wird nicht angerufen.

Im Allgemeinen sollten alle Ziele in Ihrem Makefile, die keine Ausgabedatei mit dem gleichen Namen wie den Zielnamen erzeugen, PHONY sein. Dies beinhaltet typischerweise all, install, clean, distclean, und so weiter.


636
2017-08-26 10:54



HINWEIS: Das make-Tool liest das Makefile und überprüft die Änderungszeitstempel der Dateien an beiden Seiten des ':' - Symbols in einer Regel.

Beispiel

In einem Verzeichnis 'test' sind folgende Dateien vorhanden:

prerit@vvdn105:~/test$ ls
hello  hello.c  makefile

In Makefile ist eine Regel wie folgt definiert:

hello:hello.c
    cc hello.c -o hello

Nehmen wir nun an, dass die Datei "Hallo" eine Textdatei ist, die einige Daten enthält, die nach der Datei "hello.c" erstellt wurden. Der Modifikationszeitstempel von 'Hallo' ist also neuer als der von 'Hallo.c'. Wenn wir 'make hallo' von der Kommandozeile aus aufrufen, wird es folgendermaßen aussehen:

make: `hello' is up to date.

Nun greifen Sie auf die Datei 'hello.c' zu und fügen Sie einige Leerstellen ein, die sich nicht auf die Codesyntax oder -logik auswirken und dann speichern und beenden. Jetzt ist der Modifikationszeitstempel von hello.c neuer als der von 'Hallo'. Wenn Sie nun 'make hallo' aufrufen, werden die Befehle wie folgt ausgeführt:

cc hello.c -o hello

Und die Datei 'Hallo' (Textdatei) wird mit einer neuen Binärdatei 'Hallo' (Ergebnis des obigen Kompilierbefehls) überschrieben.

Wenn wir .PHONY in Makefile wie folgt verwenden:

.PHONY:hello

hello:hello.c
    cc hello.c -o hello

und dann 'make hallo' aufrufen, es wird ignoriert, wenn eine Datei in der Pwd mit dem Namen 'Hallo' vorhanden ist und den Befehl jedes Mal ausführen.

Angenommen, in Makefile sind keine Abhängigkeiten des Ziels vorhanden:

hello:
    cc hello.c -o hello

und 'hallo' Datei ist bereits in der pwd 'test' vorhanden, dann wird 'make hello' immer angezeigt als:

make: `hello' is up to date.

64
2017-09-30 14:51



.PHONY: install
  • bedeutet, dass das Wort "installieren" keinen Dateinamen in diesem darstellt Makefile;
  • bedeutet, dass das Makefile nichts mit einer Datei namens "install" zu tun hat im selben Verzeichnis.

63
2017-08-25 22:39



Es ist ein Build-Ziel, das kein Dateiname ist.


34
2018-01-27 16:48



Die beste Erklärung ist das GNU make manual selbst: 4.6 Phony Targets Abschnitt.

.PHONY ist eines von make's Spezielle integrierte Zielnamen. Es gibt andere Ziele, an denen Sie interessiert sein könnten. Es lohnt sich also, diese Referenzen zu lesen.

Wenn es Zeit ist, ein .PHONY-Ziel in Betracht zu ziehen, wird make sein Rezept ausführen   bedingungslos, unabhängig davon, ob eine Datei mit diesem Namen existiert oder    was ist die letzte Modifikationszeit?

Sie könnten auch interessiert sein an machen Standardziele sowie all und clean.


21
2018-04-03 23:49



Es gibt auch eine wichtige knifflige Behandlung von ".PHONY" - wenn ein physisches Ziel von einem falschen Ziel abhängt, das von einem anderen physischen Ziel abhängt:

TARGET1 -> PHONY_FORWARDER1 -> PHONY_FORWARDER2 -> TARGET2

Sie würden einfach erwarten, dass TARGET1, wenn Sie TARGET2 aktualisiert haben, als gegen TARGET1 abgestuft gelten sollte, daher sollte TARGET1 neu erstellt werden. Und es funktioniert wirklich so.

Der schwierige Teil ist, wenn TARGET2 ist nicht veraltet gegen TARGET1 - in diesem Fall sollten Sie erwarten, dass TARGET1 nicht neu erstellt werden sollte.

Dies funktioniert überraschenderweise nicht, weil: das falsche Ziel wurde trotzdem ausgeführt (wie es falsche Ziele normalerweise tun), was bedeutet, dass Das falsche Ziel wurde als aktualisiert angesehen. Und deshalb TARGET1 gilt als veraltet gegen das falsche Ziel.

Erwägen:

all: fileall

fileall: file2 filefwd
    echo file2 file1 >fileall


file2: file2.src
    echo file2.src >file2

file1: file1.src
    echo file1.src >file1
    echo file1.src >>file1

.PHONY: filefwd
.PHONY: filefwd2

filefwd: filefwd2

filefwd2: file1
    @echo "Produced target file1"


prepare:
    echo "Some text 1" >> file1.src
    echo "Some text 2" >> file2.src

Sie können damit spielen:

  • machen Sie zuerst "vorbereiten", um die "Quelldateien" vorzubereiten
  • Spielen Sie damit herum, indem Sie bestimmte Dateien berühren, um sie zu aktualisieren

Sie können sehen, dass die Datei von Datei1 indirekt durch ein falsches Ziel abhängt - aber es immer wird aufgrund dieser Abhängigkeit neu aufgebaut. Wenn Sie die Abhängigkeit in ändern fileall von filefwd zu file, jetzt fileall wird nicht jedes Mal neu aufgebaut, sondern nur dann, wenn eines der abhängigen Ziele als Datei abgestanden ist.


8
2018-02-11 10:11



Ich benutze sie oft, um dem Standardziel zu sagen, dass es nicht feuert.

superclean: clean andsomethingelse

blah: superclean

clean:
   @echo clean

%:
   @echo catcher $@

.PHONY: superclean

Ohne PHONY, make superclean würde schießen clean, andsomethingelse, und catcher superclean; aber mit PHONY, make superclean wird nicht schießen catcher superclean.

Wir müssen uns keine Sorgen machen, dass wir das machen clean Ziel ist PHONY, weil es nicht völlig falsch ist. Obwohl es nie die saubere Datei erzeugt, hat es Kommandos zu feuern, so dass make denkt, dass es ein endgültiges Ziel ist.

Aber die superclean Ziel ist wirklich falsch, also make wird versuchen, es mit etwas anderem zu stapeln, die Deps für die bereitstellt superclean Ziel - das schließt andere ein superclean Ziele und die % Ziel.

Beachten Sie, dass wir überhaupt nichts sagen andsomethingelse oder blah, so gehen sie eindeutig zum Catcher.

Die Ausgabe sieht ungefähr so ​​aus:

$ make clean
clean

$ make superclean
clean
catcher andsomethingelse

$ make blah 
clean
catcher andsomethingelse
catcher blah

0
2017-07-08 13:22