mirror of
https://git.savannah.gnu.org/git/make.git
synced 2024-12-25 05:29:46 +00:00
[SV 61226] Revert changes to detect missing included files
The fix for SV 60595 introduced a backward-incompatibility: rules that purported to rebuild included files, but didn't actually do so, were treated as errors whereas before they were ignored. This breaks a common idiom in makefiles where an empty recipe is created for an included makefile so make doesn't complain if it doesn't exist. Unfortunately this means make cannot diagnose some types of errors. Extra tests supplied by Dmitry Goncharov <dgoncharov@users.sf.net>. * doc/make.texi (Including Other Makefiles): Clarify this behavior. * src/main.c (main): Don't run the new check-for-errors behavior. * tests/scripts/features/reinvoke: Reset tests of the "old" behavior and add new tests for this situation.
This commit is contained in:
parent
b6a779d262
commit
e72c5e021f
4 changed files with 91 additions and 24 deletions
|
@ -1301,13 +1301,13 @@ command line option @code{-I} with the special value @code{-} (e.g.,
|
|||
forget any already-set include directories, including the default
|
||||
directories.
|
||||
|
||||
If an included makefile cannot be found in any of these directories it
|
||||
is not an immediately fatal error; processing of the makefile
|
||||
containing the @code{include} continues. Once it has finished reading
|
||||
makefiles, @code{make} will try to remake any that are out of date or
|
||||
don't exist. @xref{Remaking Makefiles, ,How Makefiles Are Remade}.
|
||||
Only after it has tried to find a way to remake a makefile and failed,
|
||||
will @code{make} diagnose the missing makefile as a fatal error.
|
||||
If an included makefile cannot be found in any of these directories it is not
|
||||
an immediately fatal error; processing of the makefile containing the
|
||||
@code{include} continues. Once it has finished reading makefiles, @code{make}
|
||||
will try to remake any that are out of date or don't exist. @xref{Remaking
|
||||
Makefiles, ,How Makefiles Are Remade}. Only after it has failed to find a
|
||||
rule to remake the makefile, or it found a rule but the recipe failed, will
|
||||
@code{make} diagnose the missing makefile as a fatal error.
|
||||
|
||||
If you want @code{make} to simply ignore a makefile which does not exist
|
||||
or cannot be remade, with no error message, use the @w{@code{-include}}
|
||||
|
|
|
@ -608,7 +608,7 @@ pattern_search (struct file *file, int archive,
|
|||
if (nptr == 0)
|
||||
continue;
|
||||
|
||||
/* See this is a transition to order-only prereqs. */
|
||||
/* See if this is a transition to order-only prereqs. */
|
||||
if (! order_only && len == 1 && nptr[0] == '|')
|
||||
{
|
||||
order_only = 1;
|
||||
|
|
33
src/main.c
33
src/main.c
|
@ -34,7 +34,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
# include <windows.h>
|
||||
# include <io.h>
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h> /* for strcasecmp */
|
||||
# include <strings.h> /* for strcasecmp */
|
||||
#endif
|
||||
# include "pathstuff.h"
|
||||
# include "sub_proc.h"
|
||||
|
@ -2327,19 +2327,26 @@ main (int argc, char **argv, char **envp)
|
|||
case us_none:
|
||||
/* No makefiles needed to be updated. If we couldn't read some
|
||||
included file that we care about, fail. */
|
||||
{
|
||||
struct goaldep *d;
|
||||
if (0)
|
||||
{
|
||||
/* This runs afoul of https://savannah.gnu.org/bugs/?61226
|
||||
The problem is that many makefiles use a "dummy rule" to
|
||||
pretend that an included file is rebuilt, without actually
|
||||
rebuilding it, and this has always worked. There are a
|
||||
number of solutions proposed in that bug but for now we'll
|
||||
put things back so they work the way they did before. */
|
||||
struct goaldep *d;
|
||||
|
||||
for (d = read_files; d != 0; d = d->next)
|
||||
if (d->error && ! (d->flags & RM_DONTCARE))
|
||||
{
|
||||
/* This makefile couldn't be loaded, and we care. */
|
||||
const char *err = strerror (d->error);
|
||||
OSS (error, &d->floc, _("%s: %s"), dep_name (d), err);
|
||||
any_failed = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (d = read_files; d != 0; d = d->next)
|
||||
if (d->error && ! (d->flags & RM_DONTCARE))
|
||||
{
|
||||
/* This makefile couldn't be loaded, and we care. */
|
||||
const char *err = strerror (d->error);
|
||||
OSS (error, &d->floc, _("%s: %s"), dep_name (d), err);
|
||||
any_failed = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case us_failed:
|
||||
/* Failed to update. Figure out if we care. */
|
||||
|
|
|
@ -89,7 +89,6 @@ include m1.d
|
|||
unlink('m1.d', 'm2.d');
|
||||
|
||||
# Same as before but be sure we get error messages for un-created makefiles
|
||||
|
||||
run_make_test('
|
||||
all: ; @echo RESTARTS=$(MAKE_RESTARTS)
|
||||
|
||||
|
@ -98,10 +97,71 @@ m1.d: ; @echo $@; touch $@
|
|||
m2.d: m1.d ; @test -f $< || { echo $@; touch $@; }
|
||||
|
||||
include m1.d m2.d
|
||||
',
|
||||
'', "m1.d\n#MAKEFILE#:8: m2.d: $ERR_no_such_file\n", 512);
|
||||
', '',
|
||||
# This runs afoul of https://savannah.gnu.org/bugs/?61226
|
||||
0 ? "m1.d\n#MAKEFILE#:8: m2.d: $ERR_no_such_file"
|
||||
: "m1.d\nRESTARTS=1",
|
||||
0 ? 512 : 0);
|
||||
|
||||
unlink('m1.d', 'm2.d');
|
||||
|
||||
# sv 61226.
|
||||
# This set of four cases tests two aspects of make.
|
||||
#
|
||||
# 1. If a rule has no prerequisites or recipe, and the target of the rule is a
|
||||
# nonexistent file, then make imagines this target to have been updated
|
||||
# whenever its rule is run.
|
||||
#
|
||||
# 2. Make does not re-execute itself in this case of imagined target.
|
||||
#
|
||||
# Test case 1.
|
||||
# Make imagines hello.d was updated by a rule without recipe and without
|
||||
# prereqs.
|
||||
# This should succeed.
|
||||
# Make should not re-execute itself.
|
||||
run_make_test('
|
||||
hello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))
|
||||
hello.d:
|
||||
include hello.d
|
||||
', '', "RESTARTS=\n#MAKE#: 'hello.o' is up to date.");
|
||||
|
||||
# Test case 2.
|
||||
# Make imagines hello.d was updated by a rule with a recipe and without
|
||||
# prereqs.
|
||||
# This should succeed.
|
||||
# Make should not re-execute itself.
|
||||
run_make_test('
|
||||
hello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))
|
||||
hello.d:; $(info $@)
|
||||
include hello.d
|
||||
', '', "hello.d\nRESTARTS=\n#MAKE#: 'hello.o' is up to date.");
|
||||
|
||||
&touch('hello.td');
|
||||
# Test case 3.
|
||||
# Make imagines hello.d was updated by a rule without a recipe and with
|
||||
# prereqs.
|
||||
# This should succeed.
|
||||
# Make should not re-execute itself.
|
||||
run_make_test('
|
||||
hello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))
|
||||
hello.d: hello.td
|
||||
include hello.d
|
||||
', '', "RESTARTS=\n#MAKE#: 'hello.o' is up to date.");
|
||||
|
||||
# Test case 4.
|
||||
# Same test as three tests above, but the rule has both recipe and prereqs.
|
||||
# Make should report this error.
|
||||
run_make_test('
|
||||
hello.o: hello.d; $(info $@)
|
||||
hello.d: hello.td; $(info $@)
|
||||
include hello.d
|
||||
', '',
|
||||
# This runs afoul of https://savannah.gnu.org/bugs/?61226
|
||||
0 ? "hello.d\n#MAKEFILE#:4: hello.d: $ERR_no_such_file"
|
||||
: "hello.d\nhello.o\n#MAKE#: 'hello.o' is up to date.",
|
||||
0 ? 512 : 0);
|
||||
|
||||
unlink('hello.td');
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
||||
|
|
Loading…
Reference in a new issue