目录
在韦东山的ARM视频里面有一节是讲解makefile的,虽然工作中一直在用makefile,但还是把这节视频看了,然后简单笔记如下。
1.makefile的引入
如果我们不使用makefile,而是使用gcc -o test a.c b.c进行编译,那么每次编译时所有的文件都会被编译一次,没有修改的文件也会被重新编译,我们应该对文件分别进行编译,然后链接,
gcc -c -o a.o a.c
gcc -c -o b.o b.c

gcc -o test a.o b.o
假如我们只修改了a.c,那么我们只需要重新编译a.c,然后链接就好了。
我们如何判断文件是否被修改呢,通过比较文件生成时间,例如如果a.c的时间比a.o的时间新,那么就认为a.c被修改了,这时候就会重新编译a.c。
用makefile的术语就是当依赖比目标新,就执行命令。
2.makefile的规则
目标 : 依赖1 依赖2 ...
[TAB]命令
当"目标文件"不存在,
或
某个依赖文件比目标文件"新",
则: 执行"命令"
3.makefile简单语法
a. 通配符: %.o
$@ 表示目标
$< 表示第1个依赖文件
$^ 表示所有依赖文件
b. 假想目标: .PHONY
执行make命令时,后面可以跟目标名,例如make clean ,也可以不跟目标明,如果没有目标名,默认生成第一个目标。
clean:
rm *.o
上面的这种定义目标的方式,如果我们的工程中有一个clean文件夹,那么执行make clean时将不会执行清楚命令,我们需要把clean定义成假象目标。
clean:
rm *.o
.PHONY: clean
c. 即时变量、延时变量, export
简单变量(即时变量) :
A := xxx # A的值即刻确定,在定义时即确定
B = xxx # B的值使用到时才确定
例如:
A := $(C) #A在定义时就要马上确定她的值,但是这时候C还没有定义,C为空,所以A为空。
B = $(C)
C = abc
all:
@echo $(A) #打印出来空。
@echo $(B)
:= # 即时变量
= # 延时变量
?= # 延时变量, 如果是第1次定义才起效, 如果在前面该变量已定义则忽略这句
+= # 附加, 它是即时变量还是延时变量取决于前面的定义
4.makefile常用函数
a. $(foreach var,list,text)
对于list中的每一个var变量执行text公式,例如
A = a b c
B = $(foreach f, $(A), $(f).o)
all:
@echo B = $(B)
打印结果:B = a.o b.o c.o
b. $(filter pattern...,text) # 在text中取出符合patten格式的值
$(filter-out pattern...,text) # 在text中取出不符合patten格式的值
C = a b c d/
D = $(filter %/, $(C)
E = $(filter-out %/, $(C))
all:
@echo D=$(D)
@echo E=$(E)
打印结果:
D=d/
E= a b c
c. $(wildcard pattern) # pattern定义了文件名的格式,
# wildcard取出其中存在的文件
files = $(wildcard *.c)
all:
@echo files=$(files)
打印结果:当前目录下的三个文件, a.c b.c c.c
d. $(patsubst pattern,replacement,$(var)) # 从列表中取出每一个值
# 如果符合pattern
# 则替换为replacement
例如:
files = a.c b.c c.c d.c e.c
dep_files = $(patsubst %.c , %.d, %(files2))
all:
@echo dep_files = $(dep_files)
5.Makefile实例
a. 改进: 支持头文件依赖
http://blog.csdn.net/qq1452008/article/details/50855810
gcc -M c.c // 打印出依赖
gcc -M -MF c.d c.c // 把依赖写入文件c.d
gcc -c -o c.o c.c -MD -MF c.d // 编译c.o, 把依赖写入文件c.d。-MD 不会像 -M 那样阻止正常的编译任务,因为它默认关闭了 -E 选项,比如命令中使用了 -c 选项,其结果要生成 .o 文件,若使用了 -M 选项,则不会生成 .o 文件,若使用的是 -MD 选项,则会生成 .o 文件。
#Makefile
objs = a.o b.o c.o
dep_files := $(patsubst %,.%.d, $(objs))
dep_files := $(wildcard $(dep_files))
CFLAGS = -Werror -Iinclude
test: $(objs)
gcc -o test $^
ifneq ($(dep_files),)
include $(dep_files)
endif
%.o : %.c
gcc $(CFLAGS) -c -o $@ $< -MD -MF [email protected]
clean:
rm *.o test
distclean:
rm $(dep_files)
.PHONY: clean