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 .PHONY
←B
→A
is waay surprising compared to .PHONY
→B
→A
. (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 make
s, GNU Make is the only implementation that I have some experience with - reading and writing Makefiles.)
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With