Makefile的二次展开

来源:互联网 发布:thinking in java在线 编辑:程序博客网 时间:2024/04/29 13:41
make 在执行的时候是分成两个阶段的, 第一阶段叫读入阶段, 第二阶段是更新目标阶段

在第一阶段, make读入include等文件, 并对变量进行替换, 展开隐式规则等, 这一阶段就是生成合适makefile的过程

在第二阶段是执行阶段, 根据第一阶段生成的makefile, 根据规则对需要更新的目标进行更新


但如果在规则下面的命令中, 用到了循环, 则会涉及到二次展开的问题, 所谓二次展开就是在第二阶段再展开一次
比如下面的例子:
dirs= dira, dirb, dirc
 all:
      for d in $(dirs);                        \
      do                                             \
             echo "current dir: $d";      \
       done;      
由于在规则下面的命令只能是一条一条的, 所以for循环要用 “\” 跟“;”连起来构成一条命令

上面最后的结果是输出三句话
current dir:
current dir:
current dir:
这跟我们想要的不符,我们来看看原因, 先看第一阶段的展开
 dirs= dira, dirb, dirc
 all:
      for d in dira dirb dirc;                        \
      do                                             \
             echo "current dir: $d";      \, d实际上是没有定义的,它被展开成空字符串
       done;     由于在第一阶段的展开中, d实际上是没有定义的,它被展开成空。 这里要注意的是第一阶段它只是读跟展开,并没有执行, 所以d不会被定义成for循环中对应的现
按照上面的的展开,我们就知道为什么会有那样的输出

为了看的更清楚一点,对makefile稍微改造一下
 dirs= dira, dirb, dirc
 d=/home
 all:
      for d in $(dirs);                        \
      do                                             \
             echo "current dir: $d";      \
       done;     我们会得到输出:
current dir: /home
current dir: /home
current dir: /home

这是因为它在第一阶段展开成如下的内容
 dirs= dira, dirb, dirc
 d=/home
 all:
      for d in dira dirb dirc;                        \
      do                                             \
             echo "current dir: /home";      \d被展开成了/home
       done;     
那么我们如何才能得到预期的目标呢? 这就要用到二次展开的概念,让它在第二阶段再展开一次
dirs= dira, dirb, dirc
 all:
      for d in $(dirs);                        \
      do                                             \
             echo "current dir: $$d";      \
       done;      在第一阶段后展开成
 dirs= dira, dirb, dirc
 all:
      for d in dira dirb dirc;                        \
      do                                             \
             echo "current dir: $d";      \
       done;     
这样在第二阶段执行的时候, $d就会展开成for中对应的列表了, 即dira, dirb跟dirc
0 0
原创粉丝点击