更新了我的问题,因为它似乎还不够清楚!
我正在列出何时使用make over bash。我喜欢make
的一件事是它描述必要步骤的声明方式。我们可以依靠其他规则来编写规则,知道如何提供必要的文件(或其他外部状态)。
我想知道如何在不更改外部环境的情况下(例如保留临时文件)为value而不是文件获得相同的好处。
hello.txt: (here, tell that it needs to resolve person's name)
# Here, person's name is available.
echo Hello $(var_name) > $@
我们可以在规则中命令的开头强制使用$(call prepare_name, ...)
准备必要的值,但这不是我想要的。
当我打开这个问题时,我将我的尝试作为答案。希望可以为我要实现的目标添加更多信息。
并不太清楚你要做什么,但是要澄清一些概念:
一个目标必须依赖于其他目标。它不能依赖于变量名。如果该变量解析为目标名称,则可以依赖于该变量的值。
所以您可以这样做:
VAR=some_target
hello.txt: $(VAR)
echo "hello $^" > $@
some_target:
touch $@
您不能做:
VAR=some_target
hello.txt: VAR
并期望它能正常工作(make会尝试构建可能不存在的C0并失败)。
我假设您要提出一个问题来请求一个人的变量名,并将其放入hello.txt中。在这种情况下,您可能希望将名称存储在一个临时文件中,并将其用于输出:
VAR
如果以前不存在,它将更新.getname.txt(因此不一定会在每次make调用时询问...)。您可以将.getname.txt设为.PHONY目标,并且每次都会运行。
如果您确实希望每次都运行,那么只需执行以下操作:
.getname.txt:
@read -p "enter name" name > $@
hello.txt: .getname.txt
@echo "hello $$(cat $$<)" > $@
无论hello.txt是否已存在,都会调用hello.txt规则,并且始终提示用户输入名称并重建hello.txt。
我可以想到一种使用 hello.txt:
@read -p "enter name: " name && echo "hello $$name" > $@
.PHONY: hello.txt
功能的方法。下面假设eval
是通过复杂计算获得的值。
foo
或者使用hello.txt: var_name
echo Hello $($<) > $@
.PHONY: var_name
var_name:
$(eval $@ = foo)
目标,这也可以,但是我觉得它更复杂。
.INTERMEDIATE
另一种方法是使用特定于目标的变量。它没有列出变量作为先决条件,但是我仍然不需要考虑在编写var_name = var-name.txt
hello.txt: $(var_name)
echo Hello $$(< $<) > $@
.PHONY: $(var_name)
.INTERMEDIATE: $(var_name)
$(var_name):
rm -f $@ # In case the var file already exists
echo bar > $@
时如何获取var_name
。
echo Hello ...
如其他答案所述,请使用时间戳记来跟踪文件之间的依赖关系。处理值的常规解决方案是将其存储在文件中(或将其生成到文件中)。假设每当数据更改时都有大量工作要做,您可以按照以下一种模式对文件值进行依赖检查。
仅当修改var-value的内容时,以下makefile快照才会触发重新生成复杂结果。当连续重新生成var-value的内容但不经常更改时,此功能很有用。
define get_name
echo foo
endef
hello.txt: var_name = $(call get_name)
hello.txt:
echo Hello $(var_name) > $@
或更实际的例子:如果使用md5校验和修改了任何文件的值(内容),则触发构建,
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 $@