.TP
--debug=count
-Print a count of how many objects are created
-of the various classes used internally by SCons.
+Print how many objects are created
+of the various classes used internally by SCons
+before and after reading the SConscript files
+and before and after building targets.
This only works when run under Python 2.1 or later.
.TP
--debug=memory
Prints how much memory SCons uses
before and after reading the SConscript files
-and before and after building.
+and before and after building targets.
.TP
--debug=objects
- Allow more than one --debug= option to be set at a time.
+ - Change --debug=count to report object counts before and after
+ reading SConscript files and before and after building targets.
+
+ - Change --debug=memory output to line up the numbers and to better
+ match (more or less) the headers on the --debug=count columns.
+
From Wayne Lee:
- Avoid "maximum recursion limit" errors when removing $(-$) pairs
else:
return string.split(s)
+def fetchLoggedInstances(classes="*"):
+ classnames = string_to_classes(classes)
+ return map(lambda cn: (cn, len(tracked_classes[cn])), classnames)
+
def countLoggedInstances(classes, file=sys.stdout):
for classname in string_to_classes(classes):
file.write("%s: %d\n" % (classname, len(tracked_classes[classname])))
# Global variables
keep_going_on_error = 0
-print_count = 0
+count_stats = None
print_dtree = 0
print_explanations = 0
print_includes = 0
def _set_globals(options):
global repositories, keep_going_on_error, ignore_errors
- global print_count, print_dtree
+ global count_stats, print_dtree
global print_explanations, print_includes, print_memoizer
global print_objects, print_stacktrace, print_stree
global print_time, print_tree
pass
else:
if "count" in debug_values:
- print_count = 1
+ count_stats = []
if "dtree" in debug_values:
print_dtree = 1
if "explain" in debug_values:
fs.Repository(rep)
if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
+ if not count_stats is None: count_stats.append(SCons.Debug.fetchLoggedInstances())
progress_display("scons: Reading SConscript files ...")
SCons.Node.FS.save_strings(1)
if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
+ if not count_stats is None: count_stats.append(SCons.Debug.fetchLoggedInstances())
fs.chdir(fs.Top)
SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
+ if not count_stats is None: count_stats.append(SCons.Debug.fetchLoggedInstances())
try:
jobs.run()
if not memory_stats is None:
memory_stats.append(SCons.Debug.memory())
when = [
- 'before SConscript files',
- 'after SConscript files',
- 'before building',
- 'after building',
+ 'before reading SConscript files',
+ 'after reading SConscript files',
+ 'before building targets',
+ 'after building targets',
]
for i in xrange(len(when)):
- memory_outf.write('Memory %s: %d\n' % (when[i], memory_stats[i]))
-
- if print_count:
- SCons.Debug.countLoggedInstances('*')
+ memory_outf.write('Memory %-32s %12d\n' % (when[i]+':', memory_stats[i]))
+
+ if not count_stats is None:
+ count_stats.append(SCons.Debug.fetchLoggedInstances())
+ stats_table = {}
+ for cs in count_stats:
+ for n in map(lambda t: t[0], cs):
+ stats_table[n] = [0, 0, 0, 0]
+ i = 0
+ for cs in count_stats:
+ for n, c in cs:
+ stats_table[n][i] = c
+ i = i + 1
+ keys = stats_table.keys()
+ keys.sort()
+ print "Object counts:"
+ fmt = " %7s %7s %7s %7s %s"
+ print fmt % ("pre-", "post-", "pre-", "post-", "")
+ print fmt % ("read", "read", "build", "build", "Class")
+ for k in keys:
+ r = stats_table[k]
+ print " %7d %7d %7d %7d %s" % (r[0], r[1], r[2], r[3], k)
if print_objects:
SCons.Debug.listLoggedInstances('*')
assert check(total_time, sconscript_time+scons_time+command_time, 0.01)
assert check(total_time, expected_total_time, 0.1)
-try:
- import resource
-except ImportError:
- print "Python version has no `resource' module;"
- print "skipping test of --debug=memory."
-else:
- ############################
- # test --debug=memory
-
- test.run(arguments = "--debug=memory")
- lines = string.split(test.stdout(), '\n')
- test.fail_test(re.match(r'Memory before SConscript files: \d+', lines[-5]) is None)
- test.fail_test(re.match(r'Memory after SConscript files: \d+', lines[-4]) is None)
- test.fail_test(re.match(r'Memory before building: \d+', lines[-3]) is None)
- test.fail_test(re.match(r'Memory after building: \d+', lines[-2]) is None)
-
-try:
- import weakref
-except ImportError:
- print "Python version has no `weakref' module;"
- print "skipping tests of --debug=count and --debug=objects."
-else:
- ############################
- # test --debug=count
- # Just check that object counts for some representative classes
- # show up in the output.
- test.run(arguments = "--debug=count")
- stdout = test.stdout()
- test.fail_test(re.search('BuilderBase: \d+', stdout) is None)
- test.fail_test(re.search('FS: \d+', stdout) is None)
- test.fail_test(re.search('Node: \d+', stdout) is None)
- test.fail_test(re.search('SConsEnvironment: \d+', stdout) is None)
-
- ############################
- # test --debug=objects
- # Just check that it runs, we're not overly concerned about the actual
- # output at this point.
- test.run(arguments = "--debug=objects")
-
############################
# test --debug=presub
--- /dev/null
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the --debug=count option works.
+"""
+
+import TestSCons
+import sys
+import string
+import re
+import time
+
+test = TestSCons.TestSCons()
+
+try:
+ import weakref
+except ImportError:
+ print "Python version has no `weakref' module;"
+ print "skipping tests of --debug=count."
+ test.pass_test()
+
+
+
+test.write('SConstruct', """
+def cat(target, source, env):
+ open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
+env = Environment(BUILDERS={'Cat':Builder(action=Action(cat))})
+env.Cat('file.out', 'file.in')
+""")
+
+test.write('file.in', "file.in\n")
+
+# Just check that object counts for some representative classes
+# show up in the output.
+test.run(arguments = "--debug=count")
+stdout = test.stdout()
+
+test.fail_test(re.search('\d+ +\d+ +\d+ +\d+ BuilderBase', stdout) is None)
+test.fail_test(re.search('\d+ +\d+ +\d+ +\d+ FS', stdout) is None)
+test.fail_test(re.search('\d+ +\d+ +\d+ +\d+ Node', stdout) is None)
+test.fail_test(re.search('\d+ +\d+ +\d+ +\d+ SConsEnvironment', stdout) is None)
+
+
+
+test.pass_test()
--- /dev/null
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the --debug=memory option works.
+"""
+
+import TestSCons
+import sys
+import string
+import re
+import time
+
+test = TestSCons.TestSCons()
+
+try:
+ import resource
+except ImportError:
+ print "Python version has no `resource' module;"
+ print "skipping test of --debug=memory."
+ test.pass_test()
+
+
+
+test.write('SConstruct', """
+def cat(target, source, env):
+ open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
+env = Environment(BUILDERS={'Cat':Builder(action=Action(cat))})
+env.Cat('file.out', 'file.in')
+""")
+
+test.write('file.in', "file.in\n")
+
+test.run(arguments = "--debug=memory")
+
+lines = string.split(test.stdout(), '\n')
+
+test.fail_test(re.match(r'Memory before reading SConscript files: +\d+', lines[-5]) is None)
+test.fail_test(re.match(r'Memory after reading SConscript files: +\d+', lines[-4]) is None)
+test.fail_test(re.match(r'Memory before building targets: +\d+', lines[-3]) is None)
+test.fail_test(re.match(r'Memory after building targets: +\d+', lines[-2]) is None)
+
+
+
+test.pass_test()
--- /dev/null
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the --debug=objects option works.
+"""
+
+import TestSCons
+import sys
+import string
+import re
+import time
+
+test = TestSCons.TestSCons()
+
+try:
+ import weakref
+except ImportError:
+ print "Python version has no `weakref' module;"
+ print "skipping tests of --debug=objects."
+ test.pass_test()
+
+
+
+test.write('SConstruct', """
+def cat(target, source, env):
+ open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
+env = Environment(BUILDERS={'Cat':Builder(action=Action(cat))})
+env.Cat('file.out', 'file.in')
+""")
+
+test.write('file.in', "file.in\n")
+
+# Just check that it runs, we're not overly concerned about the actual
+# output at this point.
+test.run(arguments = "--debug=objects")
+
+
+
+test.pass_test()