Linux中, make 和 makefile 的使用。
一、make和makefile 项目自动化构建工具
(1)make/makefile 背景介绍
- make是一条指令,makefile 是一个文件。两个配合使用,完成项目的自动化构建。
- makefile的好处是 自动化编译, 一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
(2)makefile使用
// 新建test.c文件
#include <stdio.h>
int main()
{
printf("hello, linux!\n");
return 0;
}
// 新建makefile文件
test.exe:test.c
gcc -o test.exe test.c
.PHONY:clean
clean:
rm -f test.exe
- 将上述文件放在同一目录下,输入指令make, 项目会自动编译,执行指令:**“gcc -o test.exe test.c”。生成一个”test.exe“**的可执行程序。
- 输入:make clean, 他会执行**”rm test.exe“**.
- 单输入make,他会默认生成第一个目标文件,默认执行第一个依赖关系(第1,2行表示一个依赖关系)。如上述例子中的”test.exe“文件。
- “.PHONY"后面修饰的目标文件,我们把它设置为伪目标,伪目标的特点是:总是被执行。(后面讲解什么是总是被执行?)
(3)原理
- 输入make,回车。make会在当前目录下找名字叫“Makefile” 或 "makefile"的文件(两个文件一样)。
- 如果找到,他会找文件中第一个目标文件,上述例子中:他会找“test.exe”这个文件,并把这个文件作为最终的目标文件。
- makefile中的内容从上往下依次执行。
- 如果"test.exe"不存在,或者他所依赖的后面的“test.c" 文件的文件修改时间要比“test.exe”这个文件新(使用touch指令,touch一个已经存在的文件,会更新这个文件的最近修改时间),那么,他会执行后面所定义的命令来生成“test.exe”这个文件。即执行“gcc -o test.exe test.c”这条命令。
- 如果"test.exe"依赖的“test.c”文件不存在,那么make会在当前文件中找目标为“hello.c”文件的依赖性,如果找到则再根据那一个依赖规则生成“hello.c"文件。
- 这就是整个make的依赖性,make会一层又一层的找文件的依赖关系,直到最终编译出第一个目标文件。
- 在寻找的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错。而对于所定义的命令的错误,或者是编译不成功,make根本不理。
- make只管文件的依赖性/依赖关系。即如果在找了依赖关系之后,冒号后面的文件还是不存在,那么make直接报错提醒。
(4)项目清理
- ”.PHONY“是makefile中的一个修饰符,他修饰的文件总是被执行。
(5)什么是总是被执行?
-
当我们输入指令make后,项目会自动编译并形成一个可执行文件。如果我们再次输入make, 发现make给我们提示:“make: `test.exe’ is up to date.”,显然make并没有再次执行编译。但是我们多次输入:“make clean”, 他并没有提示我们。那么我们把clean 和 test.exe的顺序换一下:
clean: rm test.exe .PHONY:test.exe test.exe:test.c gcc -o test.exe test.c
-
当我们输入make时,他会自动执行第一条依赖关系,即”rm test.exe“, 而我们要项让程序编译,就要输入”make test.exe“。如果我们再次输入:”make test.exe“时,发现他并不会给我们提醒,而是重新编译。
-
我们得出结论:
- make默认执行第一条依赖关系,生成第一个目标文件。
- 被”.PHONY“修饰的目标文件总是被执行。
-
-
为什么makefile对最新的可执行程序,再次执行make指令,不会再次编译?
- 提高编译的效率。对于大型项目而言,有上千上万多个文件待编译,如果每个文件编译都需要0.1秒,那么1万个文件就需要编译1000秒,如果更多文件呢?
-
make是怎么做到?
-
对比文件和可执行程序的最近一次修改时间。如果文件是最新时间的,那么make就会再次编译; 如果可执行程序时间是最新的那么make就不会再次编译。
-
使用stat 指令可以查看文件的最近一次修改日期:
stat test.exe stat test.c
-
对一个已经存在的文件,使用touch指令,会更新这个文件的最近一次修改时间:
touch test.exe
-
(6)常见用法
bin=test.exe
src=test.c
$(bin):$(src)
@gcc -o $@ $^
@echo "compliler $(src) to $(bin)..."
.PHONY:clean
clean:
@rm -f $(bin)
@echo "clean project..."
- bin 和 src 是makefile里面定义的变量
- $: 相当于取变量里面的内容
- gcc前面的@:表示在make时,不让执行的指令打印在显示器上
- $@:表示冒号前面的目标文件
- $^: 表示冒号后面的依赖文件列表
- makefile中的注释是:#