makefile中的变量是否有条件?

时间:2016-01-31 13:27:32

标签: makefile gnu-make

显然GNU Make条件中没有布尔类型,所以这似乎是最好的解决方案:

$(DEF_TARGET):
        if [ "$(CHECK)" != "y" ]; then \
                var=foo; \
                $(if $(filter foo,$(var)),result=true,result=false); \
        fi

问题在于,无论var=foo还是var=barresult始终是false。用$(var)foo替换bar会产生正确的结果。

为什么这不起作用?有没有更好的解决方案?

修改

使用命令make -f make.txt

运行以下makefile
.PHONY: all
all:
        X=aaa; \
        Y=aaa; \
        if [[ '$(filter $(X),$(Y))' ]]; then echo "matched!"; else echo "not matched!"; fi

输出:

X=aaa; \
Y=aaa; \
if [[ '' ]]; then echo "matched!"; else echo "not matched!"; fi
not matched!

为目标配方中的XY分配值时,为什么会失败?

2 个答案:

答案 0 :(得分:3)

  

显然GNU Make条件

中没有布尔类型

显然there is,否则$(if ...)宏的存在就没有意义了!

阅读食谱的方法 (即构建目标的shell命令块) 应理解 make 将配方存储为单个递归扩展变量。 仅当 make 需要将一些命令传递给shell时,才会扩展配方。

配方整体扩展一次。 然后逐个执行所得到的扩展的每一行。 每次执行都在shell的 new 实例中运行。

所以, 拿你原来的makefile, 我们假设你已经要求 make 来构建${DEF_TARGET}制作扩展食谱:

   if [ "$(CHECK)" != "y" ]; then \
            var=foo; \
            $(if $(filter foo,$(var)),result=true,result=false); \
    fi
  • ${CHECK}变得一无所知(比如说)
  • $(if $(filter foo,$(var)),result=true,result=false)

    • 首先,${var}已展开,也变为空(​​比如说)。 请注意,配方中的行var=foo由make解释! 这是一个shell命令。
    • 接下来,$(filter foo,)展开,也是空的。
    • 下一步 make 展开$(if ,result=true,result=false),当然会产生result=false

      if [ "" != "y" ]; then \
          var=foo; \
          result=false; \
      fi
      
      由于反斜杠,

      Make 将此视为一行。

所以, 不要混淆shell变量和 make 变量。 在shell获取配方时,所有 make 变量都消失了。 Make 对shell变量一无所知。

您的原始shell代码段可能类似于:

    result=$(if $(filter y,${CHECK}),true,false)

(TIMTOWTDI适用)。 shell会获得result=trueresult=false,具体取决于 make 变量CHECK的值。

答案 1 :(得分:0)

生成文件

.PHONY: all
all:
        @echo "$(filter $(X),$(Y))"

测试

$ make -f make.txt X='xxx yyy' Y='aaa bbb'

$ make -f make.txt X='xxx yyy' Y='aaa xxx'
xxx
$ make -f make.txt X='bbb yyy' Y='aaa bbb'
bbb

GNU Bash在布尔上下文中将非空字符串视为true。所以具有shell级别条件的配方可能是:

all:
        if [[ '$(filter $(X),$(Y))' ]]; then echo "matched!"; else echo "not matched!"; fi