NetBSD Problem Report #60850
From kre@munnari.OZ.AU Mon Oct 5 05:36:58 2026
Return-Path: <kre@munnari.OZ.AU>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
client-signature RSA-PSS (2048 bits) client-digest SHA256)
(Client CN "mail.netbsd.org", Issuer "YR1" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id D46C11A923B
for <gnats-bugs@gnats.NetBSD.org>; Mon, 5 Oct 2026 05:36:58 +0000 (UTC)
Message-Id: <202610050508.69558SHM008610@jacaranda.noi.kre.to>
Date: Mon, 5 Oct 2026 12:08:28 +0700 (+07)
From: kre@munnari.OZ.AU
To: gnats-bugs@NetBSD.org
Subject: Make could do with a syntax for immediate var expansion
X-Send-Pr-Version: 3.95
X-From4GNATS: "kre@munnari.OZ.AU via gnats" <gnats-admin@NetBSD.org>
>Number: 60850
>Category: bin
>Synopsis: Make could do with a syntax for immediate var expansion
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Mon Oct 05 05:40:00 +0000 2026
>Last-Modified: Fri Oct 16 19:40:01 +0000 2026
>Originator: Robert Elz
>Release: NetBSD
>Organization:
>Environment:
Machine: everything
>Description:
There are times when Make variables are transitory, existing
just for a short period before vanishing. They can be expanded
while they exist, but not afterwards. This means that a
typical assignment like
CFLAGS= -D${Var}
doesn't work if Var is one of those transitory variables, as
it will not have a value when CFLAGS is later expanded.
This leads to nonsense like
XVar:=${Var}
CFLAGS= -D${XVar}
which works OK, if Var only ever has one value, so only one
"XVar" is needed to hold that value, it starts becoming
freakish when Var goes through many different values, and
all (or some subset) of them are needed.
Better would be to simply have a syntax which instructs
make to "expand this variable right now, whatever the context"
which (assuming here it might be $[...] - but I don't care what
the syntax is, $ wouldn't work as $< already has a meaning,
but ${=Var} or something like that might work (no idea, I don't
understand make).
Then
CFLAGS= -D$[Var]
would simply assign something like
CFLAGS= -DMake_Is_too_Complex
which is generally what is wanted anyway, it is very rare
to do an assignment like that, and expect the value of the
variable to change later, and actually want to use the changed
value.
>How-To-Repeat:
Try makeing a Makefile.inc that has something like
CPPFLAGS+= -I ${.PARSEDIR}
in it, and see if you can make that work when CPPFLAGS
ends up being used in one of the standard build rules
from the bsd.*.mk files.
>Fix:
Introduce sanity.
>Audit-Trail:
From: Valery Ushakov <uwe@stderr.spb.ru>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60850: Make could do with a syntax for immediate var
expansion
Date: Mon, 5 Oct 2026 14:07:10 +0300
A slighly less kludgy (but still kludgy) way to do that is to use the
fact that the for-loop variables are expanded immediately:
$ cat Makefile
VAR = private
.for VAR_VALUE in $(VAR)
a += "-D$(VAR_VALUE)"
.endfor
VAR = include
.for VAR_VALUE in $(VAR)
a += "-I/path/$(VAR_VALUE)"
.endfor
default:
@echo "VAR=$(VAR)"
@echo a=$(a)
$ make
VAR=include
a=-Dprivate -I/path/include
$
-uwe
From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60850: Make could do with a syntax for immediate var
expansion
Date: Mon, 5 Oct 2026 11:39:23 +0000 (UTC)
This do?:
```
CPPFLAGS = -I/usr/include -I/usr/X11R7/include
CPPFLAGS := ${CPPFLAGS} -I${.PARSEDIR}
# CPPFLAGS += -I${.PARSEDIR}
CPPFLAGS += -I/usr/local/include
.PHONY: all
all:
echo cc ${CPPFLAGS}
```
-RVP
From: Valery Ushakov <uwe@stderr.spb.ru>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60850: Make could do with a syntax for immediate var
expansion
Date: Mon, 5 Oct 2026 21:38:34 +0300
> ```
> CPPFLAGS = -I/usr/include -I/usr/X11R7/include
> CPPFLAGS := ${CPPFLAGS} -I${.PARSEDIR}
> # CPPFLAGS += -I${.PARSEDIR}
> CPPFLAGS += -I/usr/local/include
Consider the case where the first assignment to CPPFLAGS contains a
variable reference that you do _not_ want to expand immediately when
that := runs
-uwe
From: Rob Whitlock <rwhitlock22@gmail.com>
To: gnats-bugs@netbsd.org
Cc: gnats-admin@netbsd.org,
netbsd-bugs@netbsd.org,
"kre@munnari.oz.au" <kre@munnari.OZ.AU>
Subject: Re: bin/60850: Make could do with a syntax for immediate var
expansion
Date: Mon, 5 Oct 2026 21:27:14 -0400
> On Oct 5, 2026, at 2:45 PM, Valery Ushakov via gnats =
<gnats-admin@NetBSD.org> wrote:
>=20
> The following reply was made to PR bin/60850; it has been noted by =
GNATS.
>=20
> From: Valery Ushakov <uwe@stderr.spb.ru>
> To: gnats-bugs@netbsd.org
> Cc:=20
> Subject: Re: bin/60850: Make could do with a syntax for immediate var
> expansion
> Date: Mon, 5 Oct 2026 21:38:34 +0300
>=20
>> ```
>> CPPFLAGS =3D -I/usr/include -I/usr/X11R7/include
>> CPPFLAGS :=3D ${CPPFLAGS} -I${.PARSEDIR}
>> # CPPFLAGS +=3D -I${.PARSEDIR}
>> CPPFLAGS +=3D -I/usr/local/include
>=20
> Consider the case where the first assignment to CPPFLAGS contains a
> variable reference that you do _not_ want to expand immediately when
> that :=3D runs
>=20
> -uwe
thinkpad$ cat Makefile
DELAYED =3D wrong value
CPPFLAGS =3D -I/usr/include -I/usr/X11R7/include ${DELAYED}
MYPARSEDIR :=3D ${.PARSEDIR}
CPPFLAGS +=3D -I${MYPARSEDIR}
CPPFLAGS +=3D -I/usr/local/include
.include "subdir/more.mk"
.PHONY: all
all:
@echo cc ${CPPFLAGS}
thinkpad$ cat subdir/more.mk
DELAYED =3D right value
thinkpad$ make
cc -I/usr/include -I/usr/X11R7/include right value -I/home/rob/tmp_make =
-I/usr/include
thinkpad$=20=
From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60850: Make could do with a syntax for immediate var expansion
Date: Tue, 06 Oct 2026 10:28:32 +0700
Date: Mon, 5 Oct 2026 11:10:01 +0000 (UTC)
From: "Valery Ushakov via gnats" <gnats-admin@NetBSD.org>
Message-ID: <20261005111001.777461A923C@mollari.NetBSD.org>
| A slighly less kludgy (but still kludgy) way to do that is to use the
| fact that the for-loop variables are expanded immediately:
Ugh! I'm glad I didn't know that (I actually believed that for-loop
variables might be one of the types that could benefit from an "expand now"
syntax) or I might have been tempted. Truly horrible!
But that does suggest an alternative resolution to this .. variables like
.PARSEDIR .PARSEFILE (and all the other .name vars which make owns, which
tend to vary - as distinct from those whick a knobs, or simply (for the
session) constant values) could simply be made to ack like for loop
variables, and simply be expanded on reference, always.
That doesn't completely remove the uses for a syntax to get immediate
expansion, but it does deal with the practical cases I know about (there
could be others where a var is assigned to different values at different
places, even something as simple as one of the xxFLAGS which get += all over
the place, and where someone wants to capture the current state of
such a variable, perhaps into a var that will contain a debug message
to be output later, and which might already contain other var references
which are not to be expanded until later. So, some syntax to achieve
this might still be nice, but my immediate need would be solved if all
of these "make changes them as and whenever it needs to" variables would
simply be expanded whenever referenced on any variable assignment, not
just the := kind (they, and everything else, already are expanded on
reference in all other contexts I can think of).
As for a syntax, another possibility would be a new variable modifier
(like there are already hundreds, what's one more!)
I don't see :^ defined as a modifier, so perhaps something like
${var:^}
could mean "expand var right now" - any other modifiers that follow
(for simplicity, ^ would need to come first - I don't think there is
any meaningful conflict with any of the other "must come first" - and
any others could just come after this "modifier" which doesn't modify
anything except the time of expansion - and only then when used in
(other than :=) variable assignment statements - everywhere else it
would just be a no-op.
So far, I have at least seen no opposition to the general idea of
adding such a mechanism however. That's good.
kre
From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60850: Make could do with a syntax for immediate var
expansion
Date: Tue, 6 Oct 2026 07:35:09 +0000 (UTC)
On Mon, 5 Oct 2026, Valery Ushakov via gnats wrote:
> Consider the case where the first assignment to CPPFLAGS contains a
> variable reference that you do _not_ want to expand immediately when
> that := runs
>
Tsk...
```
CPPFLAGS = -I/usr/include
.if ${.PARSEDIR:_}
CPPFLAGS += -I$_
.endif
CPPFLAGS += -I/usr/local/include
.PHONY: all
all:
@echo cc ${CPPFLAGS}
```
I'd better stop before kre@ tells me to behave... :)
-RVP
From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60850: Make could do with a syntax for immediate var expansion
Date: Tue, 06 Oct 2026 15:46:59 +0700
Date: Tue, 6 Oct 2026 07:40:01 +0000 (UTC)
From: "RVP via gnats" <gnats-admin@NetBSD.org>
Message-ID: <20261006074001.ECE811A923C@mollari.NetBSD.org>
| CPPFLAGS = -I/usr/include
| .if ${.PARSEDIR:_}
| CPPFLAGS += -I$_
| .endif
| CPPFLAGS += -I/usr/local/include
That works, once, but if you do it again, $_ will be changedm
and all of the -I$_ will expand to the same thing when CPPFLAGS
is eventually expanded.
It is also still cumbersome to use (3 lines where just 1 should be
needed).
| I'd better stop before kre@ tells me to behave... :)
No problem with that, these various ways that almost work, but
don't really, are just more reasons to add something easy to
use which does work.
But I will tell you to send in the developer paperwork, so you could
work out a suitable real solution and implement & commit it yourself!
kre
From: Rob Whitlock <rwhitlock22@gmail.com>
To: gnats-bugs@netbsd.org
Cc: gnats-admin@netbsd.org,
netbsd-bugs@netbsd.org,
"kre@munnari.oz.au" <kre@munnari.OZ.AU>
Subject: Re: bin/60850: Make could do with a syntax for immediate var
expansion
Date: Tue, 6 Oct 2026 12:59:08 -0400
> On Oct 5, 2026, at 11:30 PM, Robert Elz via gnats =
<gnats-admin@NetBSD.org> wrote:
>=20
> The following reply was made to PR bin/60850; it has been noted by =
GNATS.
>=20
> From: Robert Elz <kre@munnari.OZ.AU>
> To: gnats-bugs@netbsd.org
> Cc:=20
> Subject: Re: bin/60850: Make could do with a syntax for immediate var =
expansion
> Date: Tue, 06 Oct 2026 10:28:32 +0700
>=20
> So far, I have at least seen no opposition to the general idea of
> adding such a mechanism however. That's good.
>=20
> kre
I would want to know whether my earlier example satisfies your need.
If it provides the needed functionality then I don't see how a new
variable modifier is needed.=
From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org, netbsd-bugs@netbsd.org
Cc:
Subject: Re: bin/60850: Make could do with a syntax for immediate var expansion
Date: Wed, 07 Oct 2026 05:36:43 +0700
Date: Tue, 6 Oct 2026 12:59:08 -0400
From: Rob Whitlock <rwhitlock22@gmail.com>
Message-ID: <5AECF203-D2A4-4A2E-9E8E-67117E1915BE@gmail.com>
| I would want to know whether my earlier example satisfies your need.
It sort of does, and it is approximately what I had done (before I submitted
the PR) to solve the build problem we were having. It just isn't good enough.
| If it provides the needed functionality then I don't see how a new
| variable modifier is needed.
New syntax I requested, whether that is a variable modifier, or some
other way (another possibility would be to add +:= as a new assignment
operator, which would expand its string like := does, and then append
the result to the named variable, just like += does - but without
needing the intermediate variable, to use on an := line, followed by
its use on the += line, as while at first glance those intermediate
variables seem to be used for just the two lines, they're not, once
created, its value needs to remain stable until the actual variable
we're assigning to gets used.
The problem with the actual example you used, where the intermediate
variable was "MYPARSEDIR" is exactly the same as the one in RVP's
example which used _ as the variable - those are so obvious, that
they would be used all the time.
The problem occurs in usage like
.include <subdir/Makefile.inc>
.include <arch/${ARCH}/Makefile.inc>
.if expression-to-test-some-option
.include <option-dir/Makefile.inc>
.endif
(sometimes with many .include lines).
Each Makefile.inc wants to (needs to)
CPPFLAGS+= -I ${.PARSEDIR}
to get the eventual cc command to search for .h files in the
relevant directory (particularly the middle one where there
will be architecture dependent include files for many different
architectures and the right set need to be found).
(There are likely to be more vars set in a similar way, SRCS to
list all the files that need compiling is also likely, but 1 or
a dozen, the same mechanism is needed for each ... they do all just
need one intermediate variable however, not one for each.)
Please ignore whatever you think about this actual example, and
how it would be better done like something else, that is not the
point here.
If your proposed method was used, just as you wrote it, in each
of those files, what we would end up with is
CPPFLAGS= ..... -I /whatever/option-dir -I /whatever/option-dir \
-I /whatever/option-dir ....
as by the time it is expanded, MYPARSEDIR would be whatever value was
assigned to it most recently, which in this case, assuming the expression
returned "true" would be the ${.PARSEDIR} value for the option-dir.
What I actually did, which was similar to your sugegstion, was to invent
a new, unlikely to be used, typically quite long, new variable name for
each instance (each Makefile.inc), so that (hopefully) nothing else anywhere
would be changing them. That's unreliable - relies more on luck than
anything else (though it turned out, that for now at least, I was lucky
enough to invent new var names that didn't conflict with anything else).
That is, "for now" - someone might just happen to pick one of the same
names to use, for a similar, or quite different, purpose, any time in
the future - these are just "junk" names, they aren't ever going to be
documented anywhere.
Hence the suggestion for a new mechanism, that doesn't require new
variables (or not any new long term variables) to be invented.
uwe@'s suggestion to use a dummy .for loop, and variable, which (I had
no idea) always gets expanded immediately when referenced would work,
but is just such a hack, and so incomprehensible, that there really
should be some better way.
Simply making ${.PARSEDIR} (and other make supplied variables like it,
which have only temporary values) expand immediately upon reference, just
like for variables apparently do, would solve the actual problem experienced
trivially - but a more general mechanism seems, to me, as if it would be
a better idea. What mechanism is for people who actually understand make
to determine which would be best -- that is certainly not me - hence the
"expression-to-test-some-option" above, as I didn't want to attempt to
write something real, and have this PR devolve into discussion of how that
expression should have been written, or what other way would be better,
as I have seen happen (not perhaps for this precise example) before.
kre
From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60850: Make could do with a syntax for immediate var
expansion
Date: Tue, 13 Oct 2026 08:33:19 +0000 (UTC)
On Tue, 6 Oct 2026, Robert Elz via gnats wrote:
> | CPPFLAGS = -I/usr/include
> | .if ${.PARSEDIR:_}
> | CPPFLAGS += -I$_
> | .endif
> | CPPFLAGS += -I/usr/local/include
>
> That works, once, but if you do it again, $_ will be changedm
> and all of the -I$_ will expand to the same thing when CPPFLAGS
> is eventually expanded.
>
You can add a varname to that `$_' to make it unique, but I didn't do that
because,
> It is also still cumbersome to use (3 lines where just 1 should be
> needed).
>
Precisely. And it would've been no better than what you've already done (only,
2 lines longer and more obscure besides).
-RVP
From: Rob Whitlock <rwhitlock22@gmail.com>
To: gnats-bugs@netbsd.org
Cc: gnats-admin@netbsd.org,
netbsd-bugs@netbsd.org,
"kre@munnari.oz.au" <kre@munnari.OZ.AU>
Subject: Re: bin/60850: Make could do with a syntax for immediate var
expansion
Date: Fri, 16 Oct 2026 15:35:15 -0400
> On Oct 13, 2026, at 4:35 AM, RVP via gnats <gnats-admin@NetBSD.org> =
wrote:
>=20
> The following reply was made to PR bin/60850; it has been noted by =
GNATS.
>=20
> From: RVP <rvp@SDF.ORG>
> To: gnats-bugs@netbsd.org
> Cc:=20
> Subject: Re: bin/60850: Make could do with a syntax for immediate var
> expansion
> Date: Tue, 13 Oct 2026 08:33:19 +0000 (UTC)
>=20
> On Tue, 6 Oct 2026, Robert Elz via gnats wrote:
>=20
>> It is also still cumbersome to use (3 lines where just 1 should be
>> needed).
>>=20
>=20
> Precisely. And it would've been no better than what you've already =
done (only,
> 2 lines longer and more obscure besides).
Yes, I suppose such a feature would cut down the boilerplate.
Consider my previous tentative objection retracted.=
(Contact us)
$NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.