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 21:13:36 -0500

On Mon, Aug 9, 2010 at 8:04 PM, Paul Smith <address@hidden> wrote:
> On Mon, 2010-08-09 at 17:53 -0500, Peng Yu wrote:
>> I tried 'undefine' below. It still has the same problem. I guess this
>> is because make has two stage to pass the variables and then construct
>> the rules.
>>
>> .PHONY: all
>> PREFIX:=abc
>> all: all1
>>       echo all:$(PREFIX)
>> undefine PREFIX
>> PREFIX:=efg
>> all1:
>>       echo all1:$(PREFIX)
>
> 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.

> 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))

all$1:
        echo all:$$(call PREFIX, $1)

endef

all: allabc
$(eval $(call myfun,abc))

all: allefg
$(eval $(call myfun,efg))
#################

But I'm not how to define an PREFIX as an macro that doesn't take an
argument. (The following doesn't work)
####
.PHONY: all

define myfun
PREFIX=$$1

all$1:
        echo all:$$(call PREFIX)

endef

all: allabc
$(eval $(call myfun,abc))

all: allefg
$(eval $(call myfun,efg))
########

BTW, section 3.7 of the manual is hard to read if there are no
examples. I'm not sure exact how to improve it. But at least, I think
that can be made more readable by adding examples for each usage.

> Only during immediate expansion is the value expanded and so the value
> of variables at that point are taken.
>
> As you say, make has a two-pass processor: in the first pass it reads
> the entire makefile.  In this pass, recipes are deferred: they are not
> expanded.  In the second pass make tries to build all the appropriate
> targets.  Just before a target is built, that's when its recipe is
> expanded.
>
> So, for a value of $(PREFIX) in a recipe, whatever the LAST SETTING of
> PREFIX was after all the makefiles are read, is the value that $(PREFIX)
> will have when any recipe is expanded.
>
>> Is there a walkaround to allow local variables in macro? (Not that I
>> couild append the variable with some unique suffix, but this looks
>> ugly and I tend to avoid this walkaround. I'm wondering if there is
>> any better walkaround)
>
> The values of $1, $2, etc. are local to the call macro.
>
> Why are you trying to set a variable like PREFIX here?  Why not just
> reuse the local variables?
>
>        define myfun
>        all$1:
>                echo all:$1
>        endef
>
> Of course, it's better to just say:
>
>        define myfun
>        all$1:
>                echo $@
>        endef
>
> or even better, skip eval and call altogether and use simply:
>
>        all%:
>                echo $@
>
> I can only assume your real intention is too complex for these simpler
> methods.  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.

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

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

-- 
Regards,
Peng



reply via email to

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