您只能为目标设置变量,而不是规则。 %.o: %b 是一条规则,其中 %.o 是目标模式(因此称为“特定于模式”的名称)。
解决此问题的常用方法是在配方中使用以太硬编码值或使用特定于规则的标志(在您的情况下可能是 CVAR 和 BVAR)。
编辑: 从头开始。想出了一个解决方法。
这可以通过利用变量的递归评估来完成。
all: a.o b.o c.o
$(shell touch a.xx b.yy c.zz)
##
# Create rule-specific variable... rules
#
# @param 1 Target.
# @param 2 Prerequisite.
# @param 3 Variable name.
# @param 4 Variable value.
#
rule-var = $(eval $(rule-var-body))
define rule-var-body
$1: private $3 = $$(if $$(<:$2=),$(or $(value rule-var-$1-$3),$(value $3)),$4)
$2: $3 = $4
rule-var-$1-$3 = $$(if $$(<:$2=),$(or $(value rule-var-$1-$3),$(value $3)),$4)
endef
VAR = $(VAR_DEFAULT)
# Declare couple of test values
$(call rule-var,%.o,%.x,VAR,x-value)
$(call rule-var,%.o,%.y,VAR,y-value)
VAR_DEFAULT := z-value
ECHO_RULE_RECIPE = @echo -e '$@: $^\t(VAR = $(VAR))'
%.o: %.x
$(ECHO_RULE_RECIPE)
%.o: %.y
$(ECHO_RULE_RECIPE)
%.o: %.z
$(ECHO_RULE_RECIPE)
%.x: %.xx
$(ECHO_RULE_RECIPE)
%.y: %.yy
$(ECHO_RULE_RECIPE)
%.z: %.zz
$(ECHO_RULE_RECIPE)
输出是:
a.x: a.xx (VAR = x-value)
a.o: a.x (VAR = x-value)
b.y: b.yy (VAR = y-value)
b.o: b.y (VAR = y-value)
c.z: c.zz (VAR = z-value)
c.o: c.z (VAR = z-value)
操作的大脑是宏rule-var。它将变量值包装在匹配if-else 表达式的先决条件中。该表达式还保存在 rule-var-$1-$3 变量中,用于其他特定于规则的值。
$$(if $$(<:$2=),$(or $(value rule-var-$1-$3),$(value $3)),$4)去混淆:
$$(if $$(<:$2=), 将通过将其模式 ($2) 替换为空字符串来测试第一个先决条件值 ($<)。
不幸的是,当被继承时,这个 if-else 怪物将无法正确扩展,因此它被声明为 private 并使用简单的第二条规则进行修复。
在本例中,将声明以下 3 条规则。
%.o: private VAR = $(if $(<:%.y=),$(if $(<:%.x=),$(VAR_DEFAULT),x-value),y-value)
%.y: VAR = y-value
%.x: VAR = x-value
限制
即使有变通方法,变量的全局对应项仍然会被隐藏。如果您需要一个默认值,请在调用rule-var之前分配它。全局值被复制为特定规则变量的一部分,但在使用之前不会扩展。