Makefile反复使.PHONY目标

时间:2018-06-25 18:06:37

标签: makefile dependencies

我有一个看起来像这样的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进行了更改-有人知道我无法做到这一点吗?

谢谢!

2 个答案:

答案 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的另一种用法。