Perché le regole del pattern implicito .PHONY non vengono triggerste?

Ho il seguente make-up ricorsivo:

.PHONY: all clean %.subdir: $(MAKE) -C src $* $(MAKE) -C dict $* all: all.subdir clean: clean.subdir 

e funziona bene:

 $ make all make -C src all make[1]: Entering directory `/or-1.3.6-fix/src' make[1]: Nothing to be done for `all'. make[1]: Leaving directory `/or-1.3.6-fix/src' make -C dict all make[1]: Entering directory `/or-1.3.6-fix/dict' make[1]: Nothing to be done for `all'. make[1]: Leaving directory `/or-1.3.6-fix/dict' 

Ma sarebbe più logico definire le regole %.subdir come %.subdir :

 .PHONY: all clean all.subdir clean.subdir 

e ora fai smettere di lavorare come voglio:

 $ make all make: Nothing to be done for `all'. $ make -d all ... Updating goal targets.... Considering target file `all'. File `all' does not exist. Considering target file `all.subdir'. File `all.subdir' does not exist. Finished prerequisites of target file `all.subdir'. Must remake target `all.subdir'. Successfully remade target file `all.subdir'. Finished prerequisites of target file `all'. Must remake target `all'. Successfully remade target file `all'. make: Nothing to be done for `all'. 

Qualcuno può spiegarmi perché (o ancora meglio indicarmi la documentazione)?

Hai ragione, avrebbe più senso definire le regole subdir come PHONY. Ma Make non considera le regole implicite per gli obiettivi PHONY, quindi dovrai riscrivere quella regola. Suggerisco il seguente:

 SUBDIR_TARGETS = all.subdir clean.subdir .PHONY: all clean $(SUBDIR_TARGETS) $(SUBDIR_TARGETS): %.subdir: $(MAKE) -C src $* $(MAKE) -C dict $* all: all.subdir clean: clean.subdir 

Da questa sezione del manuale del make:

La ricerca della regola implicita (vedi Regole implicite) viene ignorata per gli obiettivi .PHONY. Questo è il motivo per cui dichiarare un bersaglio come .PHONY è buono per le prestazioni, anche se non sei preoccupato del file attuale esistente.

Pertanto, i tuoi obiettivi impliciti non vengono mai cercati perché sono fasulli.

Puoi ottenere ciò che stai cercando di fare in un altro modo. Prova questo:

 SUBDIRS := all clean .PHONY: $(SUBDIRS) $(SUBDIRS): echo $(MAKE) -C src [email protected] echo $(MAKE) -C dict [email protected] 

Il fatto che GNU renda obiettivi obbligatori dichiarati come .PHONY per essere espliciti è già stato indicato nelle altre risposte, che hanno anche fornito qualche rimedio a ciò.

In questa risposta aggiuntiva vorrei aggiungere un alterativo che, come ho provato, combina il comportamento “fasullo”, vale a dire che gli obiettivi vengono triggersti ​​ogni volta, indipendentemente dal fatto che esista un file con lo stesso nome (vengono ignorati). L’alternativa va così:

 .PHONY: phony_explicit phony_explicit: %.subdir: phony_explicit $(MAKE) -C src $* $(MAKE) -C dict $* 

Funziona sulla premessa che mentre solo gli obiettivi espliciti possono essere impostati come .PHONY, qualunque cosa dipenda da un objective fasullo, quindi esplicito, è essa stessa che eredita molto (a mia conoscenza tutti) gli attributi fasulli. Un bersaglio implicito, ad esempio la corrispondenza del modello come %.subdir sopra è proprio come se venisse aggiunto a .PHONY (che è imansible perché non è esso stesso esplicito), pur diventando fasullo tramite il suo prerequisito fasullo phony_explicit .

Si riduce a ogni regola – anche implicita tramite la corrispondenza dei pattern – che ha nei suoi prerequisiti un target fasullo esplicito (cioè un target che viene aggiunto a .PHONY ) tramite questa dipendenza eseguita anche in uno stile fasullo (ogni volta, incondizionatamente del file system erroneamente con un file con un nome coincidente).

Infatti la GNU fa la documentazione menziona l’ objective FORCE , che in alcune versioni di GNU che non offrono un target .PHONY emula in parte il comportamento di .PHONY . L’alternativa qui presentata utilizza questo approoche FORCE , ma poiché GNU make è usato, imposta anche il target FORCE come .PHONY evitando potenziali conflitti con file realmente esistenti con lo stesso nome.

Con questa soluzione anche a

 touch clean.subir; make clean.subdir 

produrrà l’invocazione desiderata di

 make -C src clean make -C dist clean 

Quello che potrebbe essere un potenziale punto di vantaggio di questa alternativa è che non ha bisogno di dichiarazioni esplicite di clean.subdir e all.subdir , ma in realtà sta usando la corrispondenza del pattern implicito %.subdir .