bugmake - Bugs: bug #58556, Make is confused by a target named...

 
 

bug #58556: Make is confused by a target named ".o" and neither emptying .SUFFIXES nor MAKEFLAGS=r can prevent this

Submitter:  Rossen Mikhov <log65536>
Submitted:  Sat 13 Jun 2020 04:39:34 PM UTC
   
 
Severity:  3 - Normal Item Group:  Bug
Status:  None Privacy:  Public
Assigned to:  None Open/Closed:  Open
Component Version:  4.2.1 Operating System:  None
Fixed Release:  None Triage Status:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Sun 15 Nov 2020 04:48:19 PM UTC, comment #7: 

Duh that should be: "If .SUFFIXES does not contain ".o", then the rule is a target rule not an inference rule."

Paul D. Smith <psmith>
Group administrator
Sun 15 Nov 2020 04:46:41 PM UTC, comment #6: 

I agree this is not right.  Here is what happens:

First, the command line is parsed which creates a goal target named ".o".  Second, because "-r" was not given, the default rules are created.  One of the default rules is the suffix rule for ".o", which sees the already-existing ".o" goal target and applies the recipe to it.  Then finally we try to build.  Since the ".o" is an actual target now, the code that handles -r as part of MAKEFLAGS has no effect on it.  This is clearly not right.  It's a little tricky though because GNU make keeps all the different types of targets in the same big bucket of targets indexed by name.  So, it's not really possible to have both a target ".o" which is a goal target and a target ".o" which is a suffix rule target, but have them be two different things.

I suspect the only way to make it work as the user expects, is to delay the conversion of the command line goals into internal targets until after all makefiles are read in and parsed.

POSIX's requirements here are a little tricky.  If you have a rule with the target ".o" and the ".o" appears as a member of .SUFFIXES, then that rule is an inference rule not a target rule.  If .SUFFIXES does not contain ".o", then the rule is an inference rule not a target rule.  So, you don't really know until the entire makefile has been parsed and you know the final value of .SUFFIXES, which it is.

Paul D. Smith <psmith>
Group administrator
Wed 04 Nov 2020 06:48:26 AM UTC, comment #5: 

Sorry, copied the wrong line.
In my last comment, "| make - foo.o" should be "| make -f - foo.o".

Rossen Mikhov <log65536>
Wed 04 Nov 2020 06:45:59 AM UTC, comment #4: 

It is not ineffective! Did you try it?

touch foo.c
printf MAKEFLAGS=r | make - foo.o
make: * No rule to make target 'foo.o'.  Stop.
make foo.o
cc    -c -o foo.o foo.c

The builtin rule is suppressed by MAKEFLAGS, as expected.
This doesn't work ONLY when the target is named exactly ".o".

But as I said, the point here is not whether MAKEFLAGS=r is effective in principle or not; it is effective whenever it should be and that works fine. If you insist, you can ignore the part of this report that refers to MAKEFLAGS at all, and the bug is still there.

Especially the following point:

> - There are no prerequisites in the empty directory, so an implicit rule with prerequisites should not be invoked at all, whether the rule is builtin or is actually defined in the main makefile. Neither "make foo" nor "make foo.o" tries to invoke "cc" in any way, only "make .o" does.


Matching an implicit rule when its prerequisites are non-existing is in direct contradiction to the manual section 10.8 "Implicit Rule Search Algorithm". So there seems to be an internal rule with no prerequisites for a file named ".o" (which I identified as an explicit, not implicit rule, from the "make -d" output). This is the essence of what I am reporting. Everything else is diagnostics, things I tried in order to investigate the circumstances where this manifests in order to be helpful to the people looking into this. Thank you for bearing with me.

Rossen Mikhov <log65536>
Tue 03 Nov 2020 09:17:43 PM UTC, comment #3: 

printf 'MAKEFLAGS=r \n .SUFFIXES:' | make - .o

is completely ineffective and

printf 'MAKEFLAGS=r \n .SUFFIXES:' | make -f - .o

is ineffective because MAKEFLAGS=r is read after the internal makefile was read.

BTW: it s bad practice to set MAKEFLAGS= as this is an internal variable that is intended for make to communicate with it's sub-make calls.

Jörg Schilling <schily>
Tue 03 Nov 2020 07:32:23 AM UTC, comment #2: 

Reading internal definitions before reading the makefile is fine, but this bug report specifically makes the following points:

- There are no prerequisites in the empty directory, so an implicit rule with prerequisites should not be invoked at all, whether the rule is builtin or is actually defined in the main makefile. Neither "make foo" nor "make foo.o" tries to invoke "cc" in any way, only "make .o" does.

- "make -dp" behaves as if this is an explicit internal rule, specifically matching exactly ".o" and nothing else, not an implicit rule, which seems like a bug.

- True that the internal rules are read before the makefile, but MAKEFLAGS=r should be able to disable their use. It does disable them properly for a file named "foo.o", it only gets confused by a file named ".o".

- In any case, if there are internal rules that are impossible to disable and are going to be used anyway, they should be printed by "make -p", which they are not.

Is all of this still expected?

Rossen Mikhov <log65536>
Mon 02 Nov 2020 01:49:01 PM UTC, comment #1: 

Any make implementation reads the internal make definitions before reading any normal makefile. Your observed behavior is expected behavior.

Jörg Schilling <schily>
Sat 13 Jun 2020 04:39:34 PM UTC, original submission:  

In an empty directory:

$ make .o
cc      -o .o
cc: fatal error: no input files
compilation terminated.
make: * [<builtin>: .o] Error 1

This was unexpected, because no prerequisites exist in the directory.
Looking into the relevant parts from "make -dp .o":

Considering target file '.o'.
 File '.o' does not exist.
 Finished prerequisites of target file '.o'.
Must remake target '.o'.
...
.o:
$(LINK.o) $^ $(LOADLIBS) -o $@

It doesn't mention trying implicit rules, so it seems to be matching the builtin as an explicit rule. Is this intentional?

Even if this is by design, there should be a way to turn it off from the makefile. I tried:

$ printf 'MAKEFLAGS=r \n .SUFFIXES:' | make - .o
cc      -o .o
cc: fatal error: no input files
compilation terminated.
make: * [<builtin>: .o] Error 1

This is strange, because now "make -p" doesn't mention any rules involving ".o" at all, yet it still manages to call the linker.

I should note that "make -r" from the command line does work properly, and "MAKEFLAGS=r" does disable the bulitins for targets not named like a default suffix.

I also note that I found this while trying to fix a buggy makefile. Being able to actually work with a target named ".o" is not important here, it is just that a more correct error message might have helped while debugging the makefile.

Rossen Mikhov <log65536>

 

(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 schily (Posted a comment)
  • -email is unavailable- added by log65536 (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-01-08 psmith Component VersionNone 4.2.1
    2023-01-08 psmith Item GroupNone Bug

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code