[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[bug #56892] toxic combination of -include and match-anything rules
From: |
David Boyce |
Subject: |
[bug #56892] toxic combination of -include and match-anything rules |
Date: |
Sat, 14 Sep 2019 16:28:33 -0400 (EDT) |
User-agent: |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.75 Safari/537.36 |
URL:
<https://savannah.gnu.org/bugs/?56892>
Summary: toxic combination of -include and match-anything
rules
Project: make
Submitted by: boyski
Submitted on: Sat 14 Sep 2019 08:28:32 PM UTC
Severity: 3 - Normal
Item Group: Bug
Status: None
Privacy: Public
Assigned to: None
Open/Closed: Open
Discussion Lock: Any
Component Version: 4.2.1
Operating System: POSIX-Based
Fixed Release: None
Triage Status: None
_______________________________________________________
Details:
I'm not saying this is a bug necessarily but want to submit it for some sort
of resolution. I an into an infinite loop situation recently. On my advice, in
a very old and complex recursive makefile suite (not of my design or under my
ownership) a co-worker added a construct like the following:
-include foobar.mk
foobar ?= XYZ
The idea is that foobar.mk would be a one-line include file which assigns the
"foobar" variable if it exists and if not we fall back to the default value
"XYZ". This is simple and solved his problem in unit testing but when plugged
into the large old suite it resulted in an infinite loop.
The reason is twofold: (a) if an included makefile doesn't exist make will try
to run a recipe to create it and (b) somewhere deep in this makefile suite was
a match-anything rule. From here it's obvious: make went looking for a recipe
that claimed to be able to make foobar.mk, landed on the match-anything rule
which does a recursive make invocation (and does not create foobar.mk), and
we're off to the races with an infinite make loop.
The situation is illustrated by the following test file:
$ cat Makefile
.PHONY: all
all:
@:$(info making $@)
%:
# @test -f nosuchfile.mk
$(MAKE) $@
#-include nosuchfile.mk
As it stands this works fine:
$ make
making all
If the -include line is enabled the infinite loop happens, but if the test -f
line is also uncommented things work correctly again.
My first thought is that it makes no sense to invoke a recipe to create a
nonexistent file included via -include because the whole point of -include is
to say "I know this file may not exist and that's ok". However, the
documentation says of -include that it:
"... acts like include in every way except that there is no error [...] if any
of the filenames [...] do not exist or cannot be remade."
I guess the "or cannot be remade" is a strong implication that -include files
are subject to remaking so maybe it would hard to "fix" this for compatibility
reasons? And of course there's a difference between a file being out of date
and not existing and it makes perfect sense to want to update a -included file
if it exists.
However, I still think that in the special case where foobar.mk does not exist
and is included with -include the remake attempt should be elided and the
inclusion silently skipped. Whether that's too much of a compatibility break
is a valid question though.
But even stepping back from those details, with either "include" or
"-include", why should make continue if it ran the recipe and the recipe did
not in fact create the file as it claimed it would? In other words, why not do
a check for existence after running the remake recipe (as illustrated in the
test case)? It seems to me that dying with "no such file or directory" would
be preferable to allowing an infinite loop, and furthermore I think this could
be added without breaking (documented) compatibility. AFAICT the manual
discusses only situations where the included file "cannot be remade".
Currently "remaking" seems to be a synonym for "running the recipe which
claims to make it" but tightening that definition to to require that the
recipe actually creates the file seems both more robust and entirely
compatible, not to mention intuitive.
Thus I suggest one or both of these minor tweaks:
1. Fail (with include) or continue (with -include) when, after running the
remake recipe, the file does not exist.
2. Ignore (do not attempt to make) a file included by -include if it does not
exist at all. But if if does exist, go ahead and try to update it.
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/bugs/?56892>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/