make-alpha
[Top][All Lists]
Advanced

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

Can we do it: variable scoping


From: Paul Smith
Subject: Can we do it: variable scoping
Date: Tue, 9 Nov 2010 18:13:25 -0500

It seems that every few months, someone wants to use a variable scoping
capability; this request seems be becoming more prevalent as more people
eschew recursive makefiles and have single make instances including tons
of smaller makefiles.

Of course you can avoid the need for scoping by choosing make variable
name prefixes etc., and with make's ability to use constructed variable
names it can be made somewhat less painful.

And, you can even clear out variables after you've included a makefile,
using the $(.VARIABLES) special variable, to avoid leaking variables
between included makefiles for example.


Still, abstractly it seems like it would be helpful to provide
first-class variable scoping capabilities, so I was thinking about how
difficult that would be to do.

I think, actually, that it's not that hard for the most part.  We
already have the ability to have nested variable scopes, to support
target-specific variables.  This feature would create multiple "global"
scopes as well, and individual targets would be hooked to the scope that
was active when the target was defined.  So a new scope would create a
new variable set as the "global" scope, and all targets would be hooked
to that as their variable scope.  When the scope ended we'd "pop" that
scope and reinstall its parent as the global.  This is all already
basically supported internally.

I thought we might also need "variable assignment scopes", as well as
target scopes, but I'm not sure we do: I can't think of any situation
where a variable is evaluated in a deferred context where it would need
to know what scope it was defined in, other than in a target context.  I
know that didn't make much sense but I can explain further if anyone
cares.


There are three issues I can see: first, we need to come up with a
makefile syntax.  I think a simple (nesting) push/pop-style scope is
what we want (I definitely don't want to get into "named scopes").  Does
anyone know of any other make implementation (or similar build tool)
that implements something like this?  What syntax do they use?


Second, we have to think carefully about how a new variable scope would
interact with the existing "target specific variable inheritance"
feature.  This could be the thing that knocks down the entire proposal.
Basically we already have a stack of variable scopes, constructed
dynamically based on the prerequisite tree.  How does a static variable
scoping, tied to the target itself, fit into that existing stack?

For example, today if we have:

        foo: FOO = foo
        foo: bar

        FOO = bar
        bar: ; @echo $(FOO)

you'll get "foo" here, because the "bar" target inherited the value of
FOO from foo's target-specific variable.  If you run "make bar" you'll
get "bar".

How does this kind of thing work if you add variable scoping?  Obviously
expanding "FOO" first looks at bar's target-specific variables, but if
it's not there where does it look next?  Does it look at the parent
target's variable list, which might be in an entirely different variable
scope?

At this point the only realistic, _implementable_ option I see is that
it looks in all inherited target-specific variables first, and then
where it currently jumps to the "global" scope it would then instead
jump into the variable scope.  That will definitely lead to some odd
results, but it's at least deterministic.  More and more I am sorry I
kept the target variable inheritance feature from Solaris make... ugh!


Finally, I'm concerned about maintainability/debug-ability.  It's
already tricky, often, to figure out where the value of a variable came
from.  This may be the proverbial straw that forces us to do some kind
of variable expansion tracking--although how to do this without
completely inundating the user with obscene amounts of information is
going to be "interesting".

Related to the previous issue, what about -p output?  I can't see any
real way to provide -p output that makes sense.  In order to reconstruct
the scoping we would have to track, somewhere, all the targets that were
declared in a given scope.  There is no other reason to track this and
it seems like a lot of effort.  Of course, I suppose we could
reconstruct it dynamically based on the variable scoping structure
itself (go through all the targets and figure out their scope based on
which variable set they reference).




reply via email to

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