当前位置:网站首页>c files always get rebuild when make -------- . PHONY in Makefile

c files always get rebuild when make -------- . PHONY in Makefile

2022-06-22 05:39:00 alex_ mianmian

.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 [email protected]

%.d:%.c
        @echo "Making [email protected] ..."
        @set -e;
        gcc -E -MM $(filter %.c, $^) > [email protected]

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'.

[email protected]:~/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.

[email protected]:~/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:

[email protected]:~/mktest$ make
make: 'mktest' is up to date.
[email protected]:~/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.

This example is from a real bad project Makefile. it tells us don't do:

source file includes header file, but Makefile has header file fake target. In this case, fake target header file will cause source file get build everytime 'make'.

原网站

版权声明
本文为[alex_ mianmian]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206220523352621.html