What is the purpose of .PHONY in a Makefile?
By default, Makefile targets are "file targets" - they are used to build files from other files. Make assumes its target is a file, and this makes writing Makefiles relatively easy:
foo: bar
create_one_from_the_other foo bar
However, sometimes you want your Makefile to run commands that do not represent physical files in the file system. Good examples for this are the common targets "clean" and "all". Chances are this isn't the case, but you may potentially have a file named clean
in your main directory. In such a case Make will be confused because by default the clean
target would be associated with this file and Make will only run it when the file doesn't appear to be up-to-date with regards to its dependencies.
These special targets are called phony and you can explicitly tell Make they're not associated with files, e.g.:
.PHONY: clean
clean:
rm -rf *.o
Now make clean
will run as expected even if you do have a file named clean
.
In terms of Make, a phony target is simply a target that is always out-of-date, so whenever you ask make <phony_target>
, it will run, independent from the state of the file system. Some common make
targets that are often phony are: all
, install
, clean
, distclean
, TAGS
, info
, check
.
Let's assume you have install
target, which is a very common in makefiles. If you do not use .PHONY
, and a file named install
exists in the same directory as the Makefile, then make install
will do nothing. This is because Make interprets the rule to mean "execute such-and-such recipe to create the file named install
". Since the file is already there, and its dependencies didn't change, nothing will be done.
However if you make the install
target PHONY, it will tell the make tool that the target is fictional, and that make should not expect it to create the actual file. Hence it will not check whether the install
file exists, meaning: a) its behavior will not be altered if the file does exist and b) extra stat()
will not be called.
Generally all targets in your Makefile which do not produce an output file with the same name as the target name should be PHONY. This typically includes all
, install
, clean
, distclean
, and so on.