.PHONY is key word in Makefile, it means a fake target.
Firstly let's list a Makefile as following:
C_FLAGS =
SOURCE = main.c test.c
OBJS_C = $(SOURCE:.c=.o)
DEP = $(SOURCE:.c=.d)
HEADER= header.h
mktest:$(OBJS_C)
@echo "objects is" "$(OBJS_C)"
gcc $(OBJS_C) -o mktest
include $(DEP)
.PHONY:$(HEADER)
$(HEADER):
@echo "test header cause rebuild"
%.o:%.c
@echo "start making objs"
gcc -c $< -o $@
%.d:%.c
@echo "Making $@ ..."
@set -e;
gcc -E -MM $(filter %.c, $^) > $@
clean:
-rm *.o
-rm *.d
-rm mktest
Do you still remember yesterday's Makefile. I just added following rule.
HEADER= header.h
.PHONY:$(HEADER)
$(HEADER):
@echo "test header cause rebuild"
This rule means what? let's explain later. Now let's create header.h and add it into main.c then run 'make'.
chunxie@xixi:~/mktest$ make
Makefile:16: main.d: No such file or directory
Makefile:16: test.d: No such file or directory
Making test.d ...
gcc -E -MM test.c > test.d
Making main.d ...
gcc -E -MM main.c > main.d
test header cause rebuild
start making objs
gcc -c main.c -o main.o
start making objs
gcc -c test.c -o test.o
objects is main.o test.o
gcc main.o test.o -o mktest
we can see all source files get build. Now let's run 'make' again. What should we see? we didn't change anything, right? should be nothing build.
chunxie@xixi:~/mktest$ make
test header cause rebuild
start making objs
gcc -c main.c -o main.o
objects is main.o test.o
gcc main.o test.o -o mktest
What, main.o is built again and mktest get link again. Why?
Firstly let's check main.d:
main.o: main.c test.h other.h header.h
header.h is the depend file of main.o, when header.h get update, main.o get rebuild. But we didn't modify header.h
So why?
Yes, I didn't modify or update header.h, but header.h has rule in Makefile -- $(HEADER):
it has no depend file, how it get update? remember .PHONY:$(HEADER) ?
.PHONY can make the fake target run even if has no depend file.
Now let's clear the sequence of the first 'make':
1. -include $(DEP), try to add main.d and test.d to Makefile, not found them then check their rule
2. found %.d:%.c and create main.d and test.d, main.d add header.h as main.o's depend file
3. -include $(DEP) add main.d and test.d into Makefile, then main.o and test.o targets get in Makefile
4. main.o target has depend file header.h, and check header.h's rule
5. found $(HEADER): so we can see log 'test header cause rebuild'
6. build main.o and test.o by rule %.o:%.c
7. link mktest
The second 'make' starts from step 3 to step7. But test.o doesn't build as no depend file update and depend file has no rule in Makefile.
If we remove the .PHONY:$(HEADER) then do third 'make', what will happen? will header.h is updated? here is the result:
chunxie@xixi:~/mktest$ make
make: 'mktest' is up to date.
chunxie@xixi:~/mktest$
Look, no building happen.
So can you understand .PHONY now?
And one important thing is: the real header.h never changed(ls -l can check the file date), but the header.h in Makefile get update by .PHONY rule.