help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: local variable in make


From: Peng Yu
Subject: Re: local variable in make
Date: 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
>>> works.
>>
>> 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
> all$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:
>>>
>>>        all%:
>>>                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
should be.

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

all$1:

-- 
Regards,
Peng



reply via email to

[Prev in Thread] Current Thread [Next in Thread]