Makefile
一、 Makefile基础
Makefile用来完成以下功能:
1、 如果工程没有编译过,那么工程中的所有.c文件都要被编译并且链接成可执行文件。
2、 如果工程中只有个别C文件被修改了,那么只编译这些被修改的C文件。
3、 如果工程的头文件被修改了,那么需要编译所有引用这个头文件的C文件,并且链接成可执行文件。
例: 一个工程:通过键盘输入两个整型数字,然后计算他们的和并将结果显示在屏幕上,工程中包括main.c(主体)、input.c(接收键盘输入的数值)和calcu.c(进行加法运算)三个C文件及input.h、calcu.h两个头文件。
一般编译即:
gcc main.c input.c calcu.c -o main
使用Makefile编译:
首先在工程目录下创建“Makefile”文件 文件名一定是 Makefile
在Makefile文件中输入如下代码:
行首空出来的地方一定要使用“TAB”键
编写完成后,使用命令“make”编译
二、 Makefile语法
Makefile规则格式:
目标...:依赖文件集合....
命令1
命令2
......
例如以下规则:
main : main.o input.o calcu.o
gcc -o main main.o input.o calcu.o
这条规则的目标是main,*.o文件是生成main的依赖文件,如果要更新目标main,就必须先更新它的所有依赖文件。如果依赖文件中有任何一个有更新,那么目标也必须更新。“更新”就是执行一遍规则中的命令列表
上述代码共有5条规则,1-2为第一条规则,3-4为第二条规则,5-6为第三条规则,7-8为第四条规则,10-12为第五条规则。
make命令在执行Makefile的时候,执行步骤如下:
- 首先更新第一条规则的main,第一条规则的目标成为默认目标,完成整个Makefile就是为了完成默认目标的更新。
- 在第一次编译时,由于main不存在,因此执行第一条规则。第一条规则的三个依赖文件main.o、input.o、calcu.o都还没有,因此必须先更新这三条规则。
- 最后一个规则目标是clean,没有依赖文件,因此默认为依赖文件都是最新的,不会执行其对应的命令。如果想要执行 clean,可以直接使用命令“make clean”,执行后回删除当前目录下的所有.o文件及main。
make命令的执行过程:
- make 命令会在当前目录下查找以Makefile命名的文件
- 当找到Makefile文件后,会按照Makefile中定义的规则去编译生成最终的目标文件
- 当发现目标文件不存在,或者目标所依赖的文件比目标文件新(即最后修改时间比目标文件晚)时,就会执行后面的命令来更新文件。
三、 Makefile变量
-
注释:注释开头要使用符号“#”
-
变量
定义一个变量object,并且对这个变量进行赋值,其值为字符串“main.o input.o caclu.o”
变量引用的方法是“$ (变量名)”,本例中"$ (object)"就是使用变量object -
赋值符“=”
使用“=”给变量赋值,变量的真实值取决于它所引用的最后一次变量例: name = satr0 curname = $(name) name = star1 print: @echo curname: $(curname) 最终:curname = name = star1 且 输出 star1
-
赋值符“:=”
使用“:=”给变量赋值,只能使用前面已经定义好的变量,不会使用后面定义的变量例: name = satr0 curname := $(name) name = star1 print: @echo curname: $(curname) 最终:curname star0,name = star1 且 输出 star0
-
赋值符“?=”
使用“?=”,如果变量之前没有被赋值,则使用当前值,如果已经被赋值,则使用之前的赋值例: curname ?= star1 如果curname前面没有被赋值,则此变量就是“star1” 如果前面已经赋过值了,那么就使用前面赋的值
-
变量追加“+=”
使用“+=”,可以给已经定义好的变量添加一些字符串进去例: object = main.o input.o object += caclu.o 最终:object = main.o input.o calcu.o 这就是变量的追加
四、 Makefile模式规则及自动化变量
1、模式规则
模式规则中,至少在规则的目标定义中要包含“%”,否则就是一般规则。目标中的“%”表示对文件名的匹配,“%”代表长度任意的非空字符串,比如“%.c”就是所有以.c结尾的文件,“a.%.c”就表示以a.开头,以.c结尾的文件。
当“%”出现在目标中时,目标中的“%”所代表的值决定了依赖中的“%”的值:
%.o: %.c
命令
此时,5-6行替代了此前的3-8行,第6行命令需要借助自动化变量
2、 自动化变量
自动化变量会把模式中所定义的一系列文件自动的挨个取出,直至所有的符合模式的文件都取完。自动化变量只应该出现在规则的命令中。
这7个自动化变量中,常用的为:$ @、$ <、$ ^
五、 Makefile伪目标 .PHONY
伪目标不代表真正的目标名,在执行make命令时,通过指定这个伪目标来执行所在规则定义的命令 (用于避免文件间的名字冲突)
使用方法:
.PHONY:规则名
例:
.PHONY:clean
声明clean伪目标后,不管当前目录下是否存在名为“clean”的文件,输入“make clean”后规则对应的rm命令都会执行。