- Fix the ability to directly import and use Platform and Tool modules
that have been implicitly imported into an Environment().
+ - Add support for allowing an embedding interface to annotate a node
+ when it's created.
+
From Steve Leblanc:
- Fix the output of -c -n when directories are involved, so it
"""Test the is_literal() function."""
n=SCons.Node.Node()
assert n.is_literal()
+
+ def test_Annotate(self):
+ """Test using an interface-specific Annotate function."""
+ def my_annotate(node, self=self):
+ node.annotation = self.node_string
+
+ save_Annotate = SCons.Node.Annotate
+ SCons.Node.Annotate = my_annotate
+
+ try:
+ self.node_string = '#1'
+ n = SCons.Node.Node()
+ assert n.annotation == '#1', n.annotation
+
+ self.node_string = '#2'
+ n = SCons.Node.Node()
+ assert n.annotation == '#2', n.annotation
+ finally:
+ SCons.Node.Annotate = save_Annotate
if __name__ == "__main__":
# controls whether the cached implicit deps are ignored:
implicit_deps_changed = 0
+# A variable that can be set to an interface-specific function be called
+# to annotate a Node with information about its creation.
+def do_nothing(node): pass
+
+Annotate = do_nothing
class Node:
"""The base Node class, for entities that we know how to
self.pre_actions = []
self.post_actions = []
+ # Let the interface in which the build engine is embedded
+ # annotate this Node with its own info (like a description of
+ # what line in what file created the node, for example).
+ Annotate(self)
+
def generate_build_env(self):
return self.env.Override(self.overrides)
import os.path
import string
import sys
+import traceback
def do_nothing(text): pass
HelpFunction = do_nothing
else:
f = SCons.Node.FS.default_fs.File(str(fn))
if f.rexists():
- file = open(f.rstr(), "r")
+ _file_ = open(f.rstr(), "r")
SCons.Node.FS.default_fs.chdir(f.dir)
if sconscript_chdir:
old_dir = os.getcwd()
# be easily imported
sys.path = [os.path.abspath(str(f.dir))] + sys.path
- exec file in stack[-1].globals
+ # This is the magic line that actually reads up and
+ # executes the stuff in the SConscript file. We
+ # look for the "exec _file_ " from the beginning
+ # of this line to find the right stack frame (the
+ # next one) describing the SConscript file and line
+ # number that creates a node.
+ exec _file_ in stack[-1].globals
else:
sys.stderr.write("Ignoring missing SConscript '%s'\n" %
f.path)
return results[0]
else:
return tuple(results)
+
+def annotate(node):
+ """Annotate a node with the stack frame describing the
+ SConscript file and line number that created it."""
+ stack = traceback.extract_stack()
+ last_text = ""
+ for frame in stack:
+ # If the script text of the previous frame begins with the
+ # magic "exec _file_ " string, then this frame describes the
+ # SConscript file and line number that caused this node to be
+ # created. Record the tuple and carry on.
+ if not last_text is None and last_text[:12] == "exec _file_ ":
+ node.creator = frame
+ return
+ last_text = frame[3]
+
+SCons.Node.Annotate = annotate
def Default(*targets):
global default_targets