使用Makefile
gcc编译.c文件的过程
- 预处理:找头文件、展开宏,用编译选项-E生成.i文件,也可用-E -dM编译选项查看,例如:
gcc -E -dM main.c > look.txt
,如果语法错误,不是头文件、宏定义错误,预处理不会报错 - 编译:生成汇编.s文件,编译选项是 -S
- 汇编:汇编文件转成机器代码(二进制),编译选项是 -c
- 链接:链接动、静态库,这两种库实际上也是机器可识别的二进制代码,然后形成可执行文件
这些过程用gcc编译时带上-v可以了解到整个编译过程
例如:gcc main.c -v
为什么引入Makefile?
面对大型程序改动,不管文件有没有修改,仅仅用gcc编译文件时,每次编译都要编译一次所有的文件,效率低,而Makefile通过配置可以编译只改动的文件,就可以很好地解决这个问题。
Makefile的基本规则
Makefile基本规则:当依赖文件比目标文件更加新的时候(表现在时间上)
- 用法是:目标文件 : 依赖文件
- 目标文件我们之前用gcc -o编译.c文件生成的可执行程序的文件
- 依赖文件可理解成是形成目标文件所需要的材料
例如:
vi Makefile
进入Makefile文件编辑
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
make
编译
Makefile常用符号
符号 | 作用 |
---|---|
% | 通配符 |
$@ | 目标文件 |
$^ | 所有依赖文件 |
$< | 一个依赖文件 |
例如:
test: a.o b.o c.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
假想目标的使用
语法:.DHONY :
test: a.o b.o c.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
clean:
rm *.o test
.DHONY : clean
make
编译形成test可执行文件和一些.o文件make clean
可以删除test可执行文件和一些.o文件
Makefile的变量
简单变量(即时变量)
vi Makefile
进入文件练习
例如:
A := $(C)
C = ccc
all:
echo $(A)
make
编译
- 即时变量符号:
:=
- 即时变量的特点是:A的值在定义的时候确定
如果隐藏echo可以这样做:
A := aaa
all:
@echo $(A)
延时变量
B = $C
C = ccc
all:
echo $(B)
C = ddd
- 符号:
=
- 延时变量特点:B的值在使用时才确定
+= 和 ?= 的使用
- 符号
+=
有值连接的作用 - 符号
?=
如果变量使用?=
之前赋过值,再次使用?=
不起作用
例如:
A := 123
B = bbb
B += $(A)
C ?= $(A)
C ?= $(B)
all:
@echo $(B)
@echo $(C)
Makefile函数
foreach
作用:遍历变量值,为变量值添加扩展名
用法:
A = a b c
C = $(foreach B, $(A), $(B).o)
all:
@echo C = $(C)
filter
作用一:找出有特征的变量值
%
是Makefile语法上的通配符
用法:
A = a b c_
B = $(filter %_, $(A))
all:
@echo B = $(B)
作用而:找出不具有指定特征的变量值
用法:
A = a b c_
B = $(filter-out %_, $(A))
all:
@echo B = $(B)
wildcard
作用一:默认列出当前路径以某种格式的文件
*
符号不是Makefile语法上的通配符
用法:
files = $(wildcard *.c)
all:
@echo files = $(files)
作用二:列出当前路径以某种格式的文件与变量的值有交集的文件
用法:
A = a.c b.c c.c d.c f.c
files = $(wildcard $(A))
all:
@echo files = $(files)
patsubst
作用:替换
用法:
A = a.c b.c c.c
files = $(patsubst %.c, %o, $(A))
all:
@echo files = $(files)