Paul Smith c59cc4f932 [SV 64185] Clarify handling of directive lines starting with TAB
It's clear that this change causes too many problems to be made
without warning.  Revert the change disallowing conditional lines to
start with TAB.

Instead, generate warnings whenever a directive line begins with a
TAB character.  Make this change for all directives, not just
conditional directives: define, undefine, export, unexport, vpath,
load, include, etc.

* NEWS: Update the backward-compatibility warning.
* src/read.c (eval): Track whether the line starts with a TAB.
If so then whenever we recognize a directive, emit a warning.
Revert the previous change for this bug.
(parse_var_assignment): Accept a file location if the line begins
with TAB; show a warning if we discover a directive.
(conditional_line): Warn about lines starting with TAB.
* tests/scripts/...: Add tests to verify warnings for initial TAB.
2025-08-26 08:13:55 -04:00

344 lines
5.4 KiB
Perl

# -*-perl-*-
$description = "Test define/endef variable assignments.";
$details = "";
# old-style basic define/endef
run_make_test('
define multi
@echo hi
echo there
endef
all: ; $(multi)
',
'', "hi\necho there\nthere\n");
# Various new-style define/endef
run_make_test('
FOO = foo
define multi =
echo hi
@echo $(FOO)
endef # this is the end
define simple :=
@echo $(FOO)
endef
define posix ::=
@echo $(FOO)
endef
append = @echo a
define append +=
@echo b
endef
define cond ?= # this is a conditional
@echo first
endef
define cond ?=
@echo second
endef
FOO = there
all: ; $(multi)
#TAB#$(simple)
#TAB#$(posix)
#TAB#$(append)
#TAB#$(cond)
',
'', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n");
# Various new-style define/endef, with no spaces
run_make_test(q!
FOO = foo
define multi=
echo hi
@echo $(FOO)
endef # this is the end
define simple:=
@echo $(FOO)
endef
define posix::=
@echo $(FOO)
endef
define posixbsd:::=
@echo '$(FOO)$$bar'
endef
append = @echo a
define append+=
@echo b
endef
define cond?= # this is a conditional
@echo first
endef
define cond?=
@echo second
endef
FOO = there
all: ; $(multi)
#TAB#$(simple)
#TAB#$(posix)
#TAB#$(posixbsd)
#TAB#$(append)
#TAB#$(cond)
!,
'', "echo hi\nhi\nthere\nfoo\nfoo\nfoo\$bar\na\nb\nfirst\n");
# define in true section of conditional (containing conditional)
run_make_test('
FOO = foo
NAME = def
def =
ifdef BOGUS
define $(subst e,e,$(NAME)) =
ifeq (1,1)
FOO = bar
endif
endef
endif
$(eval $(def))
all: ; @echo $(FOO)
',
'BOGUS=1', "bar\n");
# define in false section of conditional (containing conditional)
run_make_test(undef, '', "foo\n");
# nested define (supported?)
run_make_test('
define outer
define inner
A = B
endef
endef
$(eval $(outer))
outer: ; @echo $(inner)
',
'', "A = B\n");
# NEGATIVE: Missing variable name
run_make_test('
NAME =
define $(NAME) =
ouch
endef
all: ; @echo ouch
',
'', "#MAKEFILE#:3: *** empty variable name. Stop.\n", 512);
# NEGATIVE: extra text after define
run_make_test('
NAME =
define NAME = $(NAME)
ouch
endef
all: ; @echo ok
',
'', "#MAKEFILE#:3: extraneous text after 'define' directive\nok\n");
# NEGATIVE: extra text after endef
run_make_test('
NAME =
define NAME =
ouch
endef $(NAME)
all: ; @echo ok
',
'', "#MAKEFILE#:5: extraneous text after 'endef' directive\nok\n");
# NEGATIVE: missing endef
run_make_test('
NAME =
all: ; @echo ok
define NAME =
ouch
endef$(NAME)
',
'', "#MAKEFILE#:4: *** missing 'endef', unterminated 'define'. Stop.\n", 512);
# -------------------------
# Make sure that prefix characters apply properly to define/endef values.
#
# There's a bit of oddness here if you try to use a variable to hold the
# prefix character for a define. Even though something like this:
#
# define foo
# echo bar
# endef
#
# all: ; $(V)$(foo)
#
# (where V=@) can be seen by the user to be obviously different than this:
#
# define foo
# $(V)echo bar
# endef
#
# all: ; $(foo)
#
# and the user thinks it should behave the same as when the "@" is literal
# instead of in a variable, that can't happen because by the time make
# expands the variables for the command line and sees it begins with a "@" it
# can't know anymore whether the prefix character came before the variable
# reference or was included in the first line of the variable reference.
run_make_test('
define FOO
$(V1)echo hello
$(V2)echo world
endef
all: ; @$(FOO)
', '', 'hello
world');
run_make_test(undef, 'V1=@ V2=@', 'hello
world');
run_make_test('
define FOO
$(V1)echo hello
$(V2)echo world
endef
all: ; $(FOO)
', 'V1=@', 'hello
echo world
world');
run_make_test(undef, 'V2=@', 'echo hello
hello
world');
run_make_test(undef, 'V1=@ V2=@', 'hello
world');
# Test the basics; a "@" internally to the variable applies to only one line.
# A "@" before the variable applies to the entire variable.
run_make_test('
define FOO
@echo hello
echo world
endef
define BAR
echo hello
echo world
endef
all: foo bar
foo: ; $(FOO)
bar: ; @$(BAR)
', '', 'hello
echo world
world
hello
world
');
# Ensure that define can be a target when not appearing in a variable
# definition context. See SV 59870
run_make_test(q!
define = define
$(define) : ;@echo $@
%:define
all: define foo
%.x : define
foo:;
!,
'', "define\n");
# Verify that define indented by TAB is warned about.
# This will be an error in future versions.
run_make_test(q!
#TAB#define foo
@echo foo
endef
all:;$(foo)
!,
'', "#MAKEFILE#:2: warning: directive lines cannot start with TAB\nfoo\n");
# The failure doesn't happen at define time for nested defines, it happens
# at eval time
run_make_test(q!
foo = echo foo
define bar
#TAB#define foo
#TAB# echo bar
#TAB#endef
endef
all:;@$(foo)
!,
'', "foo\n");
run_make_test(q!
foo = echo foo
define bar
#TAB#define foo
#TAB# echo bar
#TAB#endef
endef
$(eval $(bar))
all:;@echo foo
!,
'', "#MAKEFILE#:10: warning: directive lines cannot start with TAB\n#MAKEFILE#:10: *** missing 'endef', unterminated 'define'. Stop.\n",
512);
# endef indented by TAB is an error; this has always been true!
run_make_test(q!
define foo
@echo foo
#TAB#endef
all:;$(foo)
!,
'', "#MAKEFILE#:2: *** missing 'endef', unterminated 'define'. Stop.\n", 512);
1;