Mercury Bugs - mercury
View Issue Details
0000566mercuryBugpublic2023-10-12 12:402023-10-16 17:01
Reporterwangp 
Assigned Towangp 
PrioritynormalSeverityminorReproducibilityalways
StatusresolvedResolutionfixed 
PlatformOSOS Version
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

Notes
(0001219)
zs   
2023-10-12 12:55   
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   
2023-10-12 13:09   
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   
2023-10-12 13:26   
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   
2023-10-12 15:46   
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   
2023-10-12 16:02   
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   
2023-10-12 17:46   
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   
2023-10-16 17:01   
Fix committed 2023-10-16

Issue History
2023-10-12 12:40wangpNew Issue
2023-10-12 12:43wangpSummaryundefined variable warnings with GNU Make 4.4 => undefined variable warnings with GNU Make 4.4.0.90
2023-10-12 12:55zsNote Added: 0001219
2023-10-12 13:09wangpNote Added: 0001220
2023-10-12 13:26zsNote Added: 0001221
2023-10-12 15:46wangpNote Added: 0001222
2023-10-12 16:02zsNote Added: 0001223
2023-10-12 17:46wangpNote Added: 0001224
2023-10-16 17:01wangpAssigned To => wangp
2023-10-16 17:01wangpStatusnew => resolved
2023-10-16 17:01wangpResolutionopen => fixed
2023-10-16 17:01wangpNote Added: 0001225