[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: local variable in make
Re: local variable in make
Mon, 9 Aug 2010 23:50:24 -0500
On Mon, Aug 9, 2010 at 9:58 PM, Philip Guenther <address@hidden> wrote:
> On Mon, Aug 9, 2010 at 7:13 PM, Peng Yu <address@hidden> wrote:
>>> Right. In make every global variable (like PREFIX here) has one and
>>> only one value. When you change that value, then it has the new value.
>>> This is a very fundamental aspect of make: you simply cannot expect to
>>> create complex makefiles until you completely internalize how expansion
>> Are you considering adding the local variable feature to macros? I
>> know that it may not easy to implement such feature in a backward
>> compatible way. But having such feature helps writing more complex and
>> more flexible Makefiles.
> Given the way that variable expansion works in make, 'local' variables
> would be a *HUGE* trap. If you think you have headaches from $(eval),
> combining them with local variables will make your code completely
> impossible to debug or maintain. Just think about how deferred
> expansion works: the scope of a "local" variable would have to include
> contexts outside of the macro's expansion, or else they would have to
> be so completely limited as to be almost pointless. I.e., they would
> either be a misnomer or a bad choice.
> What you probably want is simply a way to generate a relatively unique
> name for a variable. Fortunately, you can do that right now by
> including some unique argument in the variable names. In this case,
> $1 should work, no?
> PREFIX.$1 = $1
> echo all:$$(PREFIX.$1)
I had thought about this walkaround. But the problem is that $1 may
have some characters that are not allowed in variable names.
> Of course, this example is completely ridiculous (you have $1, so USE
> IT!), but given the example that's the best that can be shown.
This is not ridiculous. I'd rather than have a more descriptive name
rather than $1, if it is supported by make.
>>> You need to read the GNU make manual section on "How make reads a
>>> makefile" again (and again): afterwards you'll understand (hopefully,
>>> unless the manual is not well written) the concept of immediate
>>> expansion vs. deferred expansion.
>> I found the following way of defining PREFIX as a macro that takes an
>> argument ($1).
>> .PHONY: all
>> define myfun
>> PREFIX=$$(patsubst %,%,$$(1))
> This only works because PREFIX has the same definition in each case.
> I.e., it's a completely pointless variable. Why do you want a
> variable PREFIX when you already have the value in $1?
As I said, I made a simple example for demonstration purpose. What if I have
PREFIX:=a very long command
It would be inconvenient to spell out each instance of PREFIXes.
>>> or even better, skip eval and call altogether and use simply:
>>> echo $@
> Yes, this is *EXACTLY* what should be done. It sometimes seems that
> people use $(eval) because they think it's simpler than pattern rules,
> or maybe that it's easier to think about, but the opposite is true.
>>> Eval, in particular, is very tricky to use and so you should
>>> never even attempt to use it unless you're absolutely sure that any
>>> lesser option simply won't work.
>> Yes. My real case is too complex to be described here. If I did,
>> probably you will get lost. So I made a simple example to capture the
>> gist of my real case. But making my example even simpler won't help my
>> real case.
> If your case is so complex that you can't describe it, then it's too
> complicated, period. You need to find a way that *you* understand
> that can break it down into smaller problems that you can solve. For
> many many years, the answers to that have been
> - just write out all the rules
> - write a program (in shell, awk, m4, whatever) to generate
> the makefile...that has them all written out
It is not that I can't describe. Describing it in a complex context
doesn't really help people understand the problem better. People don't
have time to read. Remember, you still haven't got time to reply my
long email that I send you previously on recursive make :-).
Therefore, I'd rather not to make the description more complex than it
> Note that $(eval) is basically the latter, but you're writing that
> program in a weird language with deferred expansion and confusing
> lexical rules. It's like using the most uncomfortable screwdriver to
> insert screws, just because it came in the box of screws.
>> The complexity of the usage eval probably should be better expanded in
>> the manual. The current explanation of eval in the manual is probably
>> too sparse, considering that there could be many tricks in using eval
>> for high-order programming (just as eval in Lisp and Perl).
> Umm, Lisp programs put 'eval' in the very back corner of their
> toolbox, with barbed-wire around it, because 99 times out of 100 (or
> (more!) it's the Wrong Thing. The Right Thing there is generally
> defmacro...which is not what make has. The perl people do the same
> thing with _their_ "expand and re-evaluate as perl code" operator
> (which is one of the two uses of their eval) for similar reasons:
> variable references, closures, and compiled regexps solved 99/100 of
> their problems.
>>> Alternatively you could use target-specific variables but it seems like
>> Yes, that is the reason that I am looking for some walkaround for
>> 'local' variables.
> I don't get it. "I'm looking for a workaround for my problem. This
> is a workaround, but I don't want to use it." ?
Because this walkaround don't cover corner cases. What if you have
special variables that are not allowed in targets in the $1? Something
like the following won't work.