[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: 6.2 The Two Flavors of Variables
Re: 6.2 The Two Flavors of Variables
Thu, 24 Feb 2011 10:16:07 -0500
On Thu, 2011-02-24 at 15:42 +0100, grischka wrote:
> >> CFLAGS = $(CFLAGS) -O
> >> Why it causes an infinite loop? The first time $(CFLAGS) is null so
> >> the right side will be expanded to "null -O". There will be no second
> >> time as null is a final value and CFLAGS becomes -O
> > Now make wants to expand $(CFLAGS) and it sees that the value of that
> > variable is '$(CFLAGS) -O'. So it then tries to expand that, and sees
> > that $(CFLAGS) expands to '$(CFLAGS) -O'. And so on until you run out
> > of memory.
> I'd still argue that this is nothing more than a pretty accurate
> description of an implementation bug.
You may consider it so, but along with the use of TABs to prefix recipe
lines you must blame the inventors of the original make, back in the
1970's, and also of course the writers of the POSIX spec. This is the
one and only type of variable that is defined and supported in those
makes and so it must be defined and supported this way in GNU make.
> Which is also the only way to explain why gnu-make invented the term
> "recursive variable" to denote a variable that must not be used
No. They're termed "recursive variables" because they are expanded
recursively; that is, the value is expanded and the expansion of the
value is expanded and the value of THAT is expanded, etc. recursively
until a point where there is nothing left to expand.
The behavior in question is exactly a result of this definition: there
can never be "nothing left to expand" when the value includes a
reference to the variable itself.
Compare to simple variables (:=) where the value of the variable is
substituted directly, without expansion, when it's referenced.
> For example, there is no difference semantically whether you write
> CFLAGS = $(CFLAGS) -O
> CFLAGS += -O
> Now since gnu-make does support the latter there cannot be a quasi
> natural logical reason why it can't support the former, because +=
> also implicitly references an value of the variable which if it was
> expanded like you describe above would cause the same memory overflow.
No it doesn't. The difference is very simple to see if you think about
the assignment correctly. A recursive assignment doesn't expand the
value at all on assignment. So the value of the variable CFLAGS is the
literal string '$(CFLAGS) -O'.
The += operator for recursive variables is nothing more than string
concatenation: all make does is add more on to the end of the literal
string: you get '$(CFLAGS) -O -O' as the value. The value is NOT
expanded there. No recursion, no harm, no foul.
In order for your theoretical feature to work, make would have to keep
some kind of stack of all past values of CFLAGS, so that it could be
expanded backward to the beginning of time.
> See also:
> which basically discusses a -= operator as in
> CFLAGS -= -O
Yes, and see my response which gives more examples of the complexities
behind this apparently simple suggestion :-).
The example in your response missed a very important case: what if the
SAME variable is used MULTIPLE times in the same expansion, possible at
different levels? Does each instance of the variable start at the "top"
of the expansion, so that each instance requires its own pointer into
the stack of potential values? Or do they start at the current value so
you could keep one "pointer"? I would think the latter would be
completely unworkable, from a usability standpoint, but unless I'm
mistaken the former doesn't solve the problem (you can still easily get
Paul D. Smith <address@hidden> Find some GNU make tips at:
"Please remain calm...I may be mad, but I am a professional." --Mad Scientist