Make和Makefile

make是一个命令,makefile是一个文件

#用于注释代码

make命令扫描makefile时从上往下,如果直接执行make,会优先执行第一条命令

例1:

1
2
code:code.c					依赖关系
gcc code.c -o code 依赖方法

:左侧是目标文件,右侧是依赖文件列表(可以是多个)

第二行以tab开头,不能是空格,说明了如何从依赖文件形成目标文件

例2:

1
2
3
.PHONY:clean
clean:
rm -f code

.PHONY是一种修饰符,被其修饰的clean称为伪目标

后两行的语法与例1一致,另外clean的依赖文件列表可以为空

当被声明为伪目标时,说明该指令总是被执行,反之说明不总是被执行

例如对于gcc命令不声明伪目标,是因为默认旧代码不需要重新编译

make判断代码新旧的原理

通过比较源文件和可执行程序的Modify time,如果源文件比可执行程序新,那么认为是新代码,否则是旧代码

linux中查看文件会修改该文件的Access time,修改时间会产生大量的io,所以只有查看超过一定次数后才会发生时间更新

Modify time在修改文件内容后会发生更新,change time在修改文件属性后会发生更新,往往前者更新会伴随后者

touch命令可以同时更新文件的所有时间

makefile执行时内部会维护一个类似栈的结构,将无法执行的命令入栈,直到可以执行再依次出栈执行

例3:

1
2
3
4
BIN=myproc					#定义变量BIN,赋值为myproc
.PHONY:test
test:
@echo $(BIN) #用$后加()表示引用变量,make执行命令默认回显,命令前用@可以让命令不回显

makefile中也有特殊变量用于简化代码:

​ $@ 表示目标文件

​ $^ 表示整个源文件列表

例4:

1
2
%.o:%.c						# %类似于makefile下的通配符,将当前路径下所有.o/.c依次展开
$(CC) $(FLAGS) $< # <用于依次指定展开的每个文件

例5:

1
2
3
SRC=$(shell ls *.c)			# $中可以直接调用shell命令,以此获取所有源文件名
SRC=$(wildcard *.c) # wildcard是makefile自己的命令,功能同上
OBJ=$(SRC:.c=.o) # 将SRC的每个变量名中.c换成.o作为OBJ变量,以此获得所有obj文件名