Makefile 定义一个目标,该目标依赖于需要解析的值/变量

Makefile 定义一个目标,该目标依赖于需要解析的值/变量,makefile,Makefile,更新了我的问题,因为它似乎不够清楚 我正在列出何时使用makeoverbash。我喜欢make的一点是它描述必要步骤的声明方式;我们可以通过依赖知道如何提供必要文件(或其他外部状态)的其他规则来编写规则 我想知道我如何才能在不改变外部世界的情况下(比如留下一个临时文件),为值而不是文件获得同样的好处 我们可以在规则中的命令开头使用$(call prepare_name,…)强制准备一个必要的值,但这不是我想要的 当我打开这个问题时,我把我的尝试作为一个答案。希望这能为我的目标增加更多信息。我能想

更新了我的问题,因为它似乎不够清楚

我正在列出何时使用makeoverbash。我喜欢
make
的一点是它描述必要步骤的声明方式;我们可以通过依赖知道如何提供必要文件(或其他外部状态)的其他规则来编写规则

我想知道我如何才能在不改变外部世界的情况下(比如留下一个临时文件),为值而不是文件获得同样的好处

我们可以在规则中的命令开头使用
$(call prepare_name,…)
强制准备一个必要的值,但这不是我想要的


当我打开这个问题时,我把我的尝试作为一个答案。希望这能为我的目标增加更多信息。

我能想出一种使用
eval
函数的方法。下面假设
foo
是通过复杂计算获得的值

hello.txt: var_name
    echo Hello $($<) > $@

.PHONY: var_name
var_name:
    $(eval $@ = foo)
另一种方法是使用特定于目标的变量。它没有将变量列为先决条件,但我仍然不需要考虑在编写
echo Hello…
时如何获取
var\u name

define get_name
echo foo
endef

hello.txt: var_name = $(call get_name)
hello.txt:
    echo Hello $(var_name) > $@

不过,我们并不十分清楚您的目标是什么,只是想澄清一些概念:

目标必须依赖于其他目标。它不能依赖于变量名。如果变量解析为目标名称,则它可能取决于变量的值

所以你可以做:

VAR=some_target
hello.txt: $(VAR)
    echo "hello $^" > $@   

some_target:
    touch $@
你不能这样做:

VAR=some_target
hello.txt: VAR
并期望它能够工作(make将尝试构建
VAR
,但它可能不存在,并且会失败)

我假设您想从问题中请求一个人的变量名,并将其输入hello.txt。在这种情况下,您可能希望将名称存储在临时文件中,并将其用于输出:

 .getname.txt:
     @read -p "enter name" name > $@

 hello.txt: .getname.txt
     @echo "hello $$(cat $$<)" > $@

它将调用hello.txt规则,不管hello.txt是否已经存在,并且将始终提示用户输入名称并重新生成hello.txt。

如其他答案中所述,使用时间戳跟踪文件之间的依赖关系。处理值的常规解决方案是将其存储在文件中(或将其生成到文件中)。假设每当数据发生变化时都有大量工作要做,您可以按照下面的模式之一对文件值实施依赖性检查

只有当var value的内容被修改时,下面的makefile快照才会触发复杂结果的重建。当var值的内容不断重新生成,但不会频繁更改时,这非常有用

all: complex-result

last-value.txt: var-value.txt
        cmp -s $< $@ || cat <$^ > $@

complex-result: last-value.txt
        echo Buildig for "$$(cat var-value.txt)"
        touch $@
all:复杂结果
last-value.txt:var-value.txt
cmp-s$<$@类别$@
复杂结果:last-value.txt
“$$(cat var value.txt)”的回显构建
触碰$@
或者更现实的示例:如果使用md5校验和修改了任何文件的值(内容),则触发生成

all: complex-result

last-value.txt: $((wildcard *.data)
    md5sum $^ > $@ 

last-value.txt: var-value.txt
        cmp -s $< $@ || cat <$^ > $@

complex-result: last-value.txt
        echo Building for "$$(cat var-value.txt)"
        touch $@
all:复杂结果
last-value.txt:$((通配符*.data)
md5sum$^>$@
last-value.txt:var-value.txt
cmp-s$<$@类别$@
复杂结果:last-value.txt
“$$(cat var value.txt)”的回显生成
触碰$@

我可以问一下您想要实现什么吗?对没有持久性的东西的依赖性(即跨越多个make调用)通常由makefile的编程部分解决。Hi@Vroomfondel,我列出了何时使用makeoverbash。我喜欢make的一个方面是描述必要步骤的声明性方式,但它在中间步骤更新外部状态(通常通过创建文件)时效果很好,而在更新内部状态(变量)时效果不好。我想看看如何将变量视为先决条件,并通过假设另一条规则负责准备必要的值来专注于正确处理规则。但这可能会使事情复杂化,最好通过命令式的方式,调用变量以在
hello.txt
规则中生成值。这还不太清楚你在追求什么。它将如何解析人名?该名称在变量或文件中是否可用?是否希望它提示一个人输入其姓名?@HardcoreHenry我不想在特定情况下获取值(
var\u name
)在这里,但有一些复杂的计算,我想把它从hello.txt规则中分离出来。值检索可能取决于其他目标。我正在探索一种一般的模式,目前还没有真正的用例……感谢@HardcoreHenry,我正在探索如何使目标依赖于值/变量,即使这样做并不自然
make
。我相信您的临时文件解决方案与我的一个解决方案是一致的:)谢谢@dash-o,我本来应该在我的问题中写出来的,但我想在make执行后,我不会留下
var value.txt
last value.txt
;因此将其描述为价值。但是是的,如果情况是这样的,那么在数据更改之后需要做大量的工作,保留文件是有意义的。
 hello.txt:
     @read -p "enter name: " name && echo "hello $$name" > $@

 .PHONY: hello.txt
all: complex-result

last-value.txt: var-value.txt
        cmp -s $< $@ || cat <$^ > $@

complex-result: last-value.txt
        echo Buildig for "$$(cat var-value.txt)"
        touch $@
all: complex-result

last-value.txt: $((wildcard *.data)
    md5sum $^ > $@ 

last-value.txt: var-value.txt
        cmp -s $< $@ || cat <$^ > $@

complex-result: last-value.txt
        echo Building for "$$(cat var-value.txt)"
        touch $@