From a0d1e76d604df5bd006fd5ed6a69963d3c6b4d7a Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sat, 18 Mar 2023 17:24:45 -0400 Subject: Add support for .WARNINGS special variable Create a new special variable, .WARNINGS, to allow per-makefile control over warnings. The command line settings will override this. Move the handling of warning flags to a new file: src/warning.c. Allow the decode to work with generic strings, and call it from decode_switches(). * Makefile.am: Add new file src/warning.c. * build_w32.bat: Ditto. * builddos.bat: Ditto. * po/POTFILES.in: Ditto. * src/makeint.h: #define for the .WARNINGS variable name. * src/warning.h: Add declarations for methods moved from main.c. Rename the enum warning_state to warning_action. * src/warning.c: New file. Move all warning encode/decode here from main.c. * src/main.c: Move methods into warning.c and call those methods instead. (main): Set .WARNINGS as a special variable. * src/job.c (construct_command_argv): Rename to warning_action. * src/read.c (tilde_expand): Ditto. * src/variable.c (set_special_var): Update warnings when the .WARNINGS special variable is set. * tests/scripts/options/warn: Check invalid warning options. * tests/scripts/variables/WARNINGS: Add tests for the .WARNINGS special variable. --- tests/scripts/options/warn | 30 ++++--- tests/scripts/variables/WARNINGS | 180 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+), 11 deletions(-) create mode 100644 tests/scripts/variables/WARNINGS (limited to 'tests') diff --git a/tests/scripts/options/warn b/tests/scripts/options/warn index f41f84ff..8c66658e 100644 --- a/tests/scripts/options/warn +++ b/tests/scripts/options/warn @@ -53,7 +53,7 @@ all:; X := $(averyveryveryloooooooooooooooooooooooooooongvariablename) !, '--warn=undefined-var', - "#MAKEFILE#:3: reference to undefined variable 'averyveryveryloooooooooooooooooooooooooooongvariablename' + "#MAKEFILE#:3: warning: reference to undefined variable 'averyveryveryloooooooooooooooooooooooooooongvariablename' #MAKE#: 'all' is up to date.\n" ); @@ -75,8 +75,8 @@ run_make_test(undef, '--warn=undefined-var:ignore', 'ref'); # Check warnings run_make_test(undef, '--warn=undefined-var', - "#MAKEFILE#:7: reference to undefined variable 'UNDEFINED' -#MAKEFILE#:9: reference to undefined variable 'UNDEFINED' + "#MAKEFILE#:7: warning: reference to undefined variable 'UNDEFINED' +#MAKEFILE#:9: warning: reference to undefined variable 'UNDEFINED' ref"); # Check and errors @@ -96,9 +96,9 @@ define nl endef all: ; @echo ref $(also$(nl)bad) $(IREF) $(SIREF)', - '', "#MAKEFILE#:2: invalid variable reference 'bad variable' -#MAKEFILE#:10: invalid variable reference 'also\nbad' -#MAKEFILE#:2: invalid variable reference 'bad variable' + '', "#MAKEFILE#:2: warning: invalid variable reference 'bad variable' +#MAKEFILE#:10: warning: invalid variable reference 'also\nbad' +#MAKEFILE#:2: warning: invalid variable reference 'bad variable' ref"); run_make_test(undef, '--warn=ignore', 'ref'); @@ -133,18 +133,26 @@ foo endef all: ; @echo ref', - '', "#MAKEFILE#:4: invalid variable name 'BAD VAR' -#MAKEFILE#:11: invalid variable name 'NL\nVAR' -#MAKEFILE#:13: invalid variable name 'BAD DEF' -#MAKEFILE#:17: invalid variable name 'NL\nDEF' + '', "#MAKEFILE#:4: warning: invalid variable name 'BAD VAR' +#MAKEFILE#:11: warning: invalid variable name 'NL\nVAR' +#MAKEFILE#:13: warning: invalid variable name 'BAD DEF' +#MAKEFILE#:17: warning: invalid variable name 'NL\nDEF' ref"); run_make_test(undef, '--warn=ignore', 'ref'); run_make_test(undef, '--warn=invalid-var:ignore', 'ref'); -# Check and errors +# Check errors run_make_test(undef, '--warn=invalid-var:error', "#MAKEFILE#:4: *** invalid variable name 'BAD VAR'. Stop.", 512); +# Make sure unknown warnings and actions fail when given on the command line. + +run_make_test(undef, '--warn=no-such-warn', + "#MAKE#: *** unknown warning 'no-such-warn'. Stop.", 512); + +run_make_test(undef, '--warn=invalid-var:no-such-action', + "#MAKE#: *** unknown warning action 'no-such-action'. Stop.", 512); + 1; diff --git a/tests/scripts/variables/WARNINGS b/tests/scripts/variables/WARNINGS new file mode 100644 index 00000000..870a41d0 --- /dev/null +++ b/tests/scripts/variables/WARNINGS @@ -0,0 +1,180 @@ +# -*-perl-*- + +$description = "Test the .WARNINGS variable."; + +my %warn_test = ( + 'warn' => 'warn', 'error warn' => 'warn', + 'error' => 'error', + 'ignore error ignore invalid-var,invalid-ref,undefined-var' => 'ignore,invalid-var,invalid-ref,undefined-var', + 'invalid-ref:ignore error invalid-var:warn,,,,,undefined-var:error,,,,,' => '=error,invalid-var,invalid-ref:ignore,undefined-var:error' +); + +# Verify that values set in .WARNINGS don't get passed to sub-makes + +while (my ($f, $r) = each %warn_test) { + run_make_test(qq! +.WARNINGS = error +\$(info MF=\$(MAKEFLAGS)) +all:; \@#HELPER# env MAKEFLAGS +!, + '', "MF=\nMAKEFLAGS="); +} + +# Verify that make's special variables don't warn even if they're not set +run_make_test(q! +.WARNINGS = undefined-var +vars := $(.VARIABLES) $(MAKECMDGOALS) $(MAKE_RESTARTS) $(CURDIR) +vars += $(GNUMAKEFLAGS) $(MAKEFLAGS) $(MFLAGS) $(MAKE_COMMAND) $(MAKE) +vars += $(MAKEFILE_LIST) $(MAKEOVERRIDES) $(-*-command-variables-*-) +vars += $(.RECIPEPREFIX) $(.LOADED) $(.FEATURES) +vars += $(SHELL) $(.SHELLFLAGS) $(MAKE_TERMOUT) $(MAKE_TERMERR) +vars += $(.DEFAULT) $(.DEFAULT_GOAL) $(-*-eval-flags-*-) $(SUFFIXES) +vars += $(VPATH) $(GPATH) +all:; +!, + '', "#MAKE#: 'all' is up to date."); + +# sv 63609. +# Test for buffer overrun in warn_undefined. +run_make_test(q! +.WARNINGS = undefined-var +all:; +X := $(averyveryveryloooooooooooooooooooooooooooongvariablename) +!, + '', "#MAKEFILE#:4: warning: reference to undefined variable 'averyveryveryloooooooooooooooooooooooooooongvariablename' +#MAKE#: 'all' is up to date.\n" +); + +# Check undefined variable warnings + +# With no options or with ignore, nothing should happen +run_make_test(' +.WARNINGS := $(warnval) +EMPTY = +EREF = $(EMPTY) +UREF = $(UNDEFINED) + +SEREF := $(EREF) +SUREF := $(UREF) + +all: ; @echo ref $(EREF) $(UREF)', + '', 'ref'); + +run_make_test(undef, 'warnval=undefined-var:ignore', 'ref'); + +# Check warnings +run_make_test(undef, 'warnval=undefined-var', + "#MAKEFILE#:8: warning: reference to undefined variable 'UNDEFINED' +#MAKEFILE#:10: warning: reference to undefined variable 'UNDEFINED' +ref"); + +# Check and errors +run_make_test(undef, 'warnval=undefined-var:error', + "#MAKEFILE#:8: *** reference to undefined variable 'UNDEFINED'. Stop.", 512); + +# Check invalid variable reference warnings + +# With no options we still check for invalid references +run_make_test(' +.WARNINGS = $(warnval) +IREF = $(bad variable) +SIREF := $(IREF) + +define nl + + +endef + +all: ; @echo ref $(also$(nl)bad) $(IREF) $(SIREF)', + '', "#MAKEFILE#:3: warning: invalid variable reference 'bad variable' +#MAKEFILE#:11: warning: invalid variable reference 'also\nbad' +#MAKEFILE#:3: warning: invalid variable reference 'bad variable' +ref"); + +run_make_test(undef, 'warnval=ignore', 'ref'); + +run_make_test(undef, 'warnval=invalid-ref:ignore', 'ref'); + +# Check and errors +run_make_test(undef, 'warnval=invalid-ref:error', + "#MAKEFILE#:3: *** invalid variable reference 'bad variable'. Stop.", 512); + +# Check invalid variable name warnings + +# With no options we still check for invalid references +run_make_test(' +.WARNINGS = $(warnval) +EMPTY = +SPACE = $(EMPTY) $(EMPTY) +BAD$(SPACE)VAR = foo + +define nl + + +endef + +NL$(nl)VAR = bar + +define BAD$(SPACE)DEF := +foo +endef + +define NL$(nl)DEF := +foo +endef + +all: ; @echo ref', + '', "#MAKEFILE#:5: warning: invalid variable name 'BAD VAR' +#MAKEFILE#:12: warning: invalid variable name 'NL\nVAR' +#MAKEFILE#:14: warning: invalid variable name 'BAD DEF' +#MAKEFILE#:18: warning: invalid variable name 'NL\nDEF' +ref"); + +run_make_test(undef, 'warnval=ignore', 'ref'); + +run_make_test(undef, 'warnval=invalid-var:ignore', 'ref'); + +# Check errors +run_make_test(undef, 'warnval=invalid-var:error', + "#MAKEFILE#:5: *** invalid variable name 'BAD VAR'. Stop.", 512); + +# Make sure unknown warnings and actions are only noted but not failed on: +# this allows makefiles to be portable to older versions where those warnings +# didn't exist + +run_make_test(q! +.WARNINGS = no-such-warn +all:; +!, + '',"#MAKEFILE#:2: unknown warning 'no-such-warn': ignored\n#MAKE#: 'all' is up to date."); + +run_make_test(q! +.WARNINGS = invalid-var:no-such-action +all:; +!, + '',"#MAKEFILE#:2: unknown warning action 'no-such-action': ignored\n#MAKE#: 'all' is up to date."); + + +# Validate .WARNINGS set as target-specific variables +# This is not supported (yet...?) + +# run_make_test(q! +# ok := $(undef) +# ref = $(undef) + +# all: enabled disabled enabled2 ; + +# .WARNINGS = undefined-var + +# enabled enabled2 disabled ref: ; $(info $@:$(ref)) + +# disabled: .WARNINGS = +# disabled: ref +# !, +# '', "#MAKEFILE#:9: reference to undefined variable 'undef'\nenabled: +# ref: +# disabled: +# #MAKEFILE#:9: reference to undefined variable 'undef'\nenabled2: +# #MAKE#: 'all' is up to date."); + +1; -- cgit v1.2.1