gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 03:13:26 24 4
gpt4 key购买 nike

我知道您可以在没有先决条件的情况下为规则定义特定于模式的变量,如下所示:

%.o: var = 2

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

%.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是目标模式(因此称为“特定于模式”的名称)。

解决此问题的常用方法是在配方中对值进行以太硬编码或使用特定于规则的标志(在您的情况下可能是 CVARBVAR)。

编辑:从头开始。想出了一个解决方法。

这可以通过利用变量的递归评估来完成。

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

  • 如果模式匹配,使用$(or $(value rule-var-$1-$3),$(value $3)) .这是全局变量阴影的解决方法。在你的例子中 %.o: %.c没有 var声明因此它应该使用全局值,但两个规则共享相同的目标,它是不可见的。两者均按值和单个 $ 引用在变量替换阶段扩展表达式。所以结果很整洁 or免费。

    • 使用$(value rule-var-$1-$3)如果它是非零的。即之前已针对此目标和变量名称调用过函数。
    • 否则使用变量的全局值($(value $3))。
  • 否则使用提供的值 ( $4 )。

不幸的是,当继承时,这个 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 分配它。 .全局值被复制为特定于规则的变量的一部分,但在使用之前不会扩展。

关于makefile - 您如何为包含模式先决条件的 makefile 模式规则定义特定于模式的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38513813/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com