From 3b5e47b2e2904884a9d853848be3348b7cdd4f8a Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Thu, 16 Jan 2020 13:49:07 -0500 Subject: [PATCH] [SV 40657] Reinstate old behavior for suffix rules with prereqs POSIX says that suffix rules cannot have prerequisites, but after making this change we observed a number of makefiles "in the wild" that were relying on this behavior and failed. For .POSIX: makefiles, obey POSIX. Otherwise preserve the old behavior. However, generate a warning so users know this is a problem. In a future version we will change all behavior to be POSIX-conforming. * NEWS: describe the change * src/rule.c (convert_to_pattern): If posix_pedantic don't make a pattern rule if prereqs exist. Otherwise show a warning. * tests/scripts/features/suffixrules: Add tests for the new behavior including .POSIX vs. non-.POSIX. --- NEWS | 16 +++++++++++---- doc/make.texi | 12 +++++++++++ src/rule.c | 18 +++++++++++++--- tests/scripts/features/suffixrules | 33 ++++++++++++++++++++++++------ 4 files changed, 66 insertions(+), 13 deletions(-) diff --git a/NEWS b/NEWS index 283372a7..a33254c8 100644 --- a/NEWS +++ b/NEWS @@ -35,10 +35,18 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=108&set already contains some value. Similarly, appending an empty string does not add a trailing space. -* WARNING: Backward-incompatibility! - Contrary to the documentation, suffix rules with prerequisites were being - treated BOTH as simple targets AND as pattern rules. Behavior now matches - the documentation, and pattern rules are no longer created in this case. +* NOTE: Deprecated behavior. + Contrary to the documentation, suffix rules with prerequisites are being + treated BOTH as simple targets AND as pattern rules. Further, the + prerequisites are ignored by the pattern rules. POSIX specifies that in + order to be a suffix rule there can be no prerequisites defined. In this + release if POSIX mode is enabled then rules with prerequisites cannot be + suffix rules. If POSIX mode is not enabled then the previous behavior is + preserved (a pattern rule with no extra prerequisites is created) AND a + warning about this behavior is generated: + warning: ignoring prerequisites on suffix rule definition + The POSIX behavior will be adopted as the only behavior in a future release + of GNU make so please resolve any warnings. * New feature: Grouped explicit targets Pattern rules have always had the ability to generate multiple targets with diff --git a/doc/make.texi b/doc/make.texi index 8be8a364..560e3b3d 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -12731,6 +12731,18 @@ receive only part of the information necessary. In this case, the child will generate this warning message and proceed with its build in a sequential manner. +@item warning: ignoring prerequisites on suffix rule definition +According to POSIX, a suffix rule cannot contain prerequisites. If a rule +that could be a suffix rule has prerequisites it is interpreted as a simple +explicit rule, with an odd target name. This requirement is obeyed when +POSIX-conforming mode is enabled (the @code{.POSIX} target is defined). In +versions of GNU @code{make} prior to 4.3, no warning was emitted and a +suffix rule was created, however all prerequisites were ignored and were not +part of the suffix rule. Starting with GNU @code{make} 4.3 the behavior is +the same, and in addition this warning is generated. In a future version +the POSIX-conforming behavior will be the only behavior: no rule with a +prerequisite can be suffix rule and this warning will be removed. + @end table @node Complex Makefile, GNU Free Documentation License, Error Messages, Top diff --git a/src/rule.c b/src/rule.c index f4c11790..7efca58b 100644 --- a/src/rule.c +++ b/src/rule.c @@ -272,11 +272,23 @@ convert_to_pattern (void) memcpy (rulename + slen, dep_name (d2), s2len + 1); f = lookup_file (rulename); - /* No target, or no commands, or it has deps: it can't be a - suffix rule. */ - if (f == 0 || f->cmds == 0 || f->deps != 0) + /* No target, or no commands: it can't be a suffix rule. */ + if (f == 0 || f->cmds == 0) continue; + /* POSIX says that suffix rules can't have prerequisites. + In POSIX mode, don't make this a suffix rule. Previous versions + of GNU make did treat this as a suffix rule and ignored the + prerequisites, which is bad. In the future we'll do the same as + POSIX, but for now preserve the old behavior and warn about it. */ + if (f->deps != 0) + { + if (posix_pedantic) + continue; + error (&f->cmds->fileinfo, 0, + _("warning: ignoring prerequisites on suffix rule definition")); + } + if (s2len == 2 && rulename[slen] == '.' && rulename[slen + 1] == 'a') /* A suffix rule '.X.a:' generates the pattern rule '(%.o): %.X'. It also generates a normal '%.a: %.X' rule below. */ diff --git a/tests/scripts/features/suffixrules b/tests/scripts/features/suffixrules index a18c3637..b8f46526 100644 --- a/tests/scripts/features/suffixrules +++ b/tests/scripts/features/suffixrules @@ -51,7 +51,9 @@ run_make_test(q! unlink('foo.baz'); -# Test #4: Suffix rules with deps are not suffix rules +# SV 40657: Test #4: "Suffix rules" with deps are normal rules + +my $prewarn = 'warning: ignoring prerequisites on suffix rule definition'; touch('foo.bar'); @@ -59,20 +61,39 @@ run_make_test(q! .SUFFIXES: .SUFFIXES: .biz .baz +$X.POSIX: + .baz.biz: foo.bar ; @echo make $@ from $< !, - '.baz.biz', "make .baz.biz from foo.bar\n"); + 'X=1 .baz.biz', "#MAKEFILE#:7: $prewarn\nmake .baz.biz from foo.bar\n"); + +# SV 40657: Test #5: In POSIX mode we don't get a warning + +run_make_test(undef, 'X= .baz.biz', "make .baz.biz from foo.bar\n"); unlink('foo.bar'); -# Test #5: Should not create pattern rules for it either +# SV 40657: Test #6: In POSIX mode, no pattern rules should be created -touch('foo.baz'); +utouch(-20, 'foo.baz'); run_make_test(undef, - 'foo.biz', "#MAKE#: *** No rule to make target 'foo.biz'. Stop.\n", 512); + 'X= foo.biz', "#MAKE#: *** No rule to make target 'foo.biz'. Stop.\n", 512); -unlink('foo.baz'); +# SV 40657: Test #7: In Non-POSIX mode, a pattern rule is created + +run_make_test(undef, + 'X=1 foo.biz', "#MAKEFILE#:7: $prewarn\nmake foo.biz from foo.baz\n"); + +# SV 40657: Test #8: ... but any prerequisites are ignored + +utouch(-10, 'foo.biz'); +touch('foo.bar'); + +run_make_test(undef, + 'X=1 foo.biz', "#MAKEFILE#:7: $prewarn\n#MAKE#: 'foo.biz' is up to date.\n"); + +unlink('foo.baz', 'foo.biz', 'foo.bar'); # Complete 1;