summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-04-20 03:30:39 (GMT)
committerSteven Knight <knight@baldmt.com>2003-04-20 03:30:39 (GMT)
commitb462d3a29bc8ed264b51c6af5e38cd878ca00ea2 (patch)
tree3d4cbf18f71cfa6b6622e3a4a33f4f36d522063a
parent1691e6792ea238c0cfe3d8f4cc1aa56262d343b4 (diff)
downloadSCons-b462d3a29bc8ed264b51c6af5e38cd878ca00ea2.zip
SCons-b462d3a29bc8ed264b51c6af5e38cd878ca00ea2.tar.gz
SCons-b462d3a29bc8ed264b51c6af5e38cd878ca00ea2.tar.bz2
Make Export() work for local variables. (Anthony Roach)
-rw-r--r--doc/man/scons.125
-rw-r--r--src/CHANGES.txt6
-rw-r--r--src/engine/SCons/Script/SConscript.py67
-rw-r--r--test/SConscript.py130
4 files changed, 200 insertions, 28 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index 27dd9a7..18c5d80 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -3318,9 +3318,12 @@ The exported variables are kept in a global collection,
so subsequent calls to
.BR Export ()
will over-write previous exports that have the same name.
-Multiple variable names should be passed to
+Multiple variable names can be passed to
.BR Export ()
-as separate arguments. Examples:
+as separate arguments or as a list. A dictionary can be used to map
+variables to a different name when exported. Both local variables and
+global variables can be exported.
+Examples:
.ES
env = Environment()
@@ -3328,8 +3331,14 @@ env = Environment()
Export("env")
package = 'my_name'
-# Make env and package available for all SConscript files to Import().
+# Make env and package available for all SConscript files:.
Export("env", "package")
+
+# Make env and package available for all SConscript files:
+Export(["env", "package"])
+
+# Make env available using the name debug:.
+Export({"debug":env})
.EE
.IP
@@ -3405,14 +3414,17 @@ argument to
Variables exported by
.BR SConscript ()
have precedence.
-Multiple variable names should be passed to
+Multiple variable names can be passed to
.BR Import ()
-as separate arguments.
+as separate arguments or as a list. The variable "*" can be used
+to import all variables.
Examples:
.ES
Import("env")
Import("env", "variable")
+Import(["env", "variable"])
+Import("*")
.EE
.TP
@@ -3554,7 +3566,8 @@ as a SConscript (configuration) file.
The optional
.I exports
-argument provides a list of variable names to export to
+argument provides a list of variable names or a dictionary of
+named values to export to
.IR script ". "
These variables are locally exported only to the specified
.IR script ,
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 2f3ffbd..f6f2746 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -69,6 +69,12 @@ RELEASE 0.14 - XXX
- Add a standalone "Alias" function (separate from an Environment).
+ - Make Export() work for local variables.
+
+ - Support passing a dictionary to Export().
+
+ - Support Import('*') to import everything that's been Export()ed.
+
From Greg Spencer:
- Support the C preprocessor #import statement.
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index 1c9d2b2..e77b879 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -75,24 +75,46 @@ def _scons_add_args(alist):
a, b = string.split(arg, '=', 2)
arguments[a] = b
+def get_calling_namespaces():
+ """Return the locals and globals for the function that called
+ into this module in the current callstack."""
+ try: 1/0
+ except: frame = sys.exc_info()[2].tb_frame
+
+ while frame.f_globals.get("__name__") == __name__: frame = frame.f_back
+
+ return frame.f_locals, frame.f_globals
+
+
+def compute_exports(exports):
+ """Compute a dictionary of exports given one of the parameters
+ to the Export() function or the exports argument to SConscript()."""
+ exports = SCons.Util.argmunge(exports)
+ loc, glob = get_calling_namespaces()
+
+ retval = {}
+ try:
+ for export in exports:
+ if SCons.Util.is_Dict(export):
+ retval.update(export)
+ else:
+ try:
+ retval[export] = loc[export]
+ except KeyError:
+ retval[export] = glob[export]
+ except KeyError, x:
+ raise SCons.Errors.UserError, "Export of non-existant variable '%s'"%x
+
+ return retval
+
+
class Frame:
"""A frame on the SConstruct/SConscript call stack"""
def __init__(self, exports):
self.globals = BuildDefaultGlobals()
self.retval = None
self.prev_dir = SCons.Node.FS.default_fs.getcwd()
- self.exports = {} # exports from the calling SConscript
-
- try:
- if SCons.Util.is_List(exports):
- for export in exports:
- self.exports[export] = stack[-1].globals[export]
- else:
- for export in string.split(exports):
- self.exports[export] = stack[-1].globals[export]
- except KeyError, x:
- raise SCons.Errors.UserError, "Export of non-existant variable '%s'"%x
-
+ self.exports = compute_exports(exports) # exports from the calling SConscript
# the SConstruct/SConscript call stack:
stack = []
@@ -339,21 +361,22 @@ def FindFile(file, dirs):
return SCons.Node.FS.find_file(file, nodes)
def Export(*vars):
- try:
- for var in vars:
- for v in string.split(var):
- global_exports[v] = stack[-1].globals[v]
- except KeyError, x:
- raise SCons.Errors.UserError, "Export of non-existant variable '%s'"%x
+ for var in vars:
+ global_exports.update(compute_exports(var))
def Import(*vars):
try:
for var in vars:
- for v in string.split(var):
- if stack[-1].exports.has_key(v):
- stack[-1].globals[v] = stack[-1].exports[v]
+ var = SCons.Util.argmunge(var)
+ for v in var:
+ if 'v' == '*':
+ stack[-1].globals.update(global_exports)
+ stack[-1].globals.update(stack[-1].exports[v])
else:
- stack[-1].globals[v] = global_exports[v]
+ if stack[-1].exports.has_key(v):
+ stack[-1].globals[v] = stack[-1].exports[v]
+ else:
+ stack[-1].globals[v] = global_exports[v]
except KeyError,x:
raise SCons.Errors.UserError, "Import of non-existant variable '%s'"%x
diff --git a/test/SConscript.py b/test/SConscript.py
index df215a3..a290d07 100644
--- a/test/SConscript.py
+++ b/test/SConscript.py
@@ -212,5 +212,135 @@ test.run(arguments = ".",
stdout = test.wrap_stdout(read_str = 'SConstruct %s\nSConscript %s\n' % (wpath, wpath),
build_str = 'scons: "." is up to date.\n'))
+# Test exporting all global variables as a list of keys:
+test.write("SConstruct", """
+x = 'x'
+y = 'zoom'
+Export(globals().keys())
+SConscript('SConscript')
+""")
+
+test.write("SConscript", """
+Import(['x', 'y'])
+assert x == 'x'
+assert y == 'zoom'
+""")
+
+test.run(arguments = ".")
+
+# Test exporting all global variables as a list of keys in SConscript call:
+test.write("SConstruct", """
+x = 'x'
+y = 'zoom'
+SConscript('SConscript', globals().keys())
+""")
+
+test.write("SConscript", """
+Import(['x', 'y'])
+assert x == 'x'
+assert y == 'zoom'
+""")
+
+test.run(arguments = ".")
+
+# Test exporting all global variables as a dictionary:
+test.write("SConstruct", """
+x = 'x'
+y = 'zoom'
+Export(globals())
+SConscript('SConscript')
+""")
+
+test.write("SConscript", """
+Import(['x', 'y'])
+assert x == 'x'
+assert y == 'zoom'
+""")
+
+test.run(arguments = ".")
+
+# Test exporting all global variables as dictionary in SConscript call:
+test.write("SConstruct", """
+x = 'x'
+y = 'zoom'
+SConscript('SConscript', globals())
+""")
+
+test.write("SConscript", """
+Import(['x', 'y'])
+assert x == 'x'
+assert y == 'zoom'
+""")
+
+test.run(arguments = ".")
+
+# Test export of local variables:
+test.write("SConstruct", """
+def f():
+ x = 'x'
+ y = 'zoom'
+ Export('x', 'y')
+
+f()
+SConscript('SConscript')
+""")
+
+test.write("SConscript", """
+Import(['x', 'y'])
+assert x == 'x'
+assert y == 'zoom'
+""")
+
+test.run(arguments = ".")
+
+# Test export of local variables in SConscript call:
+test.write("SConstruct", """
+def f():
+ x = 'x'
+ y = 'zoom'
+ SConscript('SConscript', ['x', 'y'])
+f()
+""")
+
+test.write("SConscript", """
+Import(['x', 'y'])
+assert x == 'x'
+assert y == 'zoom'
+""")
+
+test.run(arguments = ".")
+
+# Test export of local variables as a dictionary:
+test.write("SConstruct", """
+def f():
+ x = 'x'
+ y = 'zoom'
+ Export(locals())
+
+f()
+SConscript('SConscript')
+""")
+
+test.write("SConscript", """
+Import(['x', 'y'])
+assert x == 'x'
+assert y == 'zoom'
+""")
+
+test.run(arguments = ".")
+
+# Test importing all variables:
+test.write("SConstruct", """
+x = 'x'
+y = 'zoom'
+Export('x')
+SConscript('SConscript', 'y')
+""")
+
+test.write("SConscript", """
+Import('*')
+assert x == 'x'
+assert y == 'zoom'
+""")
test.pass_test()