How Makefiles Are Remade - don't understand official documentation

Viewed 293

I can't understand chapter 3 of official gmake documentation starting from section 3.5

https://www.gnu.org/software/make/manual/make.html#Remaking-Makefiles

Docs say: ... after reading in all makefiles make will consider each as a goal target and attempt to update it. If a makefile has a rule which says how to update it ...., it will be updated if necessary. After all makefiles have been checked, if any have actually been changed, make starts with a clean slate and reads all the makefiles over again. (It will also attempt to update each of them over again, but normally this will not change them again, since they are already up to date.) Each restart will cause the special variable MAKE_RESTARTS to be updated.

So I try with this mkfile ( presence of the -include as G.M. has suggested changes nothing ):

all:
        echo all $(MAKE_RESTARTS) aaa

#-include: mkfile

mkfile:
        echo touch
        touch mkfile

I expect that after mkfile runs first time mkfile modification time changed and make must run it again and again. But nothing happens:

$ make -f  mkfile 
echo all  aaa
all aaa
$

Moreover, target "mkfile" not called as expecting from docs: after reading in all makefiles make will consider each as a goal target and attempt to update it.

What I'm misunderstand ? Can you, please, give an example of what docs mean about "remading" makefiles?

UPD: I've tried Andreas' suggestions but got strange results again :

  1. original mkfile but run with --always-make
 $ make --always-make -f mkfile 
echo touch
touch
touch mkfile
echo all 1 aaa
all 1 aaa

here target "mkfile" runs once and target "all" runs once too. The results of consequence runs are repeatable.

  1. If I change target "mkfile" to force run, results a strange and differ from invocation to invocation: mkfile:
all:
    echo all $(MAKE_RESTARTS) aaa

mkfile: force
    echo touch
    touch mkfile

force: ; 

results:

$ make -f mkfile 
echo touch
touch
touch mkfile
echo touch
touch
touch mkfile
echo touch
touch
touch mkfile
................
touch mkfile
echo touch
touch
touch mkfile
echo all 16 aaa
all 16 aaa
$ make -f mkfile 
echo touch
touch
touch mkfile
echo touch
touch
touch mkfile
echo touch
touch
touch mkfile
echo all 2 aaa
all 2 aaa

$ make -f mkfile
echo touch
touch
touch mkfile
...............
touch mkfile
echo all 13 aaa
all 13 aaa
$

UPD2 - about MAKE_RESTARTS

--always-make respects MAKE_RESTARTS only if makefile's target has no prerequisites.

mkfile:

all:
    echo all $(MAKE_RESTARTS) aaa

mkfile:
    echo touch $(MAKE_RESTARTS)
    sleep 0.5
    touch mkfile

result:

$ make --always-make -f  mkfile
echo touch 
touch
sleep 0.5
touch mkfile
echo all 1 aaa
all 1 aaa
$

if makefile's target has force prerequisite, loop is infinite (I even try to set MAKE_RESTARTS by force to value greater than 0 )

mkfile:

MAKE_RESTARTS := 1

all:
    echo all $(MAKE_RESTARTS) aaa

mkfile: force
    echo touch $(MAKE_RESTARTS)
    sleep 0.5
    touch mkfile

force: ; 

result:

$ make --always-make -f  mkfile
echo touch 1
touch 1
sleep 0.5
touch mkfile
echo touch 1
touch 1
sleep 0.5
touch mkfile
echo touch 1
touch 1
sleep 0.5
touch mkfile
^C
1 Answers

For this:

all:
        echo all $(MAKE_RESTARTS) aaa
mkfile:
        echo touch
        touch mkfile

When make -f mkfile runs it tries to build mkfile. The make manual says that if a target has no prerequisites, then if it exists it's considered up-to-date (how can it be out of date when it doesn't depend on anything?) Since the mkfile file exists (obviously), this rule is really a no-op. If you want to see the behavior of rebuilding makefiles then the makefile has to have some prerequisite which shows that it's out of date.

If you run it with --always-make you'll run across this statement in the GNU make manual:

GNU make proceeds to consider targets and their prerequisites using the normal algorithms; however, all targets so considered are always remade regardless of the status of their prerequisites. To avoid infinite recursion, if MAKE_RESTARTS is set to a number greater than 0 this option is disabled when considering whether to remake makefiles.

(Emphasis added).

If you run with a force target, then it will be updated as you've seen. For some operating systems this will run forever. However for others, at some point the touch command will run fast enough that it won't actually change the modification time of the mkfile file; it will be so fast that the modification time before and after the command runs will be the same. When a recipe runs but doesn't change the modification time of that target, then the target is not considered to be modified and any rules that depend on it will not be considered out-of-date because of that target.

When that happens, make believes that the target was not changed and it no longer re-execs itself.

Related