makefile中有条件的变量?

Pet*_*ith 1 makefile gnu-make

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

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

问题是,无论是var=foo还是var=bar,result永远都是false。替换$(var)为foo或bar将产生正确的结果。

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

使用命令运行以下 makefile make -f make.txt

.PHONY: all
all:
     X=aaa; \
     Y=aaa; \
     if [[ '$(filter $(X),$(Y))' ]]; then echo "matched!"; else echo "not matched!"; fi
Run Code Online (Sandbox Code Playgroud)

输出:

X=aaa; \
Y=aaa; \
if [[ '' ]]; then echo "matched!"; else echo "not matched!"; fi
not matched!
Run Code Online (Sandbox Code Playgroud)

为什么当它失败X,并Y在目标配方被赋值?

bob*_*ogo 5

显然 GNU Make 条件中没有布尔类型

显然有,否则$(if ...)宏的存在是没有意义的!

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

配方整体扩展一次。然后逐行执行结果扩展的每一行。每次执行都在shell 的一个新实例中运行。

因此,以您的原始 makefile 为例,假设您已要求make构建${DEF_TARGET}. Make扩展配方:

if [ "$(CHECK)" != "y" ]; then \
        var=foo; \
        $(if $(filter foo,$(var)),result=true,result=false); \
fi
Run Code Online (Sandbox Code Playgroud)
  • ${CHECK} 变得一无所有(说)
  • $(if $(filter foo,$(var)),result=true,result=false)
    • 首先,${var}被扩展并且也变成空的(比如说)。请注意,var=foo配方中的行不会被 make 解释!这是一个shell命令。

    • 接下来,$(filter foo,)被扩展,也是空的。

    • 接下来make expands $(if ,result=true,result=false),result=false当然会产生。

      if [ "" != "y" ]; then \
         var=foo; \
         result=false; \
      fi
      
      Run Code Online (Sandbox Code Playgroud)

      由于反斜杠,Make将其视为一行。

所以,不要混淆shell变量和make变量。当 shell 拿到配方时,所有的make变量都消失了。 Make对 shell 变量一无所知。

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

result=$(if $(filter y,${CHECK}),true,false)
Run Code Online (Sandbox Code Playgroud)

(TIMTOWTDI 适用)。外壳获取result=true或result=false取决于make变量的值CHECK。