bugmake - Bugs: bug #64964, GNU Make deletes intermediate...

 
 

bug #64964: GNU Make deletes intermediate targets that are pattern-rule dependancies

Submitter:  Pablo Rackham <pablorackham>
Submitted:  Sat 02 Dec 2023 04:42:27 PM UTC
   
 
Severity:  3 - Normal Item Group:  None
Status:  Not A Bug Privacy:  Public
Assigned to:  None Open/Closed:  Closed
Component Version:  None Operating System:  None
Fixed Release:  None Triage Status:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Mon 04 Dec 2023 12:43:14 AM UTC, comment #2: 

As Dmitry says this is not a bug.

You are confusing "built-in rules" and "implicit rules".

Built-in rules are built into make and will be present regardless of whether a makefile is parsed are not, unless you remove them with the -r option.

Implicit rules are suffix rules or pattern rules.

Explicit rules are rules that specify an explicit target (are not implicit rules).

Built-in rules are always implicit (since it doesn't really make sense to have explicit built-in targets).

But, implicit rules don't have to be built in: any suffix or pattern rule, even ones that are defined in a makefile, are still implicit.

You don't have to use .SECONDARY etc.  All you have to do is mention the targets you want to be preserved as a target or prerequisite SOMEWHERE in the makefile.  So in your example, all you have to do is define some target that lists these files you don't want to be deleted as a prerequisite.

The reason that make re-runs the sh all the time is that your pattern rule is not creating its target.  That is, if your makefile was like this:


foo%: foo%.txt
        cat $<
        touch $@
foo%.txt: foo%.sh
        sh $< > $@


then make would know, because foo1 exists and is newer than foo1.sh, that foo1.txt did not need to be rebuilt.

If you don't want to do that you could create a rule like:

all-txts : foo1.txt foo2.txt foo3.txt ... fooN.txt

and that would be enough to avoid these targets being deleted as intermediate targets.

If you want to discuss this further I recommend sending an email to the -email is unavailable- mailing list.

Paul D. Smith <psmith>
Group administrator
Sat 02 Dec 2023 05:10:35 PM UTC, comment #1: 

The rules in this example 'foo%: foo%.txt' and 'foo%.txt: foo%.sh' are implicit. Implicit rules can be specified in the makefile. Make's behavior is correct.

Dmitry Goncharov <dgoncharov>
Sat 02 Dec 2023 04:42:27 PM UTC, original submission:  

Hello all,

I believe a GNU Make behavior I just stumbled upon should qualify as a bug, as it completely break the principle of least surprise for the user, as well as the philosophy of the Make tool.

How Make is expected to work:
Usually, targets that are built as dependancies by Make are not deleted. That is even the essence of why Make is useful: if it needs to build some .o object file from .c and .h source files when it is asked to build a binary, it will do so and keep the .o files there for next time to avoid rebuilding them everytime.

Bug reproduction:
This behavior is broken when the specified target uses a %-pattern. See for example this Makefile:

foo%: foo%.txt
        cat $<
foo%.txt: foo%.sh
        sh $< > $@


Expected behavior:
Given this Makefile, and how Make is expected to work, I would expect that:

  • running `make foo1` a first time will run ./foo1.sh, save its output to foo1.txt, and then show the content of foo1.txt ;
  • running `make foo1` a second time, since the foo1.txt file is already there and since foo1.sh has not been modified since the first run, it should just show the content of foo1.txt.


Actual behavior:
Given this Makefile, running `make foo1` will run ./foo1.sh, save its output to foo1.txt, then show the content of foo1.txt, and then it will rm foo1.txt.
This behavior causes Make to rerun the .sh files to rebuild the .txt files every time.

I'm aware of what GNU Make calls "chains", and the documentation explicitely says that intermediate files of implicit chains are deleted (the given example is a .c file that is auto-generated from a .y file), but in my example the chain should not be considered implicit: all the rules are written in the Makefile, they are not default rules that are implicitely there.

-----

I'm aware that I can add `.SECONDARY:` to tell Make not to delete intermediate targets, but I believe it should not happen at all with explicitely written rules.

Imagine a Makefile that, over time, comes to look like this:

foo1: foo1.txt
        cat $<
foo2: foo2.txt
        cat $<
foo3: foo3.txt
        cat $<
...
fooN: fooN.txt
        cat $<

foo%.txt: foo%.sh
        sh $< > $@


It's only natural to rewrite it as in the example given above to reproduce the undesired behavior. Except that the rewrite, which looks just like a sensical simple refactoring is actually completely changing the behavior.

Pablo Rackham <pablorackham>

 

(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 dgoncharov (Posted a comment)
  • -email is unavailable- added by pablorackham (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.

     

    Follow 2 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2023-12-04 psmith StatusNone Not A Bug
        Open/ClosedOpen Closed

    Back to the top

    Powered by Savane 3.13-04b1.
    Corresponding source code