2023-11-29 10:58 AEDT

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0000566mercuryBugpublic2023-10-16 17:01
Reporterwangp 
Assigned Towangp 
PrioritynormalSeverityminorReproducibilityalways
StatusresolvedResolutionfixed 
Product Version 
Target VersionFixed in Version 
Summary0000566: undefined variable warnings with GNU Make 4.4.0.90
DescriptionSince GNU Make 4.4.0.90, we get warnings about undefined variables '*' and '@':

/tmp/mmake.RTEA5X:64: warning: undefined variable '*'
/tmp/mmake.RTEA5X:64: warning: undefined variable '@'
/tmp/mmake.RTEA5X:64: warning: undefined variable '@'

The problem first appears with GNU Make commit 15dfad96d77c9445d11be939a5042675e4ca8c65 "[SV 63439, SV 63452] Don't warn on undefined internal variables"
https://git.savannah.gnu.org/cgit/make.git/commit/?id=15dfad96d77c9445d11be939a5042675e4ca8c65

The code that ultimately triggers these warnings is in Mmake.vars.in, from lines 374 onwards, that says:

# `TARGET_<prog>FLAGS' is used to pass different flags to <prog> for
# different targets. By setting MCFLAGS-foo, for example, you can add
# extra values to TARGET_MCFLAGS that will used only for compiling foo.m.
#
# For each program <prog>, `TARGET_<prog>FLAGS' expands to
# `$(<prog>FLAGS-$@)' and/or `$(<prog>FLAGS-$*)'.
# $@ and $* are the builtin variables that expand to the
# current target and (for pattern rules) the base name of the current target,
# respectively. So $* is used for flags variables used by pattern rules,
# whereas $@ is used for flags variables used by hard-coded rules,
# including the ones in the generated .dep files.
#
# The code below uses some tricky GNU Make hacks to avoid expanding
# <prog>FLAGS-$* and <prog>FLAGS-$@ if these vars are not defined,
# so that we can avoid spurious warnings if the warning about
# undefined variables is enabled.

TagsNo tags attached.
Attached Files

-Relationships
+Relationships

-Notes

~0001219

zs (developer)

Are you saying that the variable references that trigger bug
are the ones in the *comment* you quoted? That would seem to be
a serious issue in gnu make. Has this been reported to its maintainers?

For us, there is an obvious workaround: put something between
the $ and the @ or *, with a comment saying *why* that something is there.

~0001220

wangp (developer)

Sorry, not in the comment, but in the code that the comment is describing:

TARGET_GRADEFLAGS = \
  $(maybe-base-GRADEFLAGS-$(findstring undefined,\
        $(origin GRADEFLAGS-$(patsubst %_init,%,$*)))) \
  $(maybe-target-GRADEFLAGS-$(findstring undefined,\
          $(origin GRADEFLAGS-$(patsubst $(cs_subdir)%_init.c,%,$@))))
maybe-base-GRADEFLAGS- = $(GRADEFLAGS-$(patsubst %_init,%,$*))
maybe-base-GRADEFLAGS-undefined =
maybe-target-GRADEFLAGS- = $(GRADEFLAGS-$(patsubst $(cs_subdir)%_init.c,%,$@))
maybe-target-GRADEFLAGS-undefined =

etc.


It could well be a bug in GNU Make. Before reporting I'd like to understand the issue properly, and construct a smaller test case.

~0001221

zs (developer)

If you get the error for the occurrences of $* and $@ in those
variable definitions, then those occurrences are being expanded
at variable-definition-time. Both $* and $@ are defined with respect
to a make rule, and there is no rule here. Their evaluation should
be delayed until the variable being defined is actually used in a rule.
If it is evaluated at any time before then, then $* and $@ are unusable
in variable definitions, which I would classify as a serious regression.

~0001222

wangp (developer)

The warnings about $@ and $* being undefined are occurring when VPATH is being evaluated, outside of any rule.

The chain of references goes
VPATH -> MMAKE_VPATH -> UNIX_MERCURY_EXTRA_INIT_DIRS -> MERCURY_EXTRA_INIT_DIRS -> EXTRA_INIT_DIRS -> GRADESTRING -> ALL_GRADEFLAGS -> USUAL_GRADEFLAGS -> TARGET_GRADEFLAGS -> $* and $@

~0001223

zs (developer)

In what context is VPATH being evaluated? The condition of
of a ifeq/ifneq line? The search for a file? Because in both cases,
I can see why the new warning from make would be justified.

I can understand why VPATH depends on the grade; I don't see
why it should depend on a grade modified by *module-specific* flags,
as opposed to *program-specific* flags.

~0001224

wangp (developer)

VPATH is evaluated once before considering any target, and
this value of VPATH is used to find prerequisites of all targets (from what I gather).

Here is a makefile for demonstration:

    VPATH = srcs.$@ \
        $(shell echo Evaluating VPATH now for target [$@] >&2 )

    # Put foo.c in srcs.foo
    foo: foo.c
        @echo VPATH in recipe is $(VPATH)

    # Put bar.c in current dir
    bar: bar.c
        @echo VPATH in recipe is $(VPATH)

This is the log for `make --warn-undefined-variables -d -r foo`.
foo.c cannot be found because VPATH is set to "srcs.", and *not* "srcs.foo".

    GNU Make 4.4.1
    Built for x86_64-unknown-linux-gnu
    Copyright (C) 1988-2023 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    Reading makefiles...
    Reading makefile 'Makefile'...
    Makefile:1: warning: undefined variable '@'
    Makefile:1: warning: undefined variable '@'
    Evaluating VPATH now for target []
    Updating makefiles....
     Considering target file 'Makefile'.
      Looking for an implicit rule for 'Makefile'.
      No implicit rule found for 'Makefile'.
     Finished prerequisites of target file 'Makefile'.
     No need to remake target 'Makefile'.
    Updating goal targets....
    Considering target file 'foo'.
     Considering target file 'foo.c'.
      File 'foo.c' does not exist.
      Looking for an implicit rule for 'foo.c'.
      No implicit rule found for 'foo.c'.
     Finished prerequisites of target file 'foo.c'.
     Must remake target 'foo.c'.
    make: *** No rule to make target 'foo.c', needed by 'foo'. Stop.


This is the log for `make --warn-undefined-variables -d -r bar`.
bar.c exists in the current directory so it is found.
VPATH is evaluated again only when executing the recipe, now with $@ set to the target.

    GNU Make 4.4.1
    Built for x86_64-unknown-linux-gnu
    Copyright (C) 1988-2023 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    Reading makefiles...
    Reading makefile 'Makefile'...
    Makefile:1: warning: undefined variable '@'
    Makefile:1: warning: undefined variable '@'
    Evaluating VPATH now for target []
    Updating makefiles....
     Considering target file 'Makefile'.
      Looking for an implicit rule for 'Makefile'.
      No implicit rule found for 'Makefile'.
     Finished prerequisites of target file 'Makefile'.
     No need to remake target 'Makefile'.
    Updating goal targets....
    Considering target file 'bar'.
     File 'bar' does not exist.
     Considering target file 'bar.c'.
      Looking for an implicit rule for 'bar.c'.
      No implicit rule found for 'bar.c'.
     Finished prerequisites of target file 'bar.c'.
     No need to remake target 'bar.c'.
    Finished prerequisites of target file 'bar'.
    Must remake target 'bar'.
    Evaluating VPATH now for target [bar]
    Makefile:10: update target 'bar' due to: target does not exist
    echo VPATH in recipe is srcs.bar
    Putting child 0x557e7dcb1010 (bar) PID 18703 on the chain.
    Live child 0x557e7dcb1010 (bar) PID 18703
    VPATH in recipe is srcs.bar
    Reaping winning child 0x557e7dcb1010 PID 18703
    Removing child 0x557e7dcb1010 PID 18703 from chain.
    Successfully remade target file 'bar'.
    Directory srcs. cache invalidated (count 2 != command 4)


So what mmake tries to do with VPATH (i.e. trying to take into account target-specific flags to change where to look for prerequisites) probably never actually worked.

~0001225

wangp (developer)

Fix committed 2023-10-16
+Notes

-Issue History
Date Modified Username Field Change
2023-10-12 12:40 wangp New Issue
2023-10-12 12:43 wangp Summary undefined variable warnings with GNU Make 4.4 => undefined variable warnings with GNU Make 4.4.0.90
2023-10-12 12:55 zs Note Added: 0001219
2023-10-12 13:09 wangp Note Added: 0001220
2023-10-12 13:26 zs Note Added: 0001221
2023-10-12 15:46 wangp Note Added: 0001222
2023-10-12 16:02 zs Note Added: 0001223
2023-10-12 17:46 wangp Note Added: 0001224
2023-10-16 17:01 wangp Assigned To => wangp
2023-10-16 17:01 wangp Status new => resolved
2023-10-16 17:01 wangp Resolution open => fixed
2023-10-16 17:01 wangp Note Added: 0001225
+Issue History