summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/man/scons.120
-rw-r--r--src/CHANGES.txt2
-rw-r--r--src/engine/SCons/Script/__init__.py23
-rw-r--r--src/engine/SCons/Util.py32
-rw-r--r--src/engine/SCons/UtilTests.py36
-rw-r--r--test/option--debug.py92
6 files changed, 194 insertions, 11 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index 38b196d..ad8a834 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -264,14 +264,20 @@ or
.I sconstruct
in the specified directory.)
-.IP -d
-Display dependencies while building target files. Useful for
-figuring out why a specific file is being rebuilt, as well as
-general debugging of the build process.
+.\" .IP -d
+.\" Display dependencies while building target files. Useful for
+.\" figuring out why a specific file is being rebuilt, as well as
+.\" general debugging of the build process.
-.\" .TP
-.\" .RI --debug= flags
-.\"Print debugging information. ???
+.TP
+.RI --debug= type
+Print debugging information durring the build process.
+.I type
+specifies what type of of debugging information to print. Currently the
+only supported type is
+.I tree
+which causes the dependency tree to be printed after each top-level
+target is built.
.IP "-e, --environment-overrides"
Variables from the execution environment override construction
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index c84d0cb..54dc2ad 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -20,6 +20,8 @@ RELEASE 0.03 -
- Add a "duplicate" keyword argument to BuildDir() that can be set
to prevent linking/copying source files into build directories.
+ - Add a "--debug=tree" option to print an ASCII dependency tree.
+
RELEASE 0.02 - Sun, 23 Dec 2001 19:05:09 -0600
diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py
index bb67991..3b5a79d 100644
--- a/src/engine/SCons/Script/__init__.py
+++ b/src/engine/SCons/Script/__init__.py
@@ -71,9 +71,15 @@ class BuildTask(SCons.Taskmaster.Task):
if self.target.get_state() == SCons.Node.up_to_date:
if self.top:
print 'scons: "%s" is up to date.' % str(self.target)
+ if print_tree:
+ print
+ print SCons.Util.render_tree(self.target, get_children)
else:
try:
self.target.build()
+ if self.top and print_tree:
+ print
+ print SCons.Util.render_tree(self.target, get_children)
except BuildError, e:
sys.stderr.write("scons: *** [%s] Error %s\n" % (e.node, str(e.stat)))
raise
@@ -106,9 +112,12 @@ calc = None
ignore_errors = 0
keep_going_on_error = 0
help_option = None
+print_tree = 0
# utility functions
+def get_children(node): return node.children()
+
def _scons_syntax_error(e):
"""Handle syntax errors. Print out a message and show where the error
occurred.
@@ -340,9 +349,17 @@ def options_init():
short = 'd',
help = "Print file dependency information.")
- Option(func = opt_not_yet, future = 1,
- long = ['debug'], arg = 'FLAGS',
- help = "Print various types of debugging information.")
+ def opt_debug(opt, arg):
+ global print_tree
+ if arg == "tree":
+ print_tree = 1
+ else:
+ sys.stderr.write("Warning: %s is not a valid debug type\n"
+ % arg)
+
+ Option(func = opt_debug,
+ long = ['debug'], arg='TYPE',
+ help = "Print various types of debugging information.")
Option(func = opt_not_yet, future = 1,
short = 'e', long = ['environment-overrides'],
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py
index 262762e..7687250 100644
--- a/src/engine/SCons/Util.py
+++ b/src/engine/SCons/Util.py
@@ -360,3 +360,35 @@ def autogenerate(dict, fs = SCons.Node.FS.default_fs, dir = None):
for interp in AUTO_GEN_VARS:
interp.instance(dir, fs).generate(dict)
+def render_tree(root, child_func, margin=[0], visited={}):
+ """
+ Render a tree of nodes into an ASCII tree view.
+ root - the root node of the tree
+ child_func - the function called to get the children of a node
+ margin - the format of the left margin to use for children of root.
+ 1 results in a pipe, and 0 results in no pipe.
+ visited - a dictionart of visited nodes in the current branch
+ """
+
+ if visited.has_key(root):
+ return ""
+
+ children = child_func(root)
+ retval = ""
+ for pipe in margin[:-1]:
+ if pipe:
+ retval = retval + "| "
+ else:
+ retval = retval + " "
+
+ retval = retval + "+-" + str(root) + "\n"
+ visited = copy.copy(visited)
+ visited[root] = 1
+
+ for i in range(len(children)):
+ margin.append(i<len(children)-1)
+ retval = retval + render_tree(children[i], child_func, margin, visited
+)
+ margin.pop()
+
+ return retval
diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py
index a7c9e70..168896f 100644
--- a/src/engine/SCons/UtilTests.py
+++ b/src/engine/SCons/UtilTests.py
@@ -207,7 +207,41 @@ class UtilTestCase(unittest.TestCase):
assert dict['_INCFLAGS'][4] == os.path.normpath('fooblatbar'), \
dict['_INCFLAGS'][4]
-
+
+ def test_render_tree(self):
+ class Node:
+ def __init__(self, name, children=[]):
+ self.children = children
+ self.name = name
+ def __str__(self):
+ return self.name
+
+ def get_children(node):
+ return node.children
+
+ windows_h = Node("windows.h")
+ stdlib_h = Node("stdlib.h")
+ stdio_h = Node("stdio.h")
+ bar_c = Node("bar.c", [stdlib_h, windows_h])
+ bar_o = Node("bar.o", [bar_c])
+ foo_c = Node("foo.c", [stdio_h])
+ foo_o = Node("foo.o", [foo_c])
+ foo = Node("foo", [foo_o, bar_o])
+
+ expect = """\
++-foo
+ +-foo.o
+ | +-foo.c
+ | +-stdio.h
+ +-bar.o
+ +-bar.c
+ +-stdlib.h
+ +-windows.h
+"""
+
+ actual = render_tree(foo, get_children)
+ assert expect == actual, (expect, actual)
+
if __name__ == "__main__":
suite = unittest.makeSuite(UtilTestCase, 'test_')
if not unittest.TextTestRunner().run(suite).wasSuccessful():
diff --git a/test/option--debug.py b/test/option--debug.py
new file mode 100644
index 0000000..b44c5f6
--- /dev/null
+++ b/test/option--debug.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2001 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "test/option--test.py __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestSCons
+import sys
+import string
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+env = Environment()
+env.Program('foo', 'foo.c bar.c')
+""")
+
+test.write('foo.c', """
+#include "foo.h"
+int main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("f1.c\n");
+ exit (0);
+}
+""")
+
+test.write('bar.c', """
+#include "bar.h"
+""")
+
+test.write('foo.h', """
+#ifndef FOO_H
+#define FOO_H
+#include "bar.h"
+#endif
+""")
+
+test.write('bar.h', """
+#ifndef BAR_H
+#define BAR_H
+#include "foo.h"
+#endif
+""")
+
+
+if sys.platform == 'win32':
+ foo = 'foo.exe'
+else:
+ foo = 'foo'
+
+test.run(arguments = "--debug=tree " + foo)
+
+tree = """
++-foo
+ +-foo.o
+ | +-foo.c
+ | +-foo.h
+ | +-bar.h
+ +-bar.o
+ +-bar.c
+ +-bar.h
+ +-foo.h
+"""
+
+assert string.find(test.stdout(), tree) != -1
+
+test.run(arguments = "--debug=tree " + foo)
+assert string.find(test.stdout(), tree) != -1
+
+test.pass_test()
+