-
五大元素
-
指定读取文件
-
include
引用其他文件-
处理
-
注意
-
使用场景
-
搜索
-
路径
- 工作路径
-I dir,--include-dir=dir
的方式声明的一个或多个搜索路径- 默认
prefix/include:(/usr/local/include,/usr/gnu/include,/usr/local/include,/usr/include)
-
无法搜索
- 先输出警告;
- 继续读取,读完以后;
- 再尝试搜索规则生成对应文件;
- 没有规则可以生成也不存在则出错返回.
-
说明
include
的文件都会在读取完了之后尝试搜索规则更新或生成.- 也就是文件也是
target
.一般会定义这样一个规则. - 比如
include xx.mk
,这个xx.mk
是由g++ -MM xx.cpp -o xx.mk
生成.那么xx.mk
就可以建立规则,依赖xx.cpp
.
-
安全模式
-include,sinclude
最后无规则生成不报错.继续执行.
-
-
-
MAKEFILES
预读 -
文件也是
target
-
include
冲突 -
make
处理makefile
-
处理的两个阶段
-
变量扩张
-
扩张情况分析
-
include
include
中使用变量或函数会立即扩张.
-
变量赋值
immediate = deferred immediate ?= deferred immediate := immediate immediate ::= immediate immediate += deferred or immediate immediate != immediate define immediate deferred endef define immediate = deferred endef define immediate ?= deferred endef define immediate := immediate endef define immediate ::= immediate endef define immediate += deferred or immediate endef define immediate != immediate endef
+=
要根据变量本身定义的时候是否为立即扩张,即是否是:=,::=
定义的.!=
右边是shell
指令.立即扩张,结果为变量值.- 变量名肯定是马上就要确认,所以都是立即扩张.
-
条件指令
ifeq
中的立即扩张.- 如果要在
recipe
中使用,建议使用shell
对应的条件,因为recipe
只有执行的时候才会处理.
-
规则定义
immediate : immediate ; deferred deferred
- 所有规则的
recipe
都是延迟扩张. - 获取最终值,因为只有在处理
target
的时候才真正需要. - 后面介绍二次扩张的时候可以加深理解
- 所有规则的
-
-
总结
- 五大元素之四,除了注释,都已经介绍了.
-
-
make
解析流程 -
二次扩张
-
说明
-
针对对象
rule
中的prerequisite
.- 更准确的说是在
prerequisite
使用自动变量.
-
自动变量
- 啥样的:
$@,$*,$?
- 看起来和普通的变量没啥区别.
- 根据上面的
make
解析makefile
的流程,在解析内容前就需要进行变量和函数扩张. - 扩张是从环境中找对应值,一般没有定义,得到的是空.
- 这些变量都是解析后的
局部变量
. - 即从已知的
prerequisistes
列表中进行查询.
- 啥样的:
-
二次扩张
- 在解析完了所有的之后,给
prerequisite
再次进行变量解析.
- 在解析完了所有的之后,给
-
二次扩张补充
- 执行完了读取构造有向图后,所有的值都已确定.
- 同样自动变量的值也知道了.
- 在二次扩张的时候是可以看到这些变量的值的.
- 也就是说,在二次扩张的时候可以使用这些变量了.
-
-
二次扩张
-
发生阶段
- 完成有向图构建后,处理任务之前.
-
使用
- 在第一个需要使用二次扩张的
rule
前面定义特殊rule -- .SECONDEXPANSION:;
- 在第一个需要使用二次扩张的
-
处理
- 第一阶段扩张完了之后,在末尾对
prerequisite
的变量引用进行扩张.即$(var) | $V
. - 一般第一阶段后,都被解析为了对应的值,第二次不会再进行解析.
- 如果要解析怎么做呢,先看下面的变量引用介绍和二次扩张案例分析.
- 第一阶段扩张完了之后,在末尾对
-
获取
$
字符$$
- 二次扩张是
$$$$
,后面分析.
-
变量引用
- 两种格式.
$(var)
括号里面的var
为key
进行查表解析.$var
以第一字符v
为key
进行查表解析.
-
案例分析
.ONESHELL: .PHONY:all alla .SECONDEXPANSION: all:$$@a @echo this is $@ alla: @echo this is $@
- 根据
make
解析规则; - 读取数据
all:$$@a
- 不是注释,第一个字符也不是
.RECIPEPREFIX
,也不在rule
上下文中. - 检测到需要扩张
$$
得到$
字符,得到all:$@a
. - 进行数据内联.继续读取.
- 执行完了读取后,对
.SECONDEXPANSION
后的rule
中的prerequisite
再次扩张. - 执行二次扩张,处理
$@a
,查表获取$@
的值,得到变量值为all
,最终结果是alla
. - 处理
target
,默认是all
,处理all
的prerequisite: alla
,执行alla
的规则. - 得到结果
this is alla\nthis is all
.
- 根据
-
变体
.ONESHELL: .PHONY:all alla temp=$$ .SECONDEXPANSION: all:$(temp)@a @echo this is $@ alla: @echo this is $@
- 得到的结果和上面一样.
-
为啥是四个
$
- 因为第一次解析后
$$
变成了$
- 第二次解析就是
$
,即美元符号加空格,得到的是空. - 因此
$$$$
第一次解析是$$
,第二次解析得到$
.
- 因为第一次解析后
-
-
使用
-
变量扩张
-
自变量
-
显式规则
- 对于多
rule
的target
,他们的prerequisite
会依次拼接. - 不同时机出现的自动变量查询到的结果不一样,因为他们都是向前查询.
- 而且因为不会执行
target
处理,所以更新相关的特殊变量无法知晓值,$$?
无法知道值. - 而因为显示规则非正则规则,所以也没有匹配的自动变量
$$*
无法知道值.
- 对于多
-
显示规则案例
foo: foo.1 bar.1 $$< $$^ $$+ # line #1 foo: foo.2 bar.2 $$< $$^ $$+ # line #2 foo: foo.3 bar.3 $$< $$^ $$+ # line #3
- 第一次的
$$<,$$^,$$+
是空,因为还没有构建任何的rule
. - 第二次的
$$<,$$^,$$+
从已有的rule
中查,得到的分别是foo.1,foo.1 bar.1,foo.1 bar.1
,然后将现有的prerequisite
添加到依赖队列中. - 第二次的
$$<,$$^,$$+
从已有的rule
中查,得到的分别是foo.1, foo.1 bar.1 foo.2 bar.2,foo.1 bar.1 foo.2 bar.2 foo.1 foo.1 bar.1 foo.1 bar.1
,然后将现有的prerequisite
添加到依赖队列中.
- 第一次的
-
正则规则
- 正则规则知晓
$$*
的值,即匹配部分. - 但是
$$?
仍然无法知晓.
- 正则规则知晓
-
-
makefile总览
最新推荐文章于 2023-12-26 22:19:14 发布