Makefile
在linux系统中我们通常使用gcc等命令来实现一个项目的流程,而Makefile类似于一个shell脚本,通过一系列规则来帮助我们简化项目的编译、链接等操作。可以实现近乎windows上vc++等编译器的功能。
一、工作原理
我们可以像在终端中输入命令一样,将命令写在makefile中。依靠简单的依赖原则,makefile会比较文件最后的修改时间来决定是否执行该命令,即
工作原理(更新机制):如果被依赖项的更新时间比依赖项新,则会更新被依赖项。
例如:
#注意,必须要有缩进
main.o:main.c
gcc main.c -o main.o
- 在上述语句中,main.o 依赖于main.c(依赖:必须要有main.c才有main.o),如果main.c的修改时间晚于main.o,则会执行gcc命令,否则不做编译。
二、模式规则
- 第一条规则是用来生成终极目标的规则,直接make只会生成终极目标
- 如果规则中的依赖不存在,向下寻找其他规则,会一层一层往下依赖
- 更新规则规则:比较目标文件和依赖文件的时间
例如:
app:main.o add.o
main.o:main.c
gcc -c main.c
add.o:add.c
gcc -c add.c
- 此例中,终极目标是app,依赖是main.o,add.o,如果当前没有找到两个文件,则会向下寻找依赖文件,到第3句时生成main.o,第5句生成add.o,寻找结束;若如果有这两个文件,则会通过比较目标文件和依赖文件的时间来决定某个文件是否需要更新。
三、变量
自定义变量
类似shell脚本语句,makefile中设置变量直接通过等号“=”赋值:
obj=main.o add.o sub.o
- 等号左边是变量名,等号右边是值(字符串)。
- 类似于shell语句,通过$obj,可以将变量中的值取出。
自动变量
在makefile中可以通过一些匹配符来代替字符串,简化编写:
公式匹配:
%:匹配符号,根据格式进行匹配,同一行%表示相同的字段
%.o:%.c
#用来代替main.o:main.c
只能在规则中的命令中使用:
$<:规则中的第一个依赖
$@:规则中的目标
$^:规则中所有的依赖
%.o:%.c
gcc $< -c $@
# $<代替main.c,$@代替main.o
makefile中维护的变量:
都是大写
CC:CC = cc
CPPFLAGS:CPPFLAGS = -I;预编译需要的变量
四、最常用的两个函数
makefile中也定义了自己的函数,来方便我们进行编写,简单举两个最常用的函数
- wildcard:查找某种类型的文件,$是取出返回值
src=$(wildcard ./*.c)
#wildcard是函数名,无需括号
#./*.c,是当前目录下所有.c文件,是wildcard的输入参数
#$,是取值,()通过括号将值返回
- patsubst:字符串匹配替换函数,第一个参数是替换后的值,第二个参数是替换前的值,第三个参数是需要替换的字符串
obj=$(patsubst ./%.c,./%.o,$(src))
#patsubst,是函数名
#后面三个是patsubst的输入参数,即将src中的字符串值取出来,将所有的.c替换成.o
五、make clean
直接make是生成终极目标
make clean不会在文件夹生成clean,如果clean没有依赖,默认接下来的命令是生成目标
.PHONY:clean
clean:
rm $(obj) $(target) -f
#-f是强制执行,不管有没有都强行执行命令
#需要.PHONY:clean声明clean使其不会比较更新时间,如果本地磁盘有clean也不会造成影响。