问题
This question is a follow-up to What makefile lazy evaluation rule governs this behavior?. I'm still trying to grok some of the rules of gnu make's lazy evaluation.
I want to have a make variable for the content of a directory after that directory has been updated by a recipe.
This Makefile demonstrates that $(A_FILE)
is evaluated to find the created file when it's in the "parent" of the recipe that actually creates the file:
A_FILE = $(wildcard subdir/*)
all: a
@echo $(A_FILE)
a:
@mkdir ./subdir
@touch subdir/b
$ rm -rf ./subdir/ && make
subdir/b
$
But the following Makefile has a seemingly trivial change: $(A_FILE)
is referenced in the recipe where its containing directory is updated - but now the variable is empty:
A_FILE = $(wildcard subdir/*)
all: a
@echo $(A_FILE)
a:
@mkdir ./subdir
@touch subdir/b
@sleep 1
@echo $(A_FILE)
$ rm -rf ./subdir/ && make
$
I added the sleep
to rule out timing issues of the directory being trawled too quickly after it had been updated.
What gives? Why does $(A_FILE)
get evaluated against the updated subdir content if it's referenced in the higher-layer recipe but not in the lower-layer recipe where it's actually updated?
回答1:
GNU make evaluates all lines in the recipe before it starts running any line in the recipe. So, when it is getting ready to run your recipe for the rule a
it first expands all the lines, including the last line with $(A_FILE)
in it. At that point no parts of the recipe have been run yet so the result is empty.
Then after all the expansion, the shell is invoked to run the lines in the recipe.
来源:https://stackoverflow.com/questions/64084643/why-does-makefile-lazy-evaluation-find-a-file-in-a-parent-recipe-but-not-the-c