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.=

NetBSD Home
NetBSD PR Database Search

(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.