如何为包含模式化先决条件的makefile模式规则定义特定于模式的变量?

如何为包含模式化先决条件的makefile模式规则定义特定于模式的变量?,makefile,gnu-make,Makefile,Gnu Make,我知道您可以为规则定义特定于模式的变量,而无需任何先决条件,如下所示: %.o: var = 2 %.o: %.c 对于适用于以.o结尾的所有目标的配方,这将变量var设置为2。这一点在报告中有明确说明。但是如何为包含模式先决条件的模式规则定义特定于模式的变量,如下所示: %.o: var = 2 %.o: %.c 假设我有makefile的这一部分: %.o: %.c (recipe here) %.o: %.b (recipe here) 我只想为%.o:%.b规

我知道您可以为规则定义特定于模式的变量,而无需任何先决条件,如下所示:

%.o: var = 2
%.o: %.c
对于适用于以.o结尾的所有目标的配方,这将变量
var
设置为2。这一点在报告中有明确说明。但是如何为包含模式先决条件的模式规则定义特定于模式的变量,如下所示:

%.o: var = 2
%.o: %.c
假设我有makefile的这一部分:

%.o: %.c
    (recipe here)

%.o: %.b
    (recipe here)
我只想为
%.o:%.b
规则定义一个特定于模式的变量,但我不知道该怎么做(如果可能的话)。我想做这样的事情,但当然不行:

%.o: %.c
    (recipe here)

%.o: %.b: var = 2
    (recipe here)

有办法吗?

您只能为目标设置变量,而不能设置规则<代码>%.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)
操作的大脑是宏
规则var
。它将把变量值包装在一个先决条件匹配的
if-else
表达式中。对于其他特定于规则的值,表达式也保存在
规则变量-$1-$3
变量中


$$(如果$$)(我找到了另一个解决方案,尽管它可能会变得有点难以阅读,这取决于进行了多少先决条件比较。也许有一种方法可以重构它

# Return 1 if prerequisite ends in `.c`.
# Return 2 if prerequisite ends in `.b`.
build-var = $(if $(filter %.c,$<),1,$(if $(filter %.b,$<),2))

%.o: private var = $(build-var)
%.o: %.c
    (recipe here)

%.o: %.b
    (recipe here)
#如果先决条件以“.c”结尾,则返回1。
#如果先决条件以“.b”结尾,则返回2。

build var=$(if$(filter%.c$)我正试图遵循语法,但有一点困难。行
$$(if$$)(@smeep)就是这样。你很清楚你的东西。我仍在研究你的答案,但在这样做的过程中可能找到了另一个解决方案,我发布了。