1. 编译连接4步曲
2.make的规则
gcc -o test a.c b.c
按照gcc的4步,可以通过以上一条命令获得可执行文件,但有个缺点,当修改其中的一个源文件时,所有的文件都会再处理一次,当文件非常多的时候,整个编译过程就会非常耗时。接下来就是一步步如何改掉这个缺点
Makefile的编译规则很简单,就是比较依赖和目标文件的时间是不是最新的,如果是则不编译,不是就编译
目标 : 依赖1 依赖2 ...
[TAB]命令
3. makefile通配符
本节通过通配符,使一条条的语句变成通用的语句,减少代码量,以及工作的复杂
%.o:表示所用的.o文件
%.c:表示所有的.c文件
$@:表示目标文件
$<:表示第1个依赖文件、
$^:表示所有依赖文件
如果不使用通配符,要达到对每个文件分开编译
test: a.o b.o
gcc -o test a.o b.o
a.o: a.c
gcc -c -o a.o a.c
b.o: b.c
gcc -c -o b.o b.c
clean:
rm *.o test
.PHINY: clean
使用通配符后,只需要添加目标的依赖文件即可
test: a.o b.o c.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
clean:
rm *.o test
.PHONY: clean
4. 变量赋值语句的区别
:= 即是变量
= 延时变量
?= 延时变量,第一次定义是有效,其余无效
+= 附加,它即是延时也是即时,取决于前面定义
A := $(C)
B = $(C)
C = ABC
D = yangding
D ?= guiyu
ALL:
@echo A = $(A)
@echo B = $(B)
@echo D = $(D)
C += 123
5. Makefile的函数
a. $(foreach var, list,text) # 从list中遍历每个值,放入text中
b. $(filter pattern..., text) # 从text中取出符合pattern格式的值
c. $(filter-out pattern..., text) # 从text中取出不符合pattern格式的值
d. $(wildcard pattern) # 从当前路径中取出符合pattern格式的值文件名
d. $(patsubst pattern, replacement,text) # 从text中取出符合pattern格式的值替换成replacement格式的值
A = a b c b/
B = $(foreach f, $(A), $(f).o)
C = $(filter %/, $(A))
D = $(filter-out %/, $(A))
file1 = $(wildcard *.c)
file2 = $(patsubst %.c, %.d, $(file1))
all:
@echo B = $(B)
@echo C = $(C)
@echo D = $(D)
@echo file1 = $(file1)
@echo file2 = $(file2)
6. 修改bug,自动获取依赖
当使用通配章节的makefile后,有个缺陷,即是如果修改.h文件,则因为其不是先相关的依赖,所以,make生成不了。
objs = a.o b.c c.o #把依赖文件编程一个变量
dep_files := $(patsubst %, .%.d, $(objs)) #将所有依赖文件加上前缀和后缀
dep_files := $(wildcard $(dep_files)) #判断存在的文件
GFLAGS = -Werror -Iinclude #编译参数 -Werror:将wing变为err —Iinclude
test : $(objs) #统一使用变量来代替所有依赖
gcc -o test $^ #链接生成可执行程序
@echo dep_files := $(dep_files)
ifneq ($(dep_files),) #如果dep_files不等于空值,也就是说有这个文件时
include $(dep_files) #将这个文件包含进makefile中
endif
%.o : %.c
gcc $(GFLAGS) -c -o $@ $< -MD -MF .$@.d #编译并生成依赖文件
.PHONY: clean
clean:
rm *.o test
distclean :
rm $(dep_files)