通配符:
%.o:表示所用的.o文件
%.c:表示所有的.c文件
$\@:表示目标
$<:表示第1个依赖文件
$\^:表示所有依赖文件
gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -c -o c.o c.c
gcc -o test a.o b.o c.o
makefile清除预编译的文件:
C语言编译过程
1.预处理
2.编译
3.汇编
4.链接
我们经常把前三个步骤统称为编译了。我们具体分析:gcc -o test a.c b.c这条命令
它们要经过下面几个步骤:
* 1)对于**a.c**:执行:预处理 编译 汇编 的过程,**a.c ==>xxx.s ==>xxx.o** 文件。
* 2)对于**b.c**:执行:预处理 编译 汇编 的过程,**b.c ==>yyy.s ==>yyy.o** 文件。
* 3)最后:**xxx.o**和**yyy.o**链接在一起得到一个**test**应用程序。
提示:**gcc -o test a.c b.c -v** :加上一个**‘-v’**选项可以看到它们的处理过程,
第一次编译 a.c 得到 xxx.o 文件,这是很合乎情理的, 执行完第一次之后,如果修改 a.c 又再次执行:**gcc -o test a.c b.c**,对于 a.c 应该重新生成 xxx.o,但是对于 b.c 又会重新编译一次,这完全没有必要,b.c 根本没有修改,直接使用第一次生成的 yyy.o 文件就可以了。
缺点:对所有的文件都会再处理一次,即使 b.c 没有经过修改,b.c 也会重新编译一次,当文件比较少时,这没有没有什么问题,当文件非常多的时候,就会带来非常多的效率问题如果文件非常多的时候,我们,只是修改了一个文件,所用的文件就会重新处理一次,编译的时候就会等待很长时间。
对于这些源文件,我们应该分别处理,执行:预处理 编译 汇编,先分别编译它们,最后再把它们链接在一次,比如:
编译:
```bash
gcc -o a.o a.c
gcc -o b.o b.c
```
链接:
```bash
gcc -o test a.o b.o
```
变量
在makefifile中有两种变量:
1), 简单变量(即使变量):
A := xxx # A的值即刻确定,在定义时即确定
对于即使变量使用 “:=” 表示,它的值在定义的时候已经被确定了
2)延时变量
B = xxx # B的值使用到时才确定
对于延时变量使用“=”表示。它只有在使用到的时候才确定,在定义/等于时并没有
确定下来。
想使用变量的时候使用“$”来引用,如果不想看到命令是,可以在命令的前面加上"\@"符号,就不会显
示命令本身。当我们执行make命令的时候,make这个指令本身,会把整个Makefifile读进去,进行全部
分析,然后解析里面的变量。常用的变量的定义如下:
:= # 即时变量
= # 延时变量
?= # 延时变量, 如果是第1次定义才起效, 如果在前面该变量已定义则忽略这句
\+= # 附加, 它是即时变量还是延时变量取决于前面的定义
?=: 如果这个变量在前面已经被定义了,这句话就会不会起效果,
例如========================
A := $(C)
B = $(C)
C = abc
#D = 100ask
D ?= xiaofeng
all:
@echo A = $(A)
@echo B = $(B)
@echo D = $(D)
C += 123
结果========
A =
B = abc 123
D = xiaofeng
分析:
1) A := $(C):
A为即使变量,在定义时即确定,由于刚开始C的值为空,所以A的值也为空。
2) B = $(C):
B为延时变量,只有使用到时它的值才确定,当执行make时,会解析Makefifile里面的所用变量,所以先
解析C= abc,然后解析C += 123,此时,C = abc 123,当执行:\@echo B = $(B) B的值为 abc 123。
3) D ?= weidongshan:
D变量在前面没有定义,所以D的值为weidongshan,如果在前面添加D = 100ask,最后D的值为
100ask。
我们还可以通过命令行存入变量的值 例如:
执行:make D=123456 里面的 D ?= weidongshan 这句话就不起作用了。
结果:
A =
B = abc 123
D = 123456
Makefile函数
makefifile里面可以包含很多函数,这些函数都是make本身实现的,下面我们来几个常用的函数。引用
一个函数用“$”。
函数foreach
函数foreach语法如下:
前两个参数,‘var’和‘list’,将首先扩展,注意最后一个参数 ‘text’ 此时不扩展;接着,对每一个 ‘list’ 扩
展产生的字,将用来为 ‘var’ 扩展后命名的变量赋值;然后 ‘text’ 引用该变量扩展;因此它每次扩展都不
相同。结果是由空格隔开的 ‘text’。在 ‘list’ 中多次扩展的字组成的新的 ‘list’。‘text’ 多次扩展的字串联起
来,字与字之间由空格隔开,如此就产生了函数 foreach 的返回值。
实例:
结果:
函数fifilter/fifilter-out
函数fifilter/fifilter-out语法如下:
实例:
$(foreach var,list,text)
A = a b c
B = $(foreach f, &(A), $(f).o)
all:
@echo B = $(B)
B = a.o b.o c.o
$(filter pattern...,text) # 在text中取出符合patten格式的值
$(filter-out pattern...,text) # 在text中取出不符合patten格式的值结果:
Wildcard
函数Wildcard语法如下:
这个函数 wildcard 会以 pattern 这个格式,去寻找存在的文件,返回存在文件的名字。
实例:
在该目录下创建三个文件:a.c b.c c.c
结果:
我们也可以用wildcard函数来判断,真实存在的文件
实例:
结果:
patsubst函数
函数 patsubst 语法如下:
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
$(wildcard pattern) # pattern定义了文件名的格式, wildcard取出其中存在的文件。
files = $(wildcard *.c)
all:
@echo files = $(files)
files = a.c b.c c.c
files2 = a.c b.c c.c d.c e.c abc
files3 = $(wildcard $(files2))
all:
@echo files3 = $(files3)
files3 = a.c b.c c.c$(patsubst pattern,replacement,\$(var))
patsubst 函数是从 var 变量里面取出每一个值,如果这个符合 pattern 格式,把它替换成
replacement 格式,
实例:
files2 = a.c b.c c.c d.c e.c abc
dep_files = $(patsubst %.c,%.d,$(files2))
all:
@echo dep_files = $(dep_files)
结果:
dep_files = a.d b.d c.d d.d e.d abc