# Phony targets

Often it is convenient to put commands into the makefile that don't actually build a file, but are somehow logically associated with the build process. For example, a very common procedure in makefiles is something like this:

    prefix=/usr/local

    install: our_program
    	install -m 0755 our_program $(prefix)/bin
    	install -m 0644 *.png $(prefix)/share/our_program/icons

    .PHONY: install

When someone types `makepp install`, then makepp first builds `our_program`, then runs the commands associated with the install target. The `install` command simply copies its arguments to the specified directory, and sets the file's protection to the indicated value. So it copies `our_program` into `/usr/local/bin`, and some associated data files into `/usr/local/share/our_program/icons`. But this doesn't create a file called `install` in the current directory.

The `install` target here is called a phony target because makepp treats it as if it were a real file, but it is not actually a file, it's just a trick for forcing makepp to build its dependencies and then run some commands.

That's what the line

    .PHONY: install

is for. It tells makepp that it really shouldn't expect the file `./install` to exist after the commands have executed. If you forget the phony declaration, then makepp will expect the file `install` to exist after executing the commands, and it will complain loudly if it does not.

You can also write the phony declaration like this:

    $(phony install): our_program
    	...

and then omit the `.PHONY: install` line. This means that you can declare the target as phony on the same line as you define it, which may make your makefiles more readable.

Phony targets are extremely common in makefiles. In almost all makefiles, the first target is the phony target `all`, like this:

    $(phony all): program1 program2 program3

If no target is specified on the command line, makepp attempts to build the first target in the file. If your makefile makes more than just one program, you most likely want to build all of the programs by default. In this example, if the programmer just types `makepp` without any arguments, makepp attempts to build `all`, which forces it to build all three programs from this directory.

Here is a sample makefile fragment that illustrates some commonly used phony targets:

    PROGRAMS	:= combobulator discombobulator

    $(phony all): $(PROGRAMS)	# All is the first target, so it's the default.

    combobulator: $(COMBOBULATOR_OBJS)
    	$(CXX) $(inputs) -o $(output)

    discombobulator: $(DISCOMBOBULATOR_OBJS)
    	$(CXX) $(inputs) -o $(output)

    #
    # This target makes sure everything is compiled, and then puts the
    # programs into a place where everyone can access them.  We make the
    # directories if they don't exist yet.
    #
    prefix	:= /usr/local

    $(phony install): all
    	test -d $(prefix) || mkdir $(prefix)
    	test -d $(prefix)/bin || mkdir $(prefix)/bin
    	for prog in $(PROGRAMS); do \
    	  install -m 0755 $$prog $(prefix)/bin; \
    	done
    	test -d $(prefix)/share || mkdir $(prefix)/share
    	test -d $(prefix)/share/combobulate || mkdir -p $(prefix)/share/combobulate
    	for icon in *.xbm; do \
    	  install -m 0644 $$icon $(prefix)/share/combobulate; \
    	done
    # Note the use of the double dollar sign to pass a single dollar sign to
    # the shell.  Note also the backslashes at the end of a line to indicate
    # that a shell command continues to the next line.

    #
    # This target gets rid of all the junk that gets built during compiles.
    # (Note that this could be done more thoroughly with the
    # only-targets function.)
    #
    $(phony clean):
    	rm -f $(PROGRAMS) *.o

    #
    # This target makes a source distribution for shipping out to someone.
    #
    VERSION := 3.14

    $(phony distribution):
    	rm -rf combobulate-$(VERSION)	# Get rid of previous junk, if any.
    	mkdir combobulate-$(VERSION)
    	cp *.c *.h Makefile README INSTALL combobulate-$(VERSION)
    	tar cf - combobulate-$(VERSION) | gzip -9c > combobulate-$(VERSION).tar.gz
    	rm -rf combobulate-$(VERSION)

    #
    # This target runs regression tests to make sure the program(s) are
    # doing what they are supposed to do.
    #
    $(phony test): $(PROGRAMS)
    	noecho for testfile in *.test; do \
    	   ./combobulate $$testfile | ./discombobulate - > junk_output; \
    	  if cmp -s junk_output $$testfile; then \
    	    echo passed $$testfile; \
    	  else \
    	    echo failed $$testfile; \
    	  fi; \
    	done
    #
    # If "noecho" is the first word of the action, the action itself is not
    # printed before it is executed.  In this case, printing the action
    # would merely clutter up the screen so it is very common to suppress
    # printing for such long commands.
    #

Tutorial index | Next (multiple directories) | Previous (pattern rules)
Last modified: Tue Dec 26 19:35:54 PST 2000