Can make restart b/c of generated include while a target is running?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Can make restart b/c of generated include while a target is running?

Victor Sergienko
Hello,

I have a part of a Makefile that does approximately this:
=====
DIRNAME = dir-$(shell date +%Y-%m-%dT%H-%M-%S)
first_target:
    mkdir -p $(DIRNAME)
    ( do something; echo "done" > $(DIRNAME)/.done ) | tee $(DIRNAME)/build.log

# first_target is always executed first.
$(ALL_OTHER_TARGETS): first_target
=====

The Makefile uses some generated includes, so make restarts several
times before commencing.
Now I have a log where $(DIRNAME) in the "mkdir -p" line is different
from $(DIRNAME) used in the following line.

Is it possible that make was restarted while a first_target was
already running? Or could first_target read an outdated value of
$(DIRNAME) for the first time?
Or was this something else?

I'm going to work around this with MAKE_RESTARTS or with deferred
evaluation, or just ditch the $(shell date) part.
But I'd like to understand what is going on.

Thank you!

Reply | Threaded
Open this post in threaded view
|

Re: Can make restart b/c of generated include while a target is running?

Paul Smith-20
On Wed, 2020-05-20 at 17:45 -0700, Victor Sergienko wrote:
> DIRNAME = dir-$(shell date +%Y-%m-%dT%H-%M-%S)
> first_target:
>     mkdir -p $(DIRNAME)
>     ( do something; echo "done" > $(DIRNAME)/.done ) | tee
> $(DIRNAME)/build.log
>
> Now I have a log where $(DIRNAME) in the "mkdir -p" line is different
> from $(DIRNAME) used in the following line.

Of course that's easily possible.  The rule expands to this:

  first_target:
          mkdir -p dir-$(shell date +%Y-%m-%dT%H-%M-%S)
          ( do something; echo "done" > \
                dir-$(shell date +%Y-%m-%dT%H-%M-%S)/.done ) | \
            tee dir-$(shell date +%Y-%m-%dT%H-%M-%S)/build.log

Since you are invoking the date function three times, it's not strange
at all that they would not all have identical output, if the clock
changed in between two of them.

You should use simple variable assignment:

  DIRNAME := dir-$(shell date +%Y-%m-%dT%H-%M-%S)

so that the contents of the variable are expanded exactly once, when
the variable is assigned, and henceforth will have the same value
always.

See https://www.gnu.org/software/make/manual/html_node/Flavors.html


Reply | Threaded
Open this post in threaded view
|

Re: Can make restart b/c of generated include while a target is running?

Victor Sergienko
Thank you!
Shame on me. For some reason, I never figured that r.e. variables are
expanded each time, but believed they are just lazily evaluated.


On Wed, 20 May 2020 at 21:57, Paul Smith <[hidden email]> wrote:

> On Wed, 2020-05-20 at 17:45 -0700, Victor Sergienko wrote:
> > DIRNAME = dir-$(shell date +%Y-%m-%dT%H-%M-%S)
> > first_target:
> >     mkdir -p $(DIRNAME)
> >     ( do something; echo "done" > $(DIRNAME)/.done ) | tee
> > $(DIRNAME)/build.log
> >
> > Now I have a log where $(DIRNAME) in the "mkdir -p" line is different
> > from $(DIRNAME) used in the following line.
>
> Of course that's easily possible.  The rule expands to this:
>
>   first_target:
>           mkdir -p dir-$(shell date +%Y-%m-%dT%H-%M-%S)
>           ( do something; echo "done" > \
>                 dir-$(shell date +%Y-%m-%dT%H-%M-%S)/.done ) | \
>             tee dir-$(shell date +%Y-%m-%dT%H-%M-%S)/build.log
>
> Since you are invoking the date function three times, it's not strange
> at all that they would not all have identical output, if the clock
> changed in between two of them.
>
> You should use simple variable assignment:
>
>   DIRNAME := dir-$(shell date +%Y-%m-%dT%H-%M-%S)
>
> so that the contents of the variable are expanded exactly once, when
> the variable is assigned, and henceforth will have the same value
> always.
>
> See https://www.gnu.org/software/make/manual/html_node/Flavors.html
>
>