Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000330 [1003.1(2008)/Issue 7] Shell and Utilities Objection Enhancement Request 2010-10-11 21:45 2024-06-11 08:53
Reporter dwheeler View Status public  
Assigned To ajosey
Priority normal Resolution Accepted As Marked  
Status Closed  
Name David A. Wheeler
Organization
User Reference
Section make
Page Number 2908-2929
Line Number 95549-95822
Interp Status ---
Final Accepted Text see Note: 0001079
Summary 0000330: In make, add support for assignments "::=", "+=", and "?=".
Description The widely-supported additional assignment operators ":=", "+=", and "?=" should be added to the standard's specification for make, as they greatly speed up and simplify larger systems that use make. Below are the arguments for each.

Traditional make macros (defined with "=") cause exponential growth in execution time, inhibiting scalability as systems get bigger and more complex. That's because instead of being expanded when they are defined, they are expanded on use. A widely-used alternative is ":=", which creates an 'immediate-expansion' macro (which are expanded immediately) instead of a traditional 'delayed-expansion' macro.
The article "Recursive Make Considered Harmful" by Peter Miller
(http://miller.emu.id.au/pmiller/books/rmch/ [^] and
http://aegis.sourceforge.net/auug97.pdf) [^] notes this as a key problem when creating makefiles,
and strongly recommends using := instead.
Similarly, the guidelines "How-to write a makefile" specifically
recommend using := and not = because of efficiency issues, even for portable makefiles
(http://sites.google.com/site/michaelsafyan/coding/resources/how-to-guides/how-to-write-a-makefile). [^]

Immediately-expanded macros are not only more efficient, they also tend to be easier for developers to use. Traditional macros are very different from "normal" variables in other languages, and thus traditional macros are also a trap for the unwary. Since := style macros work like traditional variables, using them eliminates a subtle source of errors.

The "+=" (append) and "?=" (set if not already set) simplify setting macro variables. These make it simple to perform relatively common operations. These are especially helpful in larger systems with multiple makefiles that are combined together into a single large run of 'make'.

The ":=", "+=", and "?=" operators already have wide support:
* GNU make: http://www.gnu.org/software/autoconf/manual/make/index.html [^]
* FreeBSD make: http://www.freebsd.org/cgi/man.cgi?query=make&sektion=1 [^]
* OpenBSD make: http://www.openbsd.org/cgi-bin/man.cgi?query=make [^]
* Solaris make: http://developers.sun.com/solaris/articles/make_utility.html [^]
* MKS make supports := and += (though not ?=) http://www.mkssoftware.com/docs/man1/make.1.asp [^]
There are probably others, but that should be enough to make the point. There's some common code heritage, of course, but my point is that it's widely available, and thus should be in the standard.

These additions are relatively simple to implement, for the rare implementations that don't already have them.
Desired Action Add support for the assignments ":=" (immediate expansion), "+=" (append to macro), and "?=" (assign only if unassigned). Also, at the command line, add support for ":=" in addition to "=".

The following is some suggested text; feel free to modify it.

Replaces lines 95781-95786 (after "Macros") with:

"
A macro may be one of two flavors, "delayed-expansion" or "immediately-expanded".

The following form defines a delayed-expansion macro (replacing any previous definition of macro named by string1):
  string1 = [string2]
The following form defines an immediately-expanded macro (replacing any previous definition of macro named by string1):
  string1 := [string2]
The following form defines a delayed-expansion macro but only if the macro named string1 is not already defined:
  string ?= [string2]

The macro named string1 is defined as having the value of string2, where string2 is defined as all
characters, if any, after the <equals-sign>, up to a comment character (’#’) or an unescaped
<newline>. Any <blank> characters immediately after the <equals-sign>, or immediately before the <equals-sign>,
<colon>, or <question> respectively, shall be ignored.

The following form (the "append" form) modifies a macro by appending additional text to it:
  string1 += [string2]

After the append form:
* If the macro does not exist, this form is exactly equivalent to "string1 = string2".
* If the macro exists and is an immediately-expanded macro, it appends a space and the
  evaluation of string2 to the value currently assigned to string1.
* If the macro exists and is a delayed-expansion macro, it is equivalent to modifying the previous
  definition of the macro by appending a space and the unevaluated string2.
In all cases the value of string2 is defined as al characters, if any,
after the <equals-sign>, up to a comment character (’#’) or an unescaped
<newline>. Any <blank> characters immediately after the <equals-sign> or immediately before the <plus>
shall be ignored.

"

At line 95797, first insert:
"* Immediately-expanded macros shall be evaluated immediately when they are defined,
and this value is used as the replacement until the immediately-expanded macro is redefined."
And then change "Macros after..." to "Delayed-expansion macros...".

On line 96103, Change:
"Macros used within other macros are evaluated when the new macro is used rather than when
the new macro is defined. Therefore:"
to:
"Delayed-expansion macros are evaluated when they are used rather than when they are defined. Therefore:"

To permit ":=" on the command line:

After line 95554, add:
 macro:=value Macro definitions, as defined in Macros.
On line 95555, change "target_name and macro=value"
to "target_name, macro=value, and macro:=value"

Tags issue8
Attached Files

- Relationships
related to 0000337Closedajosey Add standard support for "!=" (macro shell assignment) in make 

-  Notes
(0000567)
dwheeler (reporter)
2010-10-11 22:55

For "+=" I proposed that it be the same as appending a <space>, but on reflection, I think it should be appending a <tab> (or <newline>) instead. That might be more future-proof in handling spaces-in-filenames.
(0000577)
dwheeler (reporter)
2010-10-14 18:39

Here is a revised proposal, creating a compromise position that I hope will be satisfactory.

First, the problem. Discussion on the mailing list in October 2010 revealed that GNU make and BSD makes have subtly different semantics for "V := S". As I understand it:
* In GNU make, evaluation of S happens exactly once, when V is set; afterwards, $(V) simply returns the set value. I'll call this semantic "single evaluation references", because it means that immediately-expanded macros are only expanded once.
* In at least some BSD makes, S is evaluated when V is set. However, $(V) then RE-EVALUATES V. I'll call this semantic "re-evaluate references", because in this semantic variable references like $V are always re-evaluated, even if they were evaluated before by an immediately-evaluated macro definition.

In practice, this difference in semantics typically makes no difference; I suspect many people aren't even aware that there IS a difference. Unless the final value after its first evaluation has an unescaped '$', there is no difference. In practice, many makefiles simply don't produce an unescaped $ in these contexts, and it's fairly easy to write makefiles that do the same thing with either semantic.

My proposed revised solution is to allow either the BSD or the GNU behavior. With this change, many existing "make"s become compliant with this proposal, without change. The fact that the spec clearly states that this variance exists is valuable, too... it's useful to KNOW that this can vary!! The following is summarized from the various BSD make man pages; if there are errors, PLEASE let me know.

DESIRED ACTION, REVISED:

Add support for the assignments ":=" (immediate expansion), "+=" (append to macro), and "?=" (assign only if unassigned). Also, at the command line, add support for ":=" in addition to "=".

The following is some suggested text; feel free to modify it.

Replace lines 95781-95786 (after "Macros") with:

"

A simple macro definition is in the form:
  string1 = [string2]
An immediately-evaluated macro definition is in the form:
  string1 := [string2]
A conditional-assignment macro definition is in the form:
  string1 ?= [string2]
An append macro definition is in the form:
  string1 += [string2]

In all of the macro definition cases above,
string2 is defined as all characters, if any, after the <equals-sign>, up to a comment character (<#>) or an unescaped <newline>. Any <blank> characters immediately after the <equals-sign>, or before the <equals-sign>, <colon>, <question>, or <plus> respectively, shall be ignored.

An implementations must implement either "single evaluation references" or "re-evaluate references". In an implementation with "single evaluation references", a macro may be one of two flavors, "recursively-expanded" or "simply-expanded".

After a simple macro definition,
the macro named string1 is defined as having the value of string2
(without evaluating string2).
In an implementation with single evaluation references, the macro named
string1 becomes recursively-expanded once the definition ends.

After an immediately-evaluated macro definition,
the macro named string1 is defined as having the value of string2
(after having evaluated string2).
In an implementation with single evaluation references, the macro named
string1 becomes simply-expanded once the definition ends.

After a conditional-assignment macro definition,
if the macro named string1 is not already defined, then
the macro named string1 is defined as having the value of string2
(without evaluating string2), and the macro named string1 becomes
recursively-expanded if the implementation has
single evaluation references.
If the macro named string1 is already defined, no change in definition occurs.

After an append macro definition,
if the macro does not exist, this form is exactly equivalent to "string1 = string2". Otherwise, if the macro is already defined, then
a <tab> or <space> character (which one is unspecified), followed by string2, is appended to its current value.
If the implementation uses single evaluation references and the macro is simply expanded, then string2 is evaluated before it is appended; otherwise, string2 is not evaluated before it is appended.
"

At line 95797, first insert:
"* Macros after := in an immediately-evaluated macro definition shall be evaluated immediately when they are defined."
* Macros after += in an append macro definition shall be evaluated if the implementation uses single evaluation references, the macro being assigned already exists, and the macro being assigned is a simply-expanded macro."
And then change "Macros after..." to "Otherwise, macros after...".

On line 96103, Change:
"Macros used within other macros are evaluated when the new macro is used rather than when the new macro is defined. Therefore:"
to:
"Delayed-expansion macros are evaluated when they are used rather than when they are defined. Therefore:"

To permit ":=" on the command line, after line 95554, add:
  macro:=value Macro definitions, as defined in Macros.
and on line 95555, change "target_name and macro=value"
to "target_name, macro=value, and macro:=value"
(0001003)
joerg (reporter)
2011-11-10 13:44

Please note that the proposal for ":=" is in conflict with SunPro make since 1986.

SunPro Make uses ":=" for conditional macro assignement and this is heavily used
when compiling OpenSolaris.

So please look for a different operator definition.
(0001009)
ajosey (manager)
2011-11-12 06:10

It was noted at the 10 Nov 2011 teleconference that bugnotes 577 and 1003 make it clear that standardizing := will break existing practices. It was agreed that we are in favor of enhancing make and therefore a solution will require a new syntax to be proposed.

Action: Andrew send a request for proposal to all Austin Group participants.
(0001014)
dwheeler (reporter)
2011-11-15 19:42

Comment #1009 says that the spelling for immediate evaluation must be something other than ":=", because SunPro has a completely different meaning for it, and the *BSD makes and GNU make have subtly different semantics.

Okay, how about "::=" for immediate evaluation? Would that work? Anyone have another preferred syntax?

A follow-up question is, what should be the exact semantics for immediate evaluation? The options are (1) not re-evaluate each time (like GNU make), (2) re-evaluate each time (like the *BSD makes), or (3) allow either behavior. I propose option #1; it seems to me that once a variable is evaluated, it is rare that you would want it evaluated again (slightly improving performance), and these variables behave more like variables in other languages (making them less error-prone due to familiarity). Also, since this proposal uses a different spelling (instead of ":=" which has 2 different semantics in use), we can be more specific about the semantics. This would cause some changes to some "makes" (now flavor information must be stored on each variable), but the changes should be relatively minimal.

So here is a revised proposal, based on the comments above:

Add support for the assignments "::=" (immediate expansion), "+=" (append to macro), and "?=" (assign only if unassigned). Also, at the command line, add support for "::=" in addition to "=".

The following is some suggested text; feel free to modify it.

Replaces lines 95781-95786 (after "Macros") with:

"
A macro may be one of two flavors, "delayed-expansion" or "immediately-expanded".

The following form defines a delayed-expansion macro (replacing any previous definition of macro named by string1):
  string1 = [string2]
The following form defines an immediately-expanded macro (replacing any previous definition of macro named by string1):
  string1 ::= [string2]
The following form defines a delayed-expansion macro but only if the macro named string1 is not already defined:
  string ?= [string2]

The macro named string1 is defined as having the value of string2, where string2 is defined as all
characters, if any, after the <equals-sign>, up to a comment character (’#’) or an unescaped
<newline>. Any <blank> characters immediately after the <equals-sign>, or immediately before the <equals-sign>,
<colon>, or <question> respectively, shall be ignored.

The following form (the "append" form) modifies a macro by appending additional text to it:
  string1 += [string2]

After the append form:
* If the macro does not exist, this form is exactly equivalent to "string1 = string2".
* If the macro exists and is an immediately-expanded macro, it appends a tab character and the evaluation of string2 to the value currently assigned to string1.
* If the macro exists and is a delayed-expansion macro, it is equivalent to modifying the previous definition of the macro by appending a tab character and the unevaluated string2.
In all cases the value of string2 is defined as all characters, if any,
after the <equals-sign>, up to a comment character (’#’) or an unescaped
<newline>. Any <blank> characters immediately after the <equals-sign> or immediately before the <plus>
shall be ignored.

"

At line 95797, first insert:
"* Immediately-expanded macros shall be evaluated immediately when they are defined,
and this value is used as the replacement until the immediately-expanded macro is redefined."
And then change "Macros after..." to "Delayed-expansion macros...".

On line 96103, Change:
"Macros used within other macros are evaluated when the new macro is used rather than when
the new macro is defined. Therefore:"
to:
"Delayed-expansion macros are evaluated when they are used rather than when they are defined. Therefore:"

To permit "::=" on the command line:

After line 95554, add:
 macro::=value Macro definitions, as defined in Macros.
On line 95555, change "target_name and macro=value"
to "target_name, macro=value, and macro::=value"
(0001015)
brkorb (reporter)
2011-11-15 21:28

The GNU syntax has been implemented with the GNU semantics on enough systems that I don't think that changing the token would be wise (or accepted). The code to implement alternate syntax isn't that hard. Adding code to decide if replaced text should be re-evaluated or not is a little bit trickier. Once that is in place, then adding options:
  -W do-it-the-GNU-way
  -W do-it-the-BSD-way
(renamed to something else) ought to be trivial.
(0001016)
dwheeler (reporter)
2011-11-15 23:03

Regarding comment #1015:

A clarification. Adding "::=" as proposed above would NOT require GNU make or anyone else to REMOVE support for ":=". The proposed syntax "::=" is just a standardized way to access the functionality that GNU make currently spells as ":=". GNU make could trivially implement "::=" - just implement it as a synonym for ":=". GNU make, and makefiles that assume it, could continue to use ":=" to their heart's content. The *BSD makes and SunPro Make would have a little more work to implement "::=", but not much; it wouldn't take long to add this. More importantly, existing makefiles that use := (with their different semantics) would all continue to work on their respective implementations. The reason I propose "::=" is an attempt to gain consensus, by not *requiring* people to change existing makefiles.

If this standards body agrees with comment #1015 that using ":=" would be better, just change all the instances of "::=" to ":=" in the proposal. That would do it!

It certainly *WOULD* be possible to implement a flag to implement the various semantic differences, e.g.:
-W do-it-the-GNU-way
-W do-it-the-BSD-way
-W do-it-the-Sunpro-way (if people want that in the standard)
(with whatever syntax). In that case, I'd propose that the "GNU way" be the default. It's perhaps not what you'd do if you were starting from a clean slate, but it's not completely insane. In particular, this would make it very easy for different existing users (and their makefiles) to move to an updated standard make. If this is the best way to get consensus on getting "make" more capable, then I'm all for it!

More generally, I believe that the make, as currently standardized, is underpowered for many of today's purposes. The result: people routinely use non-standard extensions. We can do better; we just need to find a way to gain consensus to add those capabilities.
(0001017)
dwheeler (reporter)
2011-11-15 23:07

BTW, I intentionally stated that append adds a "tab". If "space or tab" would get more consensus, that's fine. I realize that existing implementations tend to use space; I'm just hoping to head off some of the many problems with filenames that include embedded spaces.
(0001018)
eblake (manager)
2011-11-15 23:42

Regarding Note: 0001015:

POSIX explicitly reserves -W for the implementation, and therefore we cannot standardize any option named '-W do-it-the-GNU-way' or similar (although implementations like GNU make could certainly use that as a way of providing alternate semantics and exposing extensions not covered by POSIX).

And I agree with the counterargument in Note: 0001016 - adding the standardization of '::=' does _not_ invalidate existing implementations that provide ':=' as an extension - they can (and should!) continue to provide ':=' as an extension, and non-portable makefiles that are already relying on the implementation specifics of their use of ':=' will continue to work even when that implementation adds standardized behavior of '::='. It is only _new_ makefiles, written specifically to take advantage of new POSIX syntax, that would be forced to use '::=', in order to be portable to more make implementations (that is, all make implementations that follow through with the new standardization efforts). In other words, the whole point of this exercise is to standardize something that won't break existing scripts; either existing scripts are POSIX-compliant (and didn't use := in the first place), or they are tied to a specific implementation (in which case that implementation will continue to provide the extensions they were relying on). The reason the Austin Group is favoring a new syntax (be it '::=', '^=', or some other spelling), rather than standardizing ':=', is because there are existing implementations that differ in ':=', and forcing those implementations to change would break existing users of those implementation extensions.

Regarding Note: 0001017:

I would favor 'space or tab' when appending with '+='. Use of a space in a filename is already non-portable, per the POSIX definitions of portable filename character set, therefore, the only way to portably use make is on names that are already portable (actually, see 0000373 for the one case where it is not clear whether portable filenames can be portably used as make targets: if the name includes a dash). Any use of non-portable names in a makefile, including on file names with spaces, is already in the realms of vendor extension, so I would favor that we allow space or tab, rather than hard-coding things to tab (make is already hard enough with it's insistence on the significance between which type of whitespace you use, that we don't need to make it harder by adding yet more hard-coded use of tab).
(0001019)
Love4Boobies (reporter)
2011-11-16 01:01
edited on: 2011-11-16 02:06

Remember, since := isn't (yet) defined by POSIX, it is an extension. POSIX-compliant makefiles need to specify the .POSIX target and build systems which already do that cannot use := anyway. Long story short, it doesn't really break things.

(0001024)
joerg (reporter)
2011-11-17 10:46

Currently makefiles that make use of := are not portable and my smake for this reason warns in case := is seen in a makefile.

When GNU make in 1988 introduced := with a different semantics than the semantics introduced by SunPro make in 1986, this created an avoidable clash.

Using -W is not an option as it is in conflict with more important rules.

::= is the solution I had in mind when first thinking about the problem.
(0001073)
dwheeler (reporter)
2011-12-05 19:00

Excellent, it *looks* to me like there is a rough consensus on this issue. As always, though, the Austin group makes the final determination of that.

So if there's some unspoken issue, please speak up now and say what's wrong with this proposal! I'm happy to try to fix things, but I need to know that something is broken. Below are some comments and a slightly-refined proposal.

By the way, I don't strongly care how to *spell* the immediate assignment operator, as long as there is a *standard* way to do it. I suggested "::=" primarily because this is *already* sometimes used to define terms, e.g., in many Backus-Naur Form representations. Since it's already used in a similar way, I think "::=" is a little more readable. The term "^=" would be perfectly plausible, and its being only two characters is a slight advantage. However, "^=" seems much less clear; the most common use I know of "^=" is for bitwise XOR assignment, which is misleadingly different.

Could someone change the summary so that ":=" becomes "::="?

Here some deltas from the proposal in comment #1014:
* Comment #1018 recommends 'space or tab' when appending with '+='. I had suggested in comment #1017 that I'd be happy to do that to gain consensus, so let's do that to gain that consensus.
* Minor bug: In the last proposal, the delayed-expansion macro refers to "string1" but the pattern says "string" instead of string1. The revised proposal (below) fixes it.
* I've tweaked the wording so that it's hopefully more precise. E.G., more "shalls", and clearly noting that it is the VALUE of a macro being changed in various cases (not the name of the macro itself). No change in meaning was intended.

So here is a revised proposal; it's just comment #1014, with the minor changes noted above:

==========================


Replaces lines 95781-95786 (after "Macros") with:

"
A macro may be one of two flavors, "delayed-expansion" or "immediately-expanded".

The following form defines a delayed-expansion macro (replacing any previous definition of the macro named by string1):
  string1 = [string2]
The following form defines an immediately-expanded macro (replacing any previous definition of the macro named by string1):
  string1 ::= [string2]
The following form defines a delayed-expansion macro, but only if the macro named by string1 is not already defined:
  string1 ?= [string2]

The macro named by string1 is defined as having the value of string2, where string2 is defined as all characters, if any, after the <equals-sign>, up to a comment character (’#’) or an unescaped <newline>. Any <blank> characters immediately after the <equals-sign>, or immediately before the <equals-sign>, <colon>, or <question> respectively, shall be ignored.

The following form (the "append" form) appends additional text to the value of a macro:
  string1 += [string2]

After the append form:
* If the macro named by string1 does not exist, this form is exactly equivalent to "string1 = string2".
* If the macro named by string1 exists and is an immediately-expanded macro, it appends a <space> or <tab> character and then the evaluation of string2 to the value currently assigned to the macro named by string1.
* If the macro named by string1 exists and is a delayed-expansion macro, it is equivalent to modifying the previous value of the macro named by string1, by appending a <space> or <tab> character and then the unevaluated string2.
In all cases the value of string2 is defined as all characters, if any,
after the <equals-sign>, up to a comment character (’#’) or an unescaped
<newline>. Any <blank> characters immediately after the <equals-sign> or immediately before the <plus> shall be ignored.
"

At line 95797, first insert:
"* Immediately-expanded macros shall be evaluated immediately when they are defined, and this value shall be used as the replacement until the immediately-expanded macro is redefined."
And then change "Macros after..." to "Delayed-expansion macros...".

On line 96103, Change:
"Macros used within other macros shall be evaluated when the new macro is used rather than when the new macro is defined. Therefore:"
to:
"Delayed-expansion macros shall be evaluated when they are used rather than when they are defined. Therefore:"

To permit "::=" on the command line, after line 95554, add:
 macro::=value Macro definitions, as defined in Macros.
and on line 95555, change "target_name and macro=value"
to "target_name, macro=value, and macro::=value"
(0001075)
eblake (manager)
2011-12-06 16:40

Discussed on the 6 Dec 2011 call. There is consensus on accepting this bug, using Note: 0001073 as a template, but with some changes:
 "immediately-expanded" to "immediate-expansion"
 Add text to RATIONALE explaining choice of '::=' without existing practice
(0001079)
eblake (manager)
2011-12-06 21:49
edited on: 2011-12-15 16:27

At line 95484 (SYNOPSIS), change "[macro=value...]" to
"[macro[::]=value...]".

At line 95554-95556 (OPERANDS), change:
"macro=value Macro definitions, as defined in Macros (on page 2914).

If the target_name and macro=value operands are intermixed on the make
utility command line, the results are unspecified."

to:
"macro=value
macro::=value
        Delayed and immediate expansion macro definitions, as defined
in Macros (on page 2914).

Delayed and immediate expansion macro definitions can be intermixed, and
shall be processed in the order they appear. If any macro definition
appears after a target_name operand on the make utility command line,
the results are unspecified."

At line 95781-95786 (EXTENDED DESCRIPTION, after "Macros"), replace:
"Macro definitions are in the form:
  string1 = [string2]
The macro named string1 is defined as having the value of string2, where
string2 is defined as all characters, if any, after the <equals-sign>,
up to a comment character (’#’) or an unescaped <newline>. Any <blank>
characters immediately before or after the <equals-sign> shall be
ignored."

with:
"A macro can be one of two flavors, "delayed-expansion" or
"immediate-expansion".

The following form defines a delayed-expansion macro (replacing any
previous definition of the macro named by string1):
  string1 = [string2]
The following form defines an immediate-expansion macro (replacing any
previous definition of the macro named by string1):
  string1 ::= [string2]
The following form defines a delayed-expansion macro, but only if the
macro named by string1 is not already defined:
  string1 ?= [string2]

The macro named by string1 is defined as having the value of string2,
where string2 is defined as all characters, if any, after the
<equals-sign>, up to a comment character (’#’) or an unescaped
<newline>. Any <blank> characters immediately after the <equals-sign>,
or immediately before the <equals-sign>, <colon>, or <question-mark>
respectively, shall be ignored.

The following form (the "append" form) appends additional text to the
value of a macro:
  string1 += [string2]

When using the append form:
* If the macro named by string1 does not exist, this form shall be
equivalent to the delayed-expansion form "string1 = string2".
* If the macro named by string1 exists and is an immediate-expansion
macro, then a <space> or <tab> character followed by the evaluation
of string2 shall be appended to the value currently assigned to the
macro named by string1.
* If the macro named by string1 exists and is a delayed-expansion
macro, then a <space> or <tab> character followed by the unevaluated
string2 shall be appended to the value currently assigned to the
macro named by string1.

In all cases the value of string2 is defined as all characters, if
any, after the <equals-sign>, up to a comment character (’#’) or an
unescaped <newline>. Any <blank> characters immediately after the
<equals-sign> or immediately before the <plus-sign> shall be ignored."

Before line 95797, insert:
"* Immediate-expansion macros shall be evaluated immediately when
the macro assignment is made, and this value shall be used as the
replacement until the immediate-expansion macro is redefined."

At line 95797, change "Macros after..." to "Delayed-expansion
macros...".

At line 95809-95811, change:
"Macro expansions in string2 of macro definition lines shall be
performed when the macro identified by string1 is expanded in a rule
or command."

to
"Macro expansions in string2 of macro definition lines shall be
performed according to the form used to define the macro.
Immediate-expansion forms (including appending to an existing
immediate-expansion macro) shall be expanded in the macro
definition line, and shall not be re-expanded when used in a rule
or command. Delayed-expansion forms (including appending to an
existing delayed-expansion macro, and conditional assignment to a
macro not previously existing) shall be expanded when the macro
identified by string1 is expanded in a rule or command, and the
result of the expansion shall be scanned for further macros."

On line 96103 (APPLICATION USAGE), change:
"Macros used within other macros shall be evaluated when the new macro
is used rather than when the new macro is defined. Therefore:
MACRO = value1
NEW = $(MACRO)
MACRO = value2
target:
    echo $(NEW)
would produce value2 and not value1 since NEW was not expanded until
it was needed in the echo command line."

to:
"Delayed-expansion macros shall be evaluated when they are used rather
than when they are defined. Therefore:
MACRO = value1
IMMED ::= $(MACRO)
DELAY = $(MACRO)
MACRO = value2
target:
    echo $(IMMED) $(DELAY)
would produce "value1 value2", since IMMED was expanded while MACRO
was value1, but DELAY was not expanded until it was needed in the echo
command line when MACRO was value2."

After line 96368 (RATIONALE), add:
"The traditional semantics of delayed-expansion macros has often been
the source of subtle bugs for makefile writers not aware of those
semantics. Furthermore, in implementations that support an extension
of assigning the output of an arbitrary command to a macro definition,
the use of delayed-expansion macros could result in an undesirable
growth in execution time, as each use of the macro would re-run the
arbitrary command. Historically, several implementations independently
developed a form of immediate expansion, usually via the operator
':=', so that execution of an arbitrary command happens once at the
definition of the macro rather than each use of the macro; however,
there are subtle differences in the expansion rules of those various
implementations when the expanded value of string2 contained a '$'.
Other implementations used operator ':=' for conditional expansion,
altogether unrelated to immediate-expansion macro definition.

The standard developers felt that immediate-expansion semantics were
useful enough to standardize, but requiring the semantics of any one
implementation of ':=' would cause confusion in Makefiles written for
other implementation semantics, necessitating a reader to determine
if '.POSIX:' had been specified at the beginning of the file (or
worse, at the beginning of some other file that then includes the
fragment in question) to know which semantics would be in use.
Therefore, the standard developers opted to require a new operator
'::=' with specific semantics; this operator has semantics closest
to the GNU make implementation of ':=', where '$' occurring in the
immediate expansion of string2 are not further expanded in subsequent
use of the macro, and it was felt that other implementations could
easily support the required semantics.

Implementations that previously provided ':=' as an extension are
encouraged to leave this extension intact, with no change in the
implementation's particular semantics, to avoid breaking non-portable
makefiles that had been targetting that particular implementation. A
portable makefile, with '.POSIX:' specified at the beginning, should
not use the ':=' operator."


- Issue History
Date Modified Username Field Change
2010-10-11 21:45 dwheeler New Issue
2010-10-11 21:45 dwheeler Status New => Under Review
2010-10-11 21:45 dwheeler Assigned To => ajosey
2010-10-11 21:45 dwheeler Name => David A. Wheeler
2010-10-11 21:45 dwheeler Section => make
2010-10-11 21:45 dwheeler Page Number => 2908-2929
2010-10-11 21:45 dwheeler Line Number => 95549-95822
2010-10-11 22:55 dwheeler Note Added: 0000567
2010-10-11 22:55 dwheeler Note Added: 0000568
2010-10-11 23:01 Don Cragun Note Deleted: 0000568
2010-10-14 18:39 dwheeler Note Added: 0000577
2011-11-07 05:45 ajosey Relationship added related to 0000337
2011-11-10 13:44 joerg Note Added: 0001003
2011-11-12 06:10 ajosey Note Added: 0001009
2011-11-15 19:42 dwheeler Note Added: 0001014
2011-11-15 21:28 brkorb Note Added: 0001015
2011-11-15 23:03 dwheeler Note Added: 0001016
2011-11-15 23:07 dwheeler Note Added: 0001017
2011-11-15 23:42 eblake Note Added: 0001018
2011-11-16 01:01 Love4Boobies Note Added: 0001019
2011-11-16 02:06 Love4Boobies Note Edited: 0001019
2011-11-17 10:46 joerg Note Added: 0001024
2011-12-05 19:00 dwheeler Note Added: 0001073
2011-12-05 19:10 Don Cragun Interp Status => ---
2011-12-05 19:10 Don Cragun Summary In make, add support for assignments ":=", "+=", and "?=". => In make, add support for assignments "::=", "+=", and "?=".
2011-12-06 16:37 eblake Tag Attached: issue8
2011-12-06 16:40 eblake Note Added: 0001075
2011-12-06 21:49 eblake Note Added: 0001079
2011-12-15 16:27 eblake Note Edited: 0001079
2011-12-15 16:33 eblake Final Accepted Text => see Note: 0001079
2011-12-15 16:33 eblake Status Under Review => Resolved
2011-12-15 16:33 eblake Resolution Open => Accepted As Marked
2015-04-23 23:16 emaste Issue Monitored: emaste
2020-02-10 12:26 geoffclare Status Resolved => Applied
2024-06-11 08:53 agadmin Status Applied => Closed


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker