Table of Contents

Makefile Phony Targets

Phony targets don't produce files—they're commands. Mark them with .PHONY so Make doesn't check for a file with that name.

.PHONY: all clean install test
 
all: app
 
app: main.o util.o
	gcc -o app main.o util.o
 
clean:
	rm -f *.o app
 
install: app
	cp app /usr/local/bin/
 
test: app
	./test.sh

Without .PHONY, if a file named clean exists, make clean won't run (Make thinks the target is up to date). .PHONY tells Make “this target is not a file; run it every time.”

Common phony targets:

.PHONY: all clean install test help
 
all:
	@echo "Building application"
	gcc -o app *.c
 
clean:
	rm -f *.o app
 
install: all
	mkdir -p /usr/local/bin
	cp app /usr/local/bin/
 
test: all
	./run_tests.sh
 
help:
	@echo "Usage: make [target]"
	@echo "Targets:"
	@echo "  all     - build application (default)"
	@echo "  clean   - delete build artifacts"
	@echo "  install - install to /usr/local/bin"
	@echo "  test    - run tests"

all target: Conventionally, all is the default target. If no target is specified, make all runs:

.PHONY: all
all: app
 
app: main.o util.o
	gcc -o app main.o util.o

make with no arguments is equivalent to make all.

clean target: Delete build artifacts:

.PHONY: clean
clean:
	rm -f *.o *.so app
	rm -rf build/

Run with make clean before rebuilding to start fresh.

install target: Copy built files to their destination:

.PHONY: install
install: all
	install -d $(PREFIX)/bin
	install -m 755 app $(PREFIX)/bin/app

Depends on all (builds first), then installs. $(PREFIX) allows customization (make PREFIX=/opt install).

test target: Run tests:

.PHONY: test
test: app
	./test_app
	@echo "Tests passed"

Depends on app (ensures app is built), then runs the test.

help target: Document available targets:

.PHONY: help
help:
	@echo "Available targets:"
	@grep "^.PHONY:" Makefile | sed 's/.PHONY: //' | tr ' ' '\n' | grep -v "^$$"

The @ prefix suppresses command echoing; only the output is printed. Good for documentation.

Avoiding accidental files: If you have both a phony target and a file with the same name, the phony target always runs:

.PHONY: build
build:
	mkdir -p build

Without .PHONY, if build/ directory exists, make build would do nothing.