Subject: bug#75655: configure doesn't update Makefile

From: Pip Cet <[email-masked]>
Date: Mon, 20 Jan 2025 23:13:20 +0000

"Andreas Schwab" <[email-masked]> writes:

> On Jan 20 2025, Pip Cet wrote:
>
>> "Andreas Schwab" <[email-masked]> writes:
>>
>>> On Jan 20 2025, Pip Cet wrote:
>>>
>>>> I believe that needs an additional order-only prerequisite
>>>> (config.status) to work properly in parallel make: calling config.status
>>>> twice in parallel seems like a very bad idea.  And, of course, a comment
>>>> explaining it.
>>>
>>> The right way to solve this is to tell config.status to only update the
>>> current target.

I'm sorry, I misread your message at first.  Let me summarize it to make
sure I got it right:

One problem with the first solution I proposed:

$(SUBDIR_MAKEFILES_IN) $(CONFIG_STATUS_FILES_IN):
	MAKE='$(MAKE)' ./config.status

is that config.status may be run before, or while, it is being built
(either by configure, or by config.status --recheck);
this won't happen with ordinary "make", but "make -j" would do the
trick.

My proposal was to use an order-only prerequisite:

$(SUBDIR_MAKEFILES_IN) $(CONFIG_STATUS_FILES_IN): | config.status
	MAKE='$(MAKE)' ./config.status

This fixes the problem if there is a single Makefile.in that we're
trying to rebuild, but if more than one Makefile.in simultaneously goes
missing, config.status might be run twice by this code, in parallel.

This can happen and produces confusing output, but I'm not sure it
causes errors: at first glance, config.status appears to create a
temporary new file and move it to "Makefile" atomically.

Your proposal is to modify the line

        MAKE='$(MAKE)' ./config.status

so it builds only the current target $@ of this rule.

Is that accurate so far?

If it is, I'm confused because the target $@ of this rule is, in my
case, benchmark/Makefile.in.

That file does not exist before the rule is executed, and it is not
created by the rule: the effect of the rule is to regenerate "Makefile",
which make will notice and reload the Makefile.  The "target" merely
indicates which file was missing and made us decide to recreate the
Makefile.  The new Makefile will hopefully no longer refer to the
"target" and work.

Did you mean we restrict config.status to generate only Makefile?

As far as I can tell, that modification works, and it saves some output
and presumably some CPU cycles, but it still means we'll invoke

  	MAKE='$(MAKE)' ./config.status --file=Makefile

twice for "make -j" if two of the targets are missing.

So I'm not sure what you are suggesting.  My best guess is that you're
suggesting we somehow pick a single one of the rule's prerequisites
which will cause config.status to run, and ignore all others.  Is that
correct?

MISSING_MAKEFILE_IN := $(firstword $(filter-out $(addprefix ./,$(wildcard $(SUBDIR_MAKEFILES_IN))),$(SUBDIR_MAKEFILES_IN)))
$(SUBDIR_MAKEFILES_IN) $(CONFIG_STATUS_FILES_IN): | config.status
	if [ ./"$@" = "$(MISSING_MAKEFILE_IN)" ]; then sleep 1m; MAKE='$(MAKE)' ./config.status; fi

appears to work, at least, but I don't know what to replace ./ by.

Pip