foreach中的条件变量(ifeq)用于显式的make规则

问题描述 投票:1回答:2

我无法弄清楚使用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

将“评估”更改为“信息”在我看来应该是可行的:

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)"

我已经试过可以想到的多余的$,引号,= vs:=的每一种组合,但都没有奏效。有什么想法吗?

gnu-make
2个回答
1
投票

问题与循环,eval等无关。问题比这更简单,更根本:在make中,变量是[[全局定义的,并且所有规则仅在整个makefile具有被解析。 info技巧实际上是DID向您显示问题。让我们简化一下:

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 ...)函数将值直接扩展到配方中,而不是将其设置为单独的变量。]​​>

-1
投票
imageifeq当然还有另一种语法(带引号),在引号内没有空格的去除!
© www.soinside.com 2019 - 2024. All rights reserved.