Secondary Expansion(二次展开)
官方手册解释:
GNU make also has the ability to enable a second expansion of the prerequisites (only) for some or all targets defined in the makefile. In order for this second expansion to occur, the special target .SECONDEXPANSION must be defined before the first prerequisite list that makes use of this feature.
根据手册可知,make提供了 second expansion, 但是 二次展开 只存在于 target 的依赖(prerequisites)中, 并且使用 secondary expansion 必须要定义特殊目标 .SECONDEXPANSION
dirs= dira, dirb, dirc
all:
for d in $(dirs); \
do \
echo "current dir: $$d"; \
done;
上面一段代码在很多讲解二次展开的博客和文档中都会举的例子,认为 echo "current dir: $$d"; 使用了二次展开的概念,但是根据手册上的定义,大家这种说法是正确的吗?答案是肯定不对,因为二次展开只存在于依赖中,上面的代码中的 $$d 是存在于 recipe中的。但是 $$d 到底是个什么鬼呢?下面就涉及到 makefile 中 "escape the variable or function reference" 的这个概念.
Escape the variable or function reference
在 make 的手册上有这么一句话:
In order to take advantage of the secondary expansion phase of the parser, then, it’s necessary to escape the variable or function reference in the makefile.
这句话很简单,就是说二次展开是利用 escape the variable or function reference 来实现的。我们都知道在makefile中变量和函数都是通过 $ 来引用的。实现 escape 就是使用 $$ , 所以 echo "current dir: $$d" 在第一次展开后就会变成 echo "current dir: $d" ,然后传个 bash 去执行。
conclusion
- 二次展开仅存在于依赖中
- escape 就是使用 $$
- 二次展开并不等价于 $$ , 但它使用了 $$ 来实现的