What is the difference between running sleep 1
vs $(shell sleep 1)
?
Bare sleep 1
in a recipe is executed when the recipe runs. $(shell sleep 1)
in a recipe is executed when make
expands variable and function references in the recipe, before (any of) it runs.
This makes a difference in your example because
AA
is a recursively expanded variable (the only kind supported by traditional make
), and
make
fully expands the recipe before executing any of it, and
make
expands variable and function references in the recipe in the order they appear.
Therefore, when you make b
, variable $(AA)
is (recursively) expanded three times, one right after the other, which is very likely to produce the same result each time. Each of those results is interpolated into the recipe. Then the recipe is run, and the sleep
s happen in between printing the previously-computed, likely identical timestamps.
On the other hand, when you make a
, the $(shell sleep 1)
expansions occur while make
is expanding the recipe, between the expansions of $(AA)
(which in turn runs date
and captures the result). In this case, the three runs of date
should be expected ordinarily to yield results that differ by the sleep time.
As @RenaudPacalet remarked in comments, you pretty much never want to use $(shell)
inside a recipe. It is more than likely to confuse you, and you don't need it there, because recipes are executed by the shell already. Just write shell code.
Personally, I recommend avoiding $(shell)
altogether, and most other GNU make
"functions" as well, for the sake of portability. Not all make
s are GNU make
.