参考自GNU手册的3.7 How make reads a Makefile
gnu make通过两个独立的phases来完成它的工作。
第一个phase,读取所有的makefile文件,internalize所有的变量以及它们的值、隐式或显式的规则、构造所有的target的依赖图。
第二个phase,使用上面这些内部结构,决定需要更新的targets,执行它们的rules。
根据手册,如果发生在first phase,它是immediate expansion。如果扩展没有立即执行,我们说expansion is deferred。
variable assignment
immediate = deferred
immediate ?= deferred
immediate := immediate
immediate += deferred or immediate
一开始看,左边immediate是啥意思?原来变量名也可以通过变量来指定,变量名是立即扩展的。如:
a = varname
$a = 123
等价于 varname = 123
+= 比较特殊,如果变量之前是简单变量,那么仍然执行立即扩展,否则是延迟扩展。
Conditional Directives
条件语句是立即扩展的,因此,自动变量不能用在条件语句中。
但是需要指出的是,define = 中的条件语句不是立即扩展的,它们是define的内容的一部分。Makefile不会把它们当成make syntax来解析。
1 2 3 4 5 6 7 | define a ifeq ($x,y) b := 1 endif endef $(warning $(value a)) |
如上,warning的打印中,包括ifeq。
Rule Definition
immediate: immediate; deferred
deferred
目标和依赖是立即扩展的,但是recipe是延迟扩展的。
Secondary Expansion
由于依赖是立即扩展的,因此依赖中没办法使用自动变量,如$@,为了解决这个问题,Make提供了二次扩展。
这里就不举例了。