【问题标题】:Conditional variables (ifeq) in foreach for explicit make rulesforeach 中用于显式生成规则的条件变量 (ifeq)
【发布时间】:2019-09-29 21:18:52
【问题描述】:

我无法弄清楚在 GNU Make 3.81 中使用带有 foreach 循环的条件定义变量的正确语法。

一个简单的makefile

SET := A B C

define da_loop

ifeq ($(S), A)
    T := equals_A
else
    T := not_equals_A
endif

out_$(S):
    echo "$(S) $$(T)"

endef

$(foreach S, $(SET), $(eval $(call da_loop, $S)))

预期输出:

$ make out_A out_B out_C
echo "A equals_A"
A equals_A
echo "B not_equals_A"
B not_equals_A
echo "C not_equals_A"
C not_equals_A

实际输出:

$ make out_A out_B out_C
echo "A not_equals_A"
A not_equals_A
echo "B not_equals_A"
B not_equals_A
echo "C not_equals_A"
C not_equals_A

在我看来,将“eval”更改为“info”应该可行:

ifeq (A, A)
        T := equals_A
else
        T := not_equals_A
endif

out_A:
        echo "A $(T)"


ifeq (B, A)
        T := equals_A
else
        T := not_equals_A
endif

out_B:
        echo "B $(T)"


ifeq (C, A)
        T := equals_A
else
        T := not_equals_A
endif

out_C:
        echo "C $(T)"

我已经尝试了所有我能想到的额外“$”、引号、= 和 := 的组合,但还没有一个奏效。有什么想法吗?

【问题讨论】:

    标签: gnu-make


    【解决方案1】:

    问题与循环、eval等无关。问题比那个更简单、更根本:在make中,变量是全局定义的,所有规则都只在之后调用整个 makefile 已被解析。 info 技巧实际上确实向您展示了问题。让我们简化一下:

    T := equals_A
    out_A:
            echo "A $(T)"
    
    T := not_equals_A
    out_B:
            echo "B $(T)"
    
    T := not_equals_A
    out_C:
            echo "C $(T)"
    

    问题是所有变量赋值都发生在读入 makefile 时,但配方的扩展直到很久以后才会发生,此时 make 正在构建目标并决定运行配方。因此,您的 makefile 可以等效地写为:

    T := equals_A
    T := not_equals_A
    T := not_equals_A
    
    out_A:
            echo "A $(T)"
    out_B:
            echo "B $(T)"
    out_C:
            echo "C $(T)"
    

    现在你可以看到为什么你会得到你所做的行为。

    有很多方法可以“解决”这个问题,其中最合适的方法取决于您真正想要在真实的 makefile 中做什么。一个非常简单的选择是使用target-specific variables,像这样:

    SET := A B C
    
    define da_loop
    
    ifeq ($(S), A)
        out_$(S): T := equals_A
    else
        out_$(S): T := not_equals_A
    endif
    
    out_$(S):
            echo "$(S) $$(T)"
    
    endef
    
    $(foreach S, $(SET), $(eval $(call da_loop, $S)))
    

    通过使用它,您已指定每个T 变量都绑定到该特定目标的范围,并且每个目标都可以有不同的值。其他选项将是构造变量名称,或者只是使用 $(if ...) 函数将值直接扩展到配方中,而不是将其设置为单独的变量。

    【讨论】:

    • 目标特定变量有效!仅供参考:我的目标是在 $(T) = A 时在命令中添加一个附加标志,而不是在 $(T) = B 或 C 时。
    【解决方案2】:


    ifeq 当然有另一种语法(带引号),
    在引用的文本中没有去除空白!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-07
      • 1970-01-01
      • 2015-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-13
      相关资源
      最近更新 更多