Makefile 是 Linux 环境下常用的一个自动化构建工具,它主要用于编译和构建项目。Makefile 文件描述了如何编译和链接程序,以及它们之间的依赖关系。使用 Makefile 可以简化编译过程,使得只需要重新编译那些自上次编译以来被修改过的文件,从而节省时间。
基本概念
- 目标(Targets):Makefile 中的基本单位,通常代表一个可执行的程序或者一个对象文件。
- 依赖(Dependencies):目标所依赖的文件列表,这些文件在目标之前被编译或处理。
- 命令(Commands):用于生成目标的 shell 命令。
Makefile 规则
Makefile 中的规则定义了如何生成一个或多个目标文件。每条规则包含以下部分:
目标: 依赖...
命令
...
- 目标:通常是文件名,它可以是可执行文件或中间文件。
- 依赖:生成目标所需要的文件列表。如果依赖的文件比目标文件新,则执行下面的命令来生成目标。
- 命令:用于生成目标的 shell 命令,必须以 Tab 开始。
简单示例:
假设你有一个简单的 C 程序,你想编译这些文件并生成一个可执行文件proc。
但是这样每次再修改后都需要重新输入gcc -o proc proc.c
所以我们可以选择更加方便地Makefile.
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# touch Makefile
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# vim Makefile
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# cat Makefile
proc:proc.c
gcc -o proc proc.c
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# make
gcc -o proc proc.c
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# ls
Makefile proc proc.c
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# ./proc
hello Makefile
依赖关系
上面的文件proc ,它依赖 proc.c proc.c 是依赖文件列表依赖方法
gcc -o proc proc.c,就是与之对应的依赖关系。 makefile本质是依赖关系与依赖方法的结合。 在Makefile中我们还可以加入其他内容:[root@iZf8z8jpr9io12vlyj7lcuZ study01]# cat Makefile
proc:proc.c
gcc -o proc proc.c
.PHONY:clean
clean:
rm -f proc
我们可以通过这种方法使用
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# make clean
rm -f proc
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# ls
Makefile proc.c
上面的Makefile中通过.PHONY命名一个伪目标clean(这个名字可以更改)。
原理
上面的Makefile更加完整应该是:
proc:proc.o
gcc proc.o -o proc
proc.o:proc.s
gcc -c proc.s -o proc.o
proc.s:proc.i
gcc -S proc.i -o proc.s
proc.i:proc.c
gcc -E proc.c -o proc.i
.PHONY:clean
clean:
rm -f proc.i proc.s proc.o proc
make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,
- make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
- 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“proc”这个文件,并把这个文件作为最终的目标文件。
- 如果proc文件不存在,或是hello所依赖的后面的hello.o文件的文件修改时间要比proc这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成proc这个文件。
- 如果hello所依赖的proc.o文件不存在,那么make会在当前文件中找目标为proc.o文件的依赖性,如果找到则再根据那一个规则生成proc.o文件。(这有点像一个堆栈的过程)
- 当然,你的C文件和H文件是存在的啦,于是make会生成proc.o 文件,然后再用 proc.o 文件声明make的终极任务,也就是执行文件proc了。
- 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
- 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
- make只管文件的依赖性,即如果在找了依赖关系之后,冒号后面的文件还是不在,那么就不工作了。
其他
Makefile后面的命令内容可以是很多,比如:[root@iZf8z8jpr9io12vlyj7lcuZ study01]# vim Makefile
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# cat Makefile
proc:proc.c
gcc -o proc proc.c
echo "完成"
.PHONY:clean
clean:
rm -f proc
echo "删除完成"
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# make
gcc -o proc proc.c
echo "完成"
完成
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# ls
Makefile proc proc.c
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# make clean
rm -f proc
echo "删除完成"
删除完成
我们可以看见在make时会把命令名称本身也打印出来,我们可以在命令前加上'@'符号来关闭回显。
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# make
完成
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# make clean
删除完成
[root@iZf8z8jpr9io12vlyj7lcuZ study01]#
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# make
完成
[root@iZf8z8jpr9io12vlyj7lcuZ study01]# make
make: `proc' is up to date.
我们在多次make会出现这样的情况,形成了可执行程序后再make,会被提示该可执行文件是最新的。
但是我们可以在proc前加入.PHONY:proc,这样每次make都可以执行。
这是因为.PHONY:让目标文件对应的方法总是被执行。
那这是为什么呢?
对于源文件以及可执行程序,它们都是文件,文件由内容与属性构成,属性则包括时间,我们可以通过stat命令查看时间属性。
其中:
- Access表示该文件最近被访问的时间;
- Modify表示该文件内容最近被修改的时间;
- Change表示该文件属性最近被改变的时间。
在对属性进行修改后,Change时间发生了变化 。
在对proc.c内容进行修改后,Modify时间与Change时间都发生了改变,这是因为内容的改变可能也会改变文件大小等属性。
编译程序是否能被重新执行根据对比Modify时间,而.PHONY让取消其对于Modify时间的对比,所以可以使文件多次执行。
在改变文件属性后,未改变Modify时间,仅改变Change时间,所以仍无法重新多次make。
标签:文件,study01,iZf8z8jpr9io12vlyj7lcuZ,简介,make,Makefile,Linux,proc From: https://blog.csdn.net/2302_80190174/article/details/141017807