Makefile
我们知道a.c到app可执行程序,经过四个步骤:预处理、编译、汇编、链接;前三个步骤统称为编译。
1、gcc编译:
1)gcc -o test a.c b.c -v流程:
a.c到xxx.s到xxx.o
b.c到yyy.s到yyy.o
最后链接在一起得到一个名为test的可执行文件
缺点:如果只改变一个文件,其他另一个文件也需要再编译一次,浪费资源。
2)改进:
gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -o test a.o b.o
那么如何判断那个文件被修改呢?比较修改时间①若a.c比a.o新,说明被修改了②若a.o/b.o比test更新的话,则需要从新编译;
2、Makefile
1)规则:
目标文件:依赖文件(可多个)
TAB 命令
2)原理:当“依赖”比“目标”新,执行命令。
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
3)语法
%:通配符
$@:目标文件
$<:第一个依赖文件
$^:所有依赖
$(A):“A”是变量,这样代表使用这个变量
@命令:就可以不显示命令本身
test:a.o b.o
gcc -o test a.o b.o
%.o : %.c
gcc -c -o $@ $<
②:假想目标:
test:a.o b.o
gcc -o test a.o b.o
%.o : %.c
gcc -c -o $@ $<
clean:
mk *.c test
make [目标],如无目标,默认第一个目标,有目标则先生成目标;
问题:如果我们目录里没有clean这个文件,默认“依赖”比“目标”新,执行命令,但是如果有名为clean的文件,不执行命令。
这怎么解决呢?
我们就定义他为假想目标即可。
test:a.o b.o
gcc -o test a.o b.o
%.o : %.c
gcc -c -o $@ $<
clean:
mk *.c test
.PHONY:clean
③:即时变量(简单变量)和延时变量
a := xxx
b = xxx
a的值在定义时即可确定,b的值使用到时确定。
举例1:
运行顺序:A为即时变量,在定义时就确定了,但是C还不知道,所以A为空;
B为延时变量,在运行是才确定,则为ABC。
举例2:
运行顺序:A为空;B为123,说明这个C在那里,B都为最后一次的C。
④:更多
:= :即时变量
= :延时变量
?= :延时变量,如果是第一次定义才起效,如果是在前面定义过了则无效。
+= :附加,他是即时变量还是延时变量,取决去前面定义。
举例:
结果:D为100ask,因为D?=xx这句话不是第一次了。
还可以make D = 123456,这样文中的D就不起作用了。
4)函数
①:
$(foreach var, list, text)
举例:
运行原理:将A变量的每个给予.o
结果为:a.o b.o c.o
②:两个函数分别是从列表中取出符合和不符合的数
$(filter pattern..., text)
$(filter-out pattern..., text)
举例:
运行原理:D是取出C变量中符合"%/"这个条件的数;
E是取出变量中不符合"%/"这个条件的数;
结果:D = /d
E = a b c
③:用法一:取出文件夹内符合条件的文件名给返回值
$(wildcard pattern)
举例:
运行原理:取出文件夹内符合*.c的文件名给返回值;
结果:files = a.c b.c c.c
用法二:取出变量中真实存在于文件夹的名字给返回值
举例:
运行原理:取出文件夹中存在于files的文件名字,返回给files3
结果:files3 = a.c b.c .c.
④:把变量内的值符合的改为新的,不符合的不变输出
$(patsubst pattern, replacement, $(var))
示例:
运行原理:将files内.c结尾的变成.d结尾给返回值dep_files。
结果:dep_files = a.d b.d c.d d.d e.d