Linux项目自动化构建工具-Makefile简介

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命令。那么,
  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“proc”这个文件,并把这个文件作为最终的目标文件。
  3. 如果proc文件不存在,或是hello所依赖的后面的hello.o文件的文件修改时间要比proc这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成proc这个文件。
  4. 如果hello所依赖的proc.o文件不存在,那么make会在当前文件中找目标为proc.o文件的依赖性,如果找到则再根据那一个规则生成proc.o文件。(这有点像一个堆栈的过程)
  5. 当然,你的C文件和H文件是存在的啦,于是make会生成proc.o 文件,然后再用 proc.o 文件声明make的终极任务,也就是执行文件proc了。
  6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
  7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
  8. 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。 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值