Question Quel est le but de .PHONY dans un makefile?


Qu'est-ce que .PHONY signifie dans un Makefile? J'ai traversé cemais c'est trop compliqué.

Quelqu'un peut-il m'expliquer en termes simples?


1207
2018-01-27 09:08


origine


Réponses:


Par défaut, les cibles Makefile sont des "cibles de fichiers" - elles sont utilisées pour créer des fichiers à partir d'autres fichiers. Make suppose que sa cible est un fichier, ce qui rend l'écriture de Makefiles relativement facile:

foo: bar
  create_one_from_the_other foo bar

Cependant, vous voulez parfois que votre Makefile exécute des commandes qui ne représentent pas les fichiers physiques dans le système de fichiers. De bons exemples pour cela sont les cibles communes "propre" et "tout". Les chances sont que ce n'est pas le cas, mais vous mai potentiellement avoir un fichier nommé clean dans votre répertoire principal. Dans un tel cas, Make sera confus parce que par défaut, le clean La cible sera associée à ce fichier et Make ne l'exécutera que si le fichier ne semble pas être à jour en ce qui concerne ses dépendances.

Ces cibles spéciales sont appelées faux et vous pouvez explicitement dire qu'ils ne sont pas associés à des fichiers, par exemple:

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

À présent make clean se déroulera comme prévu, même si vous avez un fichier nommé clean.

En termes de Make, une cible bidon est simplement une cible qui est toujours périmée, donc quand vous le demandez make <phony_target>, il fonctionnera, indépendamment de l'état du système de fichiers. Un peu commun make Les cibles qui sont souvent fausses sont: all, install, clean, distclean, TAGS, info, check.


1341
2018-01-27 09:11



Supposons que vous avez install target, ce qui est très courant dans makefiles. Si tu fais ne pas utilisation .PHONYet un fichier nommé install existe dans le même répertoire que le Makefile, alors make install ça ira rien. En effet, Make interprète la règle comme signifiant "exécuter telle ou telle recette pour créer le fichier nommé". install"Comme le fichier est déjà là, et que ses dépendances n'ont pas changé, rien ne sera fait.

Cependant, si vous faites le install PHONY cible, il dira à l'outil make que la cible est fictive, et que make ne devrait pas s'attendre à ce qu'il crée le fichier lui-même. Par conséquent, il ne vérifiera pas si le install le fichier existe, ce qui signifie: a) son comportement ne sera pas modifié si le fichier existe et b) en plus stat() ne sera pas appelé.

En règle générale, toutes les cibles de votre Makefile qui ne produisent pas un fichier de sortie portant le même nom que le nom cible doivent être PHONY. Cela inclut généralement all, install, clean, distclean, etc.


636
2017-08-26 10:54



REMARQUE: L'outil de création lit le makefile et vérifie les horodatages de modification des fichiers à la fois du symbole ':' dans une règle.

Exemple

Dans un répertoire 'test' les fichiers suivants sont présents:

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

Dans makefile, une règle est définie comme suit:

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

Supposons maintenant que le fichier 'hello' est un fichier texte contenant des données, qui a été créé après le fichier 'hello.c'. Ainsi, la modification (ou la création) horodatage de 'hello' sera plus récente que celle de 'hello.c'. Ainsi, lorsque nous invoquerons 'make hello' depuis la ligne de commande, il sera imprimé comme suit:

make: `hello' is up to date.

Maintenant, accédez au fichier 'hello.c' et placez-y des espaces blancs, ce qui n'affecte ni la syntaxe ni la logique du code, puis sauvegarde et quitte. Maintenant, l'horodatage de modification de hello.c est plus récent que celui du 'hello'. Maintenant, si vous appelez 'make hello', il va exécuter les commandes comme:

cc hello.c -o hello

Et le fichier 'hello' (fichier texte) sera remplacé par un nouveau fichier binaire 'hello' (résultat de la commande de compilation ci-dessus).

Si nous utilisons .PHONY dans makefile comme suit:

.PHONY:hello

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

puis invoque 'make hello', il ignore si un fichier présent dans le pwd s'appelle 'hello' et exécute la commande à chaque fois.

Supposons maintenant qu'aucune dépendance de la cible n'existe dans le fichier makefile:

hello:
    cc hello.c -o hello

et le fichier 'hello' est déjà présent dans le 'test' de pwd, alors 'make hello' s'affichera toujours comme suit:

make: `hello' is up to date.

64
2017-09-30 14:51



.PHONY: install
  • signifie que le mot "installer" ne représente pas un nom de fichier dans ce Makefile;
  • signifie que le Makefile n'a rien à voir avec un fichier appelé "install" dans le même répertoire.

63
2017-08-25 22:39



C'est une cible de construction qui n'est pas un nom de fichier.


34
2018-01-27 16:48



La meilleure explication est le manuel GNU make lui-même: 4.6 Section des cibles phony.

.PHONY est l'un des faits Noms de cible intégrés spéciaux. Il y a d'autres cibles qui pourraient vous intéresser, alors il vaut la peine de parcourir ces références.

Quand il est temps d'envisager une cible .PHONY, make exécutera sa recette   inconditionnellement, indépendamment du fait qu'un fichier portant ce nom existe ou    quelle est l'heure de sa dernière modification.

Vous pouvez également être intéressé par make Cibles standard tel que all et clean.


21
2018-04-03 23:49



Il y a aussi un traitement délicat important de ".PHONY" - quand une cible physique dépend de la cible bidon qui dépend d'une autre cible physique:

TARGET1 -> PHONY_FORWARDER1 -> PHONY_FORWARDER2 -> TARGET2

Vous vous attendez simplement à ce que si vous avez mis à jour TARGET2, TARGET1 soit considéré comme périmé par rapport à TARGET1, donc TARGET1 devrait être reconstruit. Et ça marche vraiment comme ça.

La partie délicate est quand TARGET2 n'est pas périmé sur TARGET1 - auquel cas vous devriez vous attendre à ce que TARGET1 ne soit pas reconstruit.

Cela ne marche étonnamment pas parce que: la cible de faux a été exécutée de toute façon (comme le font les fausses cibles normalement), ce qui signifie que la cible bidon a été considérée mise à jour. Et à cause de ça TARGET1 est considéré comme périmé contre la cible bidon.

Considérer:

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

Vous pouvez jouer avec ça:

  • d'abord faire "préparer" pour préparer les "fichiers source"
  • jouer avec cela en touchant des fichiers particuliers pour les voir mis à jour

Vous pouvez voir que fileall dépend de fichier1 indirectement à travers une cible bidon - mais il toujours se reconstruit en raison de cette dépendance. Si vous modifiez la dépendance dans fileall de filefwd à file, à présent fileall ne se reconstruit pas à chaque fois, mais seulement quand l'une des cibles dépendantes est viciée contre elle en tant que fichier.


8
2018-02-11 10:11



Je les utilise souvent pour dire à la cible par défaut de ne pas tirer.

superclean: clean andsomethingelse

blah: superclean

clean:
   @echo clean

%:
   @echo catcher $@

.PHONY: superclean

Sans PHONY, make superclean allumerait clean, andsomethingelse, et catcher superclean; mais avec PHONY, make superclean ne tirera pas le catcher superclean.

Nous ne devons pas nous inquiéter de dire faire le clean La cible est PHONY, parce que ce n'est pas complètement faux. Bien qu'il ne produise jamais le fichier propre, il a des ordres de tirer, donc pensez que c'est une cible finale.

Cependant, le superclean la cible est vraiment bidon, alors faites essayer de l'empiler avec tout ce qui fournit des deps pour le superclean cible - cela comprend d'autres superclean cibles et la % cible.

Notez que nous ne disons rien du tout andsomethingelse ou blah, alors ils vont clairement au receveur.

La sortie ressemble à ceci:

$ make clean
clean

$ make superclean
clean
catcher andsomethingelse

$ make blah 
clean
catcher andsomethingelse
catcher blah

0
2017-07-08 13:22