[SV 65739] Add warning circular-dep.

Add a warning to control circular dependency detection.  Use "warn" as
the default action to be backward-compatible.

* src/warning.h (enum warning_type): Add warning type wt_circular_dep.
* src/warning.c (warn_init): Set default wt_circular_dep to w_warn.
* src/remake.c (update_file_1): Consult the circular-dep warning to
handle circular dependencies.
* tests/scripts/options/warn: Test --warn circular-dep flag.
* tests/scripts/variables/WARNINGS: Test .WARNINGS circular-dep flag.
* doc/make.texi: Document circular-dep warning.
* doc/make.1: Ditto.
This commit is contained in:
Dmitry Goncharov 2024-05-19 18:56:12 -04:00 committed by Paul Smith
parent e3f938caf8
commit a9e3eb1eec
8 changed files with 68 additions and 10 deletions

3
NEWS
View File

@ -83,6 +83,9 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=111&se
defined in the makefiles, one per line, then exit with success. No recipes defined in the makefiles, one per line, then exit with success. No recipes
are invoked and no makefiles are re-built. are invoked and no makefiles are re-built.
* Warnings for detecting circular dependencies are controllable via warning
reporting, with the name "circular-dep".
* 'make --print-data-base' (or 'make -p') now outputs time of day * 'make --print-data-base' (or 'make -p') now outputs time of day
using the same form as for file timestamps, e.g., "2023-05-10 using the same form as for file timestamps, e.g., "2023-05-10
10:43:57.570558743". Previously it used the form "Wed May 10 10:43:57.570558743". Previously it used the form "Wed May 10

View File

@ -379,10 +379,13 @@ can be an action; one of
or or
.I error .I error
to set the default action for all warnings, or it can be a specific warning: to set the default action for all warnings, or it can be a specific warning:
.I circular-dep
(finding a circular dependency),
.I invalid-ref
(referencing an invalid variable name),
.I invalid-var .I invalid-var
(assigning to an invalid variable name), (assigning to an invalid variable name),
.I invalid-ref or
(referencing an invalid variable name), or
.I undefined-var .I undefined-var
(referencing an undefined variable). The behavior of each warning can be set (referencing an undefined variable). The behavior of each warning can be set
by adding by adding

View File

@ -9447,11 +9447,13 @@ Show an error for the usage and immediately stop processing the makefile.
The types of warnings GNU Make can detect are: The types of warnings GNU Make can detect are:
@table @samp @table @samp
@item invalid-var @item circular-dep
@findex invalid-var @findex circular-dep
@cindex warning invalid variable @cindex warning circular dependency
Assigning to an invalid variable name (e.g., a name containing whitespace). Finding a loop in the dependency graph (the prerequisites of a target contain
The default action is @samp{warn}. or depend on the target itself). If the action is not @samp{error}, the
circular reference is dropped from the graph before continuing. The default
action is @samp{warn}.
@item invalid-ref @item invalid-ref
@findex invalid-ref @findex invalid-ref
@ -9459,6 +9461,12 @@ The default action is @samp{warn}.
Using an invalid variable name in a variable reference. The default action is Using an invalid variable name in a variable reference. The default action is
@samp{warn}. @samp{warn}.
@item invalid-var
@findex invalid-var
@cindex warning invalid variable
Assigning to an invalid variable name (e.g., a name containing whitespace).
The default action is @samp{warn}.
@item undefined-var @item undefined-var
@findex undefined-var @findex undefined-var
@cindex warning undefined variable @cindex warning undefined variable

View File

@ -20,6 +20,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "commands.h" #include "commands.h"
#include "dep.h" #include "dep.h"
#include "variable.h" #include "variable.h"
#include "warning.h"
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
@ -635,8 +636,14 @@ update_file_1 (struct file *file, unsigned int depth)
if (is_updating (d->file)) if (is_updating (d->file))
{ {
OSS (error, NILF, _("circular %s <- %s dependency dropped"), /* Avoid macro warning, bacause its output differs from that of
file->name, d->file->name); older makes. */
if (warn_error (wt_circular_dep))
OSS (fatal, NILF, _("circular %s <- %s dependency detected"),
file->name, d->file->name);
if (warn_check (wt_circular_dep))
OSS (error, NILF, _("circular %s <- %s dependency dropped"),
file->name, d->file->name);
if (lastd == 0) if (lastd == 0)
file->deps = du->next; file->deps = du->next;

View File

@ -34,7 +34,8 @@ static const char *w_action_map[w_error+1] = {NULL, "ignore", "warn", "error"};
static const char *w_name_map[wt_max] = { static const char *w_name_map[wt_max] = {
"invalid-var", "invalid-var",
"invalid-ref", "invalid-ref",
"undefined-var" "undefined-var",
"circular-dep"
}; };
#define encode_warn_action(_b,_s) \ #define encode_warn_action(_b,_s) \
@ -66,6 +67,7 @@ warn_init ()
warn_default.actions[wt_invalid_var] = w_warn; warn_default.actions[wt_invalid_var] = w_warn;
warn_default.actions[wt_invalid_ref] = w_warn; warn_default.actions[wt_invalid_ref] = w_warn;
warn_default.actions[wt_undefined_var] = w_ignore; warn_default.actions[wt_undefined_var] = w_ignore;
warn_default.actions[wt_circular_dep] = w_warn;
set_warnings (); set_warnings ();
} }

View File

@ -20,6 +20,7 @@ enum warning_type
wt_invalid_var = 0, /* Assign to an invalid variable name. */ wt_invalid_var = 0, /* Assign to an invalid variable name. */
wt_invalid_ref, /* Reference an invalid variable name. */ wt_invalid_ref, /* Reference an invalid variable name. */
wt_undefined_var, /* Reference an undefined variable name. */ wt_undefined_var, /* Reference an undefined variable name. */
wt_circular_dep, /* A target depends on itself. */
wt_max wt_max
}; };

View File

@ -166,4 +166,17 @@ run_make_test(undef, '--warn=no-such-warn',
run_make_test(undef, '--warn=invalid-var:no-such-action', run_make_test(undef, '--warn=invalid-var:no-such-action',
"#MAKE#: *** unknown warning action 'no-such-action'. Stop.", 512); "#MAKE#: *** unknown warning action 'no-such-action'. Stop.", 512);
# sv 65739. Circular dependency.
run_make_test(q!
hello: hello; @:
!,
'', "#MAKE#: circular hello <- hello dependency dropped\n");
run_make_test(undef, '--warn=error', "#MAKE#: *** circular hello <- hello dependency detected. Stop.\n", 512);
run_make_test(undef, '--warn=circular-dep:error', "#MAKE#: *** circular hello <- hello dependency detected. Stop.\n", 512);
run_make_test(undef, '--warn=warn', "#MAKE#: circular hello <- hello dependency dropped\n");
run_make_test(undef, '--warn=circular-dep:warn', "#MAKE#: circular hello <- hello dependency dropped\n");
run_make_test(undef, '--warn=ignore', '');
run_make_test(undef, '--warn=circular-dep:ignore', '');
1; 1;

View File

@ -154,6 +154,27 @@ all:;
!, !,
'',"#MAKEFILE#:2: unknown warning action 'no-such-action': ignored\n#MAKE#: 'all' is up to date."); '',"#MAKEFILE#:2: unknown warning action 'no-such-action': ignored\n#MAKE#: 'all' is up to date.");
# sv 65739. Circular dependency.
run_make_test(q!
hello: hello; @:
!,
'', "#MAKE#: circular hello <- hello dependency dropped\n");
run_make_test(q!
.WARNINGS = circular-dep:error
hello: hello; @:
!,
'', "#MAKE#: *** circular hello <- hello dependency detected. Stop.\n", 512);
run_make_test(q!
.WARNINGS = circular-dep:warn
hello: hello; @:
!,
'', "#MAKE#: circular hello <- hello dependency dropped\n");
run_make_test(q!
.WARNINGS = circular-dep:ignore
hello: hello; @:
!,
'', '');
# Validate .WARNINGS set as target-specific variables # Validate .WARNINGS set as target-specific variables
# This is not supported (yet...?) # This is not supported (yet...?)