bugmake - Bugs: bug #66073, $? is set incorrectly in the case...

 
 

bug #66073: $? is set incorrectly in the case of grouped targets.

Submitter:  Dmitry Goncharov <dgoncharov>
Submitted:  Sat 10 Aug 2024 02:15:45 AM UTC
   
 
Severity:  3 - Normal Item Group:  Bug
Status:  None Privacy:  Public
Assigned to:  None Open/Closed:  Open
Component Version:  SCM Operating System:  None
Fixed Release:  None Triage Status:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Mon 12 Aug 2024 02:17:40 AM UTC, comment #4: 


> Maybe the comment intended to use "foo.r" instead?


Right, I meant "foo.r" instead of "foo.q". Sorry for confusion.

> For example if I use the original description and touch foo.p / bar.p first, then I see the "undesired" behavior for both explicit and pattern grouped targets:


I got a different result from GNU Make Head:

  $ rm -f foo.* bar.* ; touch foo.r bar.r; sleep 1; touch foo.p
  bar.p; make-latest xfoo
  $? = foo.r FORCE
  touch foo.p foo.q

  $ rm -f foo.* bar.* ; touch foo.r bar.r; sleep 1; touch foo.p bar.p; make-latest xbar
  $? = FORCE
  touch bar.p bar.q

The behavior is different before/after commit fabb03eac412b5ea19f1a97be31dc8c6fa7fc047, as mentioned here:
https://lists.gnu.org/archive/html/help-make/2024-08/msg00003.html


> If on the other hand I touch foo.q / bar.q first, I see the "desired" behavior for both:


I got the same result for this. I agree this is the "desired" behavior.

Masahiro Yamada <masahiroy>
Mon 12 Aug 2024 12:11:50 AM UTC, comment #3: 

I don't understand why the previous comment is talking about foo.q.  In what way would it ever be correct for foo.q to appear in "$?"?  foo.q is one of the targets and "$?" lists the out of date prerequisites.

Maybe the comment intended to use "foo.r" instead?

I understand what is being requested and it makes sense at some level.  However I can't reproduce the "desired" behavior in the current version of GNU Make HEAD.  I used this makefile:

MAKEFLAGS += -rR
.RECIPEPREFIX = >

xfoo: foo.p foo.q
xbar: bar.p bar.q

foo.p foo.q &: foo.r FORCE
> @echo '$$? = $?'
> touch foo.p foo.q

%.p %.q : %.r FORCE
> @echo '$$? = $?'
> touch $*.p $*.q

.PHONY: xfoo xbar FORCE

to combine both makefiles into a single makefile.

Whether or not we see foo.r (or bar.r) included in the output depends entirely on which target is touched before we start make and which is not.

For example if I use the original description and touch foo.p / bar.p first, then I see the "undesired" behavior for both explicit and pattern grouped targets:

$ rm -f foo.* bar.* ; touch foo.r bar.r; sleep 1; touch foo.p bar.p; make xfoo
$? = FORCE
touch foo.p foo.q

$ rm -f foo.* bar.* ; touch foo.r bar.r; sleep 1; touch foo.p bar.p; make xbar
$? = FORCE
touch bar.p bar.q

If on the other hand I touch foo.q / bar.q first, I see the "desired" behavior for both:

$ rm -f foo.* bar.* ; touch foo.r bar.r; sleep 1; touch foo.q bar.q; make xfoo
$? = foo.r FORCE
touch foo.p foo.q

$ rm -f foo.* bar.* ; touch foo.r bar.r; sleep 1; touch foo.q bar.q; make xbar
$? = bar.r FORCE
touch bar.p bar.q

Am I missing some important aspect of the original example that was posted?

As far as I can see commit fabb03eac412b5ea19f1a97be31dc8c6fa7fc047 is not related to this.  It does change the mtime of also-make targets which maybe is related somehow.

Dmitry's explanation of what is happening is correct.  Whether that's the right behavior or not, needs to be considered.  Also what would be involved with changing the behavior.

Paul D. Smith <psmith>
Group administrator
Sat 10 Aug 2024 04:41:56 AM UTC, comment #2: 

I am interested in this topic because this affects Linux kernel build system (Kbuild).

If foo.q does not appear in $?, I do not know how to make the combination of if_changed and the grouped target working.

foo.p foo.q &: foo.r FORCE
        $(call if_changed,gen_both)

This code works only after GNU Make commit
fabb03eac412b5ea19f1a97be31dc8c6fa7fc047.

But, a pattern rule never works.

%.p %.q : %.r FORCE
        $(call if_changed,gen_both)

This is because $? is used to determine if the build rule should be really executed.

This code:
https://github.com/torvalds/linux/blob/v6.11-rc2/scripts/Kbuild.include#L188

It is true that FORCE is contained in $?, but it is always filtered out.

When foo.q is missing or outdated and GNU Make is building foo.p,
if_changed skips the recipe.

I do not come up with a solution on Kbuild side.

Paul, what do you think?
I believe you know what I am saying because you contributed this:
https://github.com/torvalds/linux/commit/4f1933620f57145212cdbb1ac6ce099eeeb21c5a
Oh, It was 18 years ago...

Masahiro Yamada <masahiroy>
Sat 10 Aug 2024 02:20:45 AM UTC, comment #1: 

A user reported an issue here https://lists.gnu.org/archive/html/help-make/2024-08/msg00001.html.

Here is a copy of that email which contains a good description of the issue.



Hi.


I have two similar Makefiles.


[Makefile1]

.PHONY: all
all: foo.p foo.q

foo.p foo.q &: foo.r FORCE
        @echo \$$? = $?
        touch foo.p ; touch foo.q

.PHONY: FORCE



[Makefile2]

.PHONY: all
all: foo.p foo.q

%.p %.q : %.r FORCE
        @echo \$$? = $?
        touch foo.p ; touch foo.q

.PHONY: FORCE





The two Makefiles are the same, except for one line.
Makefile1 uses grouped targets.
Makefile2 uses a pattern rule with multiple targets.

My hope is that those two work in the same way.


[test Makefile1]

$ rm -f foo.*
$ touch foo.r
$ touch foo.p
$ make -f Makefile1
$? = foo.r FORCE
touch foo.p ; touch foo.q



[test Makefile2]

$ rm -f foo.*
$ touch foo.r
$ touch foo.p
$ make -f Makefile2
$? = FORCE
touch foo.p ; touch foo.q





The value of $? is different.

I just thought this was fixed by
commit fabb03eac412b5ea19f1a97be31dc8c6fa7fc047

In my opinion, the behavior of Makefile1 is preferred.
Is the behavior of Makefile2 expected?


i think, foo.r should not be in $? in this case.
make first considers foo.p. Make finds out that foo.p needs to be rebuilt due to FORCE. The recipe builds both foo.p and foo.q. Automatic variables are set per recipe execution. When this recipe runs, $? is set to FORCE, because FORCE is the prerequisite that caused the recipe to run.
foo.q is not even considered at all at this point.
Then make considers foo.q and finds out that foo.q is already built. Make runs no recipe specifically for foo.q and so no automatic variables are set for foo.q.

Dmitry Goncharov <dgoncharov>
Sat 10 Aug 2024 02:15:45 AM UTC, original submission:  

.

Dmitry Goncharov <dgoncharov>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by psmith (Posted a comment)
  • -email is unavailable- added by masahiroy (Posted a comment)
  • -email is unavailable- added by dgoncharov (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    No changes have been made to this item

    Back to the top

    Powered by Savane 3.14-04e1.
    Corresponding source code