本人初学 makefile,对此问题有认识不足之处,烦请在评论区指出错误或补充您的观点,谢谢。

什么时候必须 make clean
当依赖文件中没有显式写出头文件时,如果仅改动了头文件,那么必须 make clean 。否则不会重新编译,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#######################mekefile
vpath %.c ./src
calc.exe: main.c add.o
gcc ./src/main.c add.o -o calc.exe
add.o: add.c
gcc -c ./src/add.c -o add.o
.PHONY: clean
clean:
rm -rf *.o
#######################main.c
#include "../header/add.h"
int main() {
int a=0;
int b=1;
int c=add(a,b);
return 0;
}
#######################add.c
#include "../header/add.h"
int add(int a,int b){
return a+b;
}
#######################add.h
#ifndef UNTITLED_ADD_H
#define UNTITLED_ADD_H
int add(int a,int b);
#endif //UNTITLED_ADD_H

make 依次,成功。在 make 一次,提示:make: 'calc.exe' is up to date. 。然后将 add.h 改为如下:

1
2
3
4
#ifndef UNTITLED_ADD_H
#define UNTITLED_ADD_H
int add(int a,int b,int c);
#endif //UNTITLED_ADD_H

然后再 make ,仍然提示:make: 'calc.exe' is up to date. ,说明 make 没有检测 add.h 的变动。此时 make clean ,接着 make ,就会报错,提示函数定义和函数原型对不上号:

以上情况就体现了 make clean 的必要性。

如果想及时追踪到头文件的改动,就必须把头文件纳入依赖:

1
2
3
4
5
6
7
8
9
vpath %.c ./src
vpath %.h ./header
calc.exe: main.c add.o
gcc ./src/main.c add.o -o calc.exe
add.o: add.c add.h
gcc -c ./src/add.c -o add.o
.PHONY: clean
clean:
rm -rf *.o

但这又会引入另一个新的问题:如果是一个比较大型的工程,你必需清楚哪些 C 文件包含了哪些头文件,并且,你在加入或删除头文件时,也需要小心地修改 Makefile,这是一个很没有维护性的工作。所以,我们可以让 make 自动找寻源文件中包含的头文件,并生成一个依赖关系。gcc/g++ 编译器有命令:gcc -MM file ,可以生成 file 文件中使用的头文件的路径,还是拿上面的例子说明:

1
2
$ gcc -MM ./src/main.c
main.o: src/main.c src/../header/add.h

还没学完,后续补充。。。。
详细内容:https://seisman.github.io/how-to-write-makefile/rules.html