Callum M
Callum M

Reputation: 2080

Makefile repeatedly making .PHONY target

I have a Makefile which looks like this:

.PHONY: aws-deps

requirements.txt: Pipfile Pipfile.lock
    pipenv lock -r > $@

aws-deps: requirements.txt
    pip3 install --upgrade --target aws_src/ -r $<

If I run make requirements.txt more than once, it correctly says it's up to date. But if I run make aws-deps it doesn't behave as I expect a .PHONY target to, it runs every time regardless of whether requirements.txt has changed. For example, deleting requirements.txt first:

$ 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>

Am I mis-understanding what .PHONY deps do? I want aws-deps to only do something if its prerequisite has changed, ie I have a change in requirements.txt - does anybody know what I'm missing in getting that to work?

Thanks!

Upvotes: 1

Views: 707

Answers (2)

f0nzie
f0nzie

Reputation: 1206

I went through similar case. I wasn't too much of a fan of creating another file .hidden or visible. But that is what I've seen a lot around. I went to the GNU make manual [who does that ANYMORE?], hoping that the authors had considered something so obvious. I found the target .INTERMEDIATE, which is not expecting a file update. So, your example would be then:

requirements.txt: Pipfile Pipfile.lock
    pipenv lock -r > $@

.INTERMEDIATE: aws-deps
aws-deps: requirements.txt
    pip3 install --upgrade --target aws_src/ -r $<

It works well and does not require writing an extra file as a flag. I used this .INTERMEDIATE target type to print a message before a mass compilation of PDF files and another message for similar mass compilation of PNG files. If you try to use .PHONY the compilation will repeat. If you print the message inside the rules block, it will print for every file that is being processed. Printing a one-time message is another use of .INTERMEDIATE.

Upvotes: 1

lubgr
lubgr

Reputation: 38267

.PHONY targets tell make to treat a target as not being a file, even though there might be a file that has a name identical to this target. As there is no file named aws-deps here, .PHONY has no real influence in your case. Instead, make has nothing to compare the timestamp of requirements.txt to and assumes that the rule for aws-deps must be run. You might change this behavior by

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 $@

Upvotes: 5

Related Questions