Why are .PHONY implicit pattern rules not triggered?

前端 未结 3 1585
盖世英雄少女心
盖世英雄少女心 2020-12-05 13:30

I have the following recursive makefile:

.PHONY: all clean

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

all: all.subdir

clean: clean.subdir


        
相关标签:
3条回答
  • 2020-12-05 13:49

    You're right, it would make more sense to define the subdir rules as PHONY. But Make does not consider implicit rules for PHONY targets, so you'll have to rewrite that rule. I suggest the following:

    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
    
    0 讨论(0)
  • 2020-12-05 13:54

    That GNU make required targets declared as .PHONY to be explicit has already been stated in the other answers, which also provided some remedy to this.

    In this additional answer I would like to add an alterative which as I tested combines "phony" behavior, i.e. that targets are triggered each time no matter if a files of the same name exists (they are ignored). The alternative goes like this:

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

    It works on the premise that while only explicit targets can be set as .PHONY, whatever depends on a hence explicit phony target is itself inheriting much (to my knowledge all) phony attributes. An implicit, i.e. pattern matching target such as the %.subdir above is just like if would being added to .PHONY (which is impossible because it is not itself explicit), yet becoming phony via its prerequesite phony phony_explicit.

    It boils down that every rule - also implicit via pattern matching - which has in its prerequisites an explicit phony target (i.e. a target that is added to the .PHONY) is via this dependency also executed in a phony style (everytime, unconditionally of the filesystem erronously having a file with a coninciding name).

    Indeed the GNU make documentation mentions the FORCE target, which in some versions of GNU that do not offer a .PHONY target emulates partly the .PHONY behaviour. The alternative presented here uses this FORCE target approuch, yet because GNU make is used it also sets the FORCE target as .PHONY avoiding potential conflicts with really existing files of the same name.

    With this solution even a

    touch clean.subir; make clean.subdir
    

    will yield the desired invocation of

    make -C src clean
    make -C dist clean
    

    What might be a potential pro point of this alternative is that it needs no explicit declaration of clean.subdir and all.subdir, but is really using the implicit %.subdir pattern matching.

    0 讨论(0)
  • 2020-12-05 14:02

    From this section of the make manual:

    The implicit rule search (see Implicit Rules) is skipped for .PHONY targets. This is why declaring a target as .PHONY is good for performance, even if you are not worried about the actual file existing.

    Therefore, your implicit targets are never searched for because they are phony.

    You can achieve what you are trying to do another way. Try this:

    SUBDIRS := all clean
    .PHONY: $(SUBDIRS)
    
    $(SUBDIRS):
        echo $(MAKE) -C src $@
        echo $(MAKE) -C dict $@
    
    0 讨论(0)
提交回复
热议问题