I was trying to execute the example in this link.
all : prog1 prog2 prog3
.PHONY : all
prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o
With or without PHONY (if i comment out the .PHONY line), the outputs are the same. What is the real use of PHONY here?
The article mentions this
When one directory contains multiple programs, it is most convenient to describe all of the programs in one makefile
Since the target remade by default will be the first one in the makefile, it is common to make this a phony target named ‘all’ and give it, as prerequisites, all the individual programs
I cant understand what is the real use of PHONY here. Can someone point me a scenario in this example in which the program would behave differently without PHONY?
without .PHONY "all" is just a regular make target which depends on prog1, prog2, prog3. This means that if a file named "all" would happen to exist in the directory that is newer than prog1, prog2 and prog3, they will not be built (try it!) - but this is obviously not what you had in mind.
.PHONY tells GNU make the "all" target is phony - you don't REALLY intended for a file called "all" to be created and it should build the dependencies regardless if a file called "all" exists or not.
Added later:
My example with all and prog1 above was not correct although the general idea is true. Here is a much simple example
all: prog
prog: prog.c
clean:
$(RM) prog prog.o
giladb@xxx:~/tmp$ ls
Makefile prog.c
giladb@xxx:~/tmp$ make
cc prog.c -o prog
giladb@xxx:~/tmp$ make clean
rm -f prog prog.o
giladb@nps06:~/tmp$ make
cc prog.c -o prog
giladb@xxx:~/tmp$ touch clean
giladb@xxx:~/tmp$ make clean
make: `clean' is up to date.
At least for GNU Make in combination with this example the behavior regarding the output is the same, no matter if the target "all" is a phony target or not. Even if there is a file named "all".
BUT as described in the manual behind your link the internal behavior of GNU Make is different. If "all" is not a phony target, GNU Make checks whether a file named "all" exists and is older than its prerequisites. Try "make -d" and you will see the difference.
Another important point is that the recipe of a phony target is always executed. If you take this example:
all: goal
echo "Done"
.PHONY : clean
goal:
echo "Hello World!" > $(@)
clean:
rm -f goal all
... and execute this:
$ make clean
rm -f goal all
$ make
echo "Hello World!" > goal
echo "Done"
Done
$ make
echo "Done"
Done
$ touch all
$ make
make: 'all' is up to date.
... the recipe will not be executed after creating the file "all".
With "all" being a phony target:
all: goal
echo "Done"
.PHONY : all clean
goal:
echo "Hello World!" > $(@)
clean:
rm -f goal all
... the recipe of "all" will be executed always independent of the existence of the file "all".
$ make clean
rm -f goal all
$ make
echo "Hello World!" > goal
echo "Done"
Done
$ make
echo "Done"
Done
$ make
echo "Done"
Done
$ touch all
$ make
echo "Done"
Done
$ make
echo "Done"
Done
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