Re: [BUG] undefined variable used in recipe before undefine directive

Martin Dorey <[email protected]> Wed, 10 Sep 2025 21:05:05 +0000
Newsgroups gmane.comp.gnu.make.bugs
Message-ID <SJ0PR08MB6704C8D9F3CD825776A7322FFA0EA@SJ0PR08MB6704.namprd08.prod.outlook.com>
  *
Am I missing anything?

Yes.  The recipe's text, which you can see with eg:

mad@shuttle:~/tmp/colomar-2025-09-10$ make -n -p 2>&1 | grep -A26 ^all:
all:
#  Implicit rule search has not been done.
...
# Load=8/32=25%, Rehash=0, Collisions=1/12=8%
#  recipe to execute (from 'Makefile', line 5):
       echo $(foo)

Mad@shuttle:~/tmp/colomar-2025-09-10$

... doesn't contain the value of foo but a reference to it.  Recipe definition is evaluated like recursively-expanded assignment (=), rather than simply-expanded assignment (:=).  Perhaps this is best documented by https://www.gnu.org/software/make/manual/html_node/Variables-in-Recipes.html, although perhaps https://www.gnu.org/software/make/manual/html_node/Recursive-Assignment.html gets more to the heart of the matter, with "This flavor of variable is the only sort supported by most other versions of make", which I might take to mean that anything that doesn't explicitly talk about this newfangled := assignment isn't using it.  You can see the... legacy of history in the way "The Two Flavors of Variables" at https://www.gnu.org/software/make/manual/html_node/Flavors.html has four subsections rather than the titular two, one of which talks about the really newfangled (POSIX Issue 8 only being standardized in 2024) :::= assignment.

________________________________
From: [email protected] on behalf of Alejandro Colomar
Sent: Wednesday, September 10, 2025 13:33
To: [email protected]
Subject: [BUG] undefined variable used in recipe before undefine directive

Hi,

I think this looks like a bug, unless I'm forgetting some details about
how variables are expanded within recipes.

        alx@debian:~/tmp/bug$ ls
        Makefile
        alx@debian:~/tmp/bug$ cat Makefile | nl -ba
             1   MAKEFLAGS += --warn-undefined-variables
             2
             3   foo := foo
             4
             5   all:; echo $(foo)
             6
             7   undefine foo
        alx@debian:~/tmp/bug$ make
        Makefile:5: warning: undefined variable 'foo'
        echo

As I understand it, the variable foo is expanded immediately in the
definition of the recipe, and make(1) shouldn't care if I undefine it
after the definition of the recipe, right?  make(1) should create the
recipe with the contents of the variable, and not with the variable
itself.

Am I missing anything?

I'm using Debian Sid:

        $ make --version | head -n1
        GNU Make 4.4.1



Have a lovely night!
Alex


--
<https://www.alejandro-colomar.es>
Use port 80 (that is, <...:80/>).