我有一个看起来像这样的Makefile:
.PHONY: aws-deps
requirements.txt: Pipfile Pipfile.lock
pipenv lock -r > $@
aws-deps: requirements.txt
pip3 install --upgrade --target aws_src/ -r $<
如果我多次运行make requirements.txt
,则正确地表明它是最新的。但是,如果我运行make aws-deps
时,它不会像我期望的.PHONY
目标那样运行,则无论requirements.txt
是否已更改,它都会每次运行。例如,首先删除Requirements.txt:
$ make aws-deps
pipenv lock -r > requirements.txt
pip3 install --upgrade --target aws_src/ -r requirements.txt
<snip>
$ make aws-deps
pip3 install --upgrade --target aws_src/ -r requirements.txt
<snip>
我误解了.PHONY
部门的职责吗?我希望aws-deps仅在先决条件已更改时才执行某项操作,即我对requirements.txt进行了更改-有人知道我无法做到这一点吗?
谢谢!
答案 0 :(得分:2)
.PHONY
目标告诉make将目标视为不是文件,即使可能存在一个名称与此目标相同的文件。由于此处没有名为aws-deps
的文件,因此.PHONY
对您的情况没有实际影响。相反,make没有任何东西可以将requirements.txt
的时间戳与之进行比较,并假定必须运行aws-deps
的规则。您可以通过以下方式更改此行为:
AWS_DEP = .aws-deps-done # hidden file to compare a timestamp against
.PHONY: aws-deps
aws-deps: $(AWS_DEP)
$(AWS_DEP): requirements.txt
pip3 install --upgrade --target aws_src/ -r $<
@touch $@
答案 1 :(得分:1)
我经历过类似的案件。我不太喜欢创建另一个隐藏或可见文件。但这就是我经常看到的。我查阅了 GNU make手册 [谁做的更多了?],希望作者考虑过如此明显的内容。我找到了目标.INTERMEDIATE
,它不希望文件更新。因此,您的示例将是:
requirements.txt: Pipfile Pipfile.lock
pipenv lock -r > $@
.INTERMEDIATE: aws-deps
aws-deps: requirements.txt
pip3 install --upgrade --target aws_src/ -r $<
它运行良好,不需要编写额外的文件作为标志。我使用此.INTERMEDIATE
目标类型在批量编译PDF文件之前打印一条消息,并在批量编译PNG文件时打印另一条消息。如果尝试使用.PHONY
,将重复编译。如果在规则块内打印消息,它将为每个正在处理的文件打印。打印一次性消息是.INTERMEDIATE
的另一种用法。