Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why .PHONY:target and not target:.PHONY?

I still don't understand why "phony" rules in Makefiles have ".PHONY" as their target. It would be much more logical as a prerequisite.

Do I have to elaborate on this? If A depends on B and B is phony, then A is phony too. So the dependency graph .PHONYBA is waay surprising compared to .PHONYBA. (Another argument is that an implementation of make must handle the .PHONY target very special.)

While this critique may seem rather theoretical (to pointless) - "since make is so ancient, its syntax is here to stay". But I am not proposing any syntax change, there is an alternative:

With GNU Make (at least), the following Makefile declares a phony target_A:

target_A: _PHONY
        touch target_A

_PHONY:
        #noop

Question 1: This is so simple and clean, surely I am not its first inventor. In fact, given this alternative, why did make ever need the special syntax?

It seems to me that this would also quite nicely solve questions about wildcards in phony targets, and could even shed some light on .PHONY's meaning when beginners doubt.

Question 2: Can you think of any circumstance where this approach is inferior? (Is invoking make .PHONY of any use?)

(I should mention that while I have invoked other makes, GNU Make is the only implementation that I have some experience with - reading and writing Makefiles.)

like image 616
tiwo Avatar asked Jul 20 '12 20:07

tiwo


People also ask

What is the purpose of .phony in a makefile?

PHONY: allows to declare phony targets, so that make will not check them as actual file names: it will work all the time even if such files still exist.

What is a make target?

A 'make target' is basically a file that you want rebuilt. Make can't divine what you want built, so you have to tell it, implicitly or explicitly, what it should build.

What is $@ in make?

From make manpage: $@ is: The file name of the target of the rule. If the target is an archive member, then '$@' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), '$@' is the name of whichever target caused the rule's recipe to be run.

What is the default make target?

By default, the goal is the first target in the makefile (not counting targets that start with a period). Therefore, makefiles are usually written so that the first target is for compiling the entire program or programs they describe.


1 Answers

One big problem with using target_A: .PHONY is that it makes it much harder to use many of make's built-in variables. Take this common recipe as an example:

%.a: $(OBJ_FILES)
    $(LD) $(LFLAGS) -o $@ $^

The $^ variable pulls in everything that's listed as a prerequisite. If .PHONY was also listed there then it would be passed to the linker on the command-line, which would probably not result in anything good happening. Using meta-targets like .PHONY as prerequisites makes these built-in variables significantly less useful, as they require a lot of extra processing like $(filter-out .PHONY,$^) every time they are used. Inverting the relationship and instead making .PHONY the target is a bit awkward for the sake of thinking about dependency trees, but it cleans up the rest of the makefile.

like image 77
bta Avatar answered Oct 08 '22 15:10

bta