1 """SCons.Script
2
3 This file implements the main() function used by the scons script.
4
5 Architecturally, this *is* the scons script, and will likely only be
6 called from the external "scons" wrapper. Consequently, anything here
7 should not be, or be considered, part of the build engine. If it's
8 something that we expect other software to want to use, it should go in
9 some other module. If it's specific to the "scons" script invocation,
10 it goes here.
11
12 """
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 __revision__ = "src/engine/SCons/Script/Main.py 2725 2008/03/31 12:52:02 knight"
38
39 import SCons.compat
40
41 import os
42 import os.path
43 import string
44 import sys
45 import time
46 import traceback
47
48
49
50
51
52
53
54
55
56
57 import SCons.CacheDir
58 import SCons.Debug
59 import SCons.Defaults
60 import SCons.Environment
61 import SCons.Errors
62 import SCons.Job
63 import SCons.Node
64 import SCons.Node.FS
65 import SCons.SConf
66 import SCons.Script
67 import SCons.Taskmaster
68 import SCons.Util
69 import SCons.Warnings
70
71 import SCons.Script.Interactive
72
82
83
84
87
88 display = SCons.Util.display
89 progress_display = SCons.Util.DisplayEngine()
90
91 first_command_start = None
92 last_command_end = None
93
95 prev = ''
96 count = 0
97 target_string = '$TARGET'
98
100 if file is None:
101 file = sys.stdout
102
103 self.obj = obj
104 self.file = file
105 self.interval = interval
106 self.overwrite = overwrite
107
108 if callable(obj):
109 self.func = obj
110 elif SCons.Util.is_List(obj):
111 self.func = self.spinner
112 elif string.find(obj, self.target_string) != -1:
113 self.func = self.replace_string
114 else:
115 self.func = self.string
116
121
123 if self.prev:
124 length = len(self.prev)
125 if self.prev[-1] in ('\n', '\r'):
126 length = length - 1
127 self.write(' ' * length + '\r')
128 self.prev = ''
129
131 self.write(self.obj[self.count % len(self.obj)])
132
135
138
145
146 ProgressObject = SCons.Util.Null()
147
151
152
153
154
155 _BuildFailures = []
156
159
161 """An SCons build task."""
162 progress = ProgressObject
163
166
170
193
205
220
222
223
224
225 status = 2
226 exc_info = self.exc_info()
227 try:
228 t, e, tb = exc_info
229 except ValueError:
230 t, e = exc_info
231 tb = None
232 if t is None:
233
234
235 t, e = sys.exc_info()[:2]
236
237 def nodestring(n):
238 if not SCons.Util.is_List(n):
239 n = [ n ]
240 return string.join(map(str, n), ', ')
241
242 errfmt = "scons: *** [%s] %s\n"
243
244 if t == SCons.Errors.BuildError:
245 tname = nodestring(e.node)
246 errstr = e.errstr
247 if e.filename:
248 errstr = e.filename + ': ' + errstr
249 sys.stderr.write(errfmt % (tname, errstr))
250 elif t == SCons.Errors.TaskmasterException:
251 tname = nodestring(e.node)
252 sys.stderr.write(errfmt % (tname, e.errstr))
253 type, value, trace = e.exc_info
254 traceback.print_exception(type, value, trace)
255 elif t == SCons.Errors.ExplicitExit:
256 status = e.status
257 tname = nodestring(e.node)
258 errstr = 'Explicit exit, status %s' % status
259 sys.stderr.write(errfmt % (tname, errstr))
260 else:
261 if e is None:
262 e = t
263 s = str(e)
264 if t == SCons.Errors.StopError and not self.options.keep_going:
265 s = s + ' Stop.'
266 sys.stderr.write("scons: *** %s\n" % s)
267
268 if tb and print_stacktrace:
269 sys.stderr.write("scons: internal stack trace:\n")
270 traceback.print_tb(tb, file=sys.stderr)
271
272 self.do_failed(status)
273
274 self.exc_clear()
275
276 - def postprocess(self):
277 if self.top:
278 t = self.targets[0]
279 for tp in self.options.tree_printers:
280 tp.display(t)
281 if self.options.debug_includes:
282 tree = t.render_include_tree()
283 if tree:
284 print
285 print tree
286 SCons.Taskmaster.Task.postprocess(self)
287
289 """Make a task ready for execution"""
290 SCons.Taskmaster.Task.make_ready(self)
291 if self.out_of_date and self.options.debug_explain:
292 explanation = self.out_of_date[0].explain()
293 if explanation:
294 sys.stdout.write("scons: " + explanation)
295
371
373 """An SCons task for the -q (question) option."""
376
383
386
387
390 self.derived = derived
391 self.prune = prune
392 self.status = status
405
406
409
411 return version < (1, 5, 2)
412
414 return version < (2, 2, 0)
415
416
417
418
419 print_objects = 0
420 print_memoizer = 0
421 print_stacktrace = 0
422 print_time = 0
423 sconscript_time = 0
424 cumulative_command_time = 0
425 exit_status = 0
426 num_jobs = None
427 delayed_warnings = []
428
430 """
431 A do-nothing option parser, used for the initial OptionsParser variable.
432
433 During normal SCons operation, the OptionsParser is created right
434 away by the main() function. Certain tests scripts however, can
435 introspect on different Tool modules, the initialization of which
436 can try to add a new, local option to an otherwise uninitialized
437 OptionsParser object. This allows that introspection to happen
438 without blowing up.
439
440 """
444 values = FakeOptionValues()
447
448 OptionsParser = FakeOptionParser()
449
455
458
461
462
475
481 stats_table = {}
482 for s in self.stats:
483 for n in map(lambda t: t[0], s):
484 stats_table[n] = [0, 0, 0, 0]
485 i = 0
486 for s in self.stats:
487 for n, c in s:
488 stats_table[n][i] = c
489 i = i + 1
490 keys = stats_table.keys()
491 keys.sort()
492 self.outfp.write("Object counts:\n")
493 pre = [" "]
494 post = [" %s\n"]
495 l = len(self.stats)
496 fmt1 = string.join(pre + [' %7s']*l + post, '')
497 fmt2 = string.join(pre + [' %7d']*l + post, '')
498 labels = self.labels[:l]
499 labels.append(("", "Class"))
500 self.outfp.write(fmt1 % tuple(map(lambda x: x[0], labels)))
501 self.outfp.write(fmt1 % tuple(map(lambda x: x[1], labels)))
502 for k in keys:
503 r = stats_table[k][:l] + [k]
504 self.outfp.write(fmt2 % tuple(r))
505
506 count_stats = CountStats()
507
513 fmt = 'Memory %-32s %12d\n'
514 for label, stats in map(None, self.labels, self.stats):
515 self.outfp.write(fmt % (label, stats))
516
517 memory_stats = MemStats()
518
519
520
522 """Handle syntax errors. Print out a message and show where the error
523 occurred.
524 """
525 etype, value, tb = sys.exc_info()
526 lines = traceback.format_exception_only(etype, value)
527 for line in lines:
528 sys.stderr.write(line+'\n')
529 sys.exit(2)
530
532 """
533 Find the deepest stack frame that is not part of SCons.
534
535 Input is a "pre-processed" stack trace in the form
536 returned by traceback.extract_tb() or traceback.extract_stack()
537 """
538
539 tb.reverse()
540
541
542
543 for frame in tb:
544 filename = frame[0]
545 if string.find(filename, os.sep+'SCons'+os.sep) == -1:
546 return frame
547 return tb[0]
548
550 """Handle user errors. Print out a message and a description of the
551 error, along with the line number and routine where it occured.
552 The file and line number will be the deepest stack frame that is
553 not part of SCons itself.
554 """
555 global print_stacktrace
556 etype, value, tb = sys.exc_info()
557 if print_stacktrace:
558 traceback.print_exception(etype, value, tb)
559 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
560 sys.stderr.write("\nscons: *** %s\n" % value)
561 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
562 sys.exit(2)
563
565 """Handle user warnings. Print out a message and a description of
566 the warning, along with the line number and routine where it occured.
567 The file and line number will be the deepest stack frame that is
568 not part of SCons itself.
569 """
570 etype, value, tb = sys.exc_info()
571 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
572 sys.stderr.write("\nscons: warning: %s\n" % e)
573 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
574
576 """Slightly different from _scons_user_warning in that we use the
577 *current call stack* rather than sys.exc_info() to get our stack trace.
578 This is used by the warnings framework to print warnings."""
579 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_stack())
580 sys.stderr.write("\nscons: warning: %s\n" % e[0])
581 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
582
584 """Handle all errors but user errors. Print out a message telling
585 the user what to do in this case and print a normal trace.
586 """
587 print 'internal error'
588 traceback.print_exc()
589 sys.exit(2)
590
592 """This function checks that an SConstruct file exists in a directory.
593 If so, it returns the path of the file. By default, it checks the
594 current directory.
595 """
596 for file in ['SConstruct', 'Sconstruct', 'sconstruct']:
597 sfile = os.path.join(dirname, file)
598 if os.path.isfile(sfile):
599 return sfile
600 if not os.path.isabs(sfile):
601 for rep in repositories:
602 if os.path.isfile(os.path.join(rep, sfile)):
603 return sfile
604 return None
605
644
653
655 """Load the site_scons dir under topdir.
656 Adds site_scons to sys.path, imports site_scons/site_init.py,
657 and adds site_scons/site_tools to default toolpath."""
658 if site_dir_name:
659 err_if_not_found = True
660 else:
661 site_dir_name = "site_scons"
662 err_if_not_found = False
663
664 site_dir = os.path.join(topdir.path, site_dir_name)
665 if not os.path.exists(site_dir):
666 if err_if_not_found:
667 raise SCons.Errors.UserError, "site dir %s not found."%site_dir
668 return
669
670 site_init_filename = "site_init.py"
671 site_init_modname = "site_init"
672 site_tools_dirname = "site_tools"
673 sys.path = [os.path.abspath(site_dir)] + sys.path
674 site_init_file = os.path.join(site_dir, site_init_filename)
675 site_tools_dir = os.path.join(site_dir, site_tools_dirname)
676 if os.path.exists(site_init_file):
677 import imp
678 try:
679 fp, pathname, description = imp.find_module(site_init_modname,
680 [site_dir])
681 try:
682 imp.load_module(site_init_modname, fp, pathname, description)
683 finally:
684 if fp:
685 fp.close()
686 except ImportError, e:
687 sys.stderr.write("Can't import site init file '%s': %s\n"%(site_init_file, e))
688 raise
689 except Exception, e:
690 sys.stderr.write("Site init file '%s' raised exception: %s\n"%(site_init_file, e))
691 raise
692 if os.path.exists(site_tools_dir):
693 SCons.Tool.DefaultToolpath.append(os.path.abspath(site_tools_dir))
694
708
710 global exit_status
711
712 options = parser.values
713
714
715
716
717
718
719
720
721 default_warnings = [ SCons.Warnings.CorruptSConsignWarning,
722 SCons.Warnings.DeprecatedWarning,
723 SCons.Warnings.DuplicateEnvironmentWarning,
724 SCons.Warnings.MissingSConscriptWarning,
725 SCons.Warnings.NoMD5ModuleWarning,
726 SCons.Warnings.NoMetaclassSupportWarning,
727 SCons.Warnings.NoObjectCountWarning,
728 SCons.Warnings.NoParallelSupportWarning,
729 SCons.Warnings.MisleadingKeywordsWarning,
730 SCons.Warnings.StackSizeWarning, ]
731 for warning in default_warnings:
732 SCons.Warnings.enableWarningClass(warning)
733 SCons.Warnings._warningOut = _scons_internal_warning
734 SCons.Warnings.process_warn_strings(options.warn)
735
736
737
738
739 try:
740 dw = options.delayed_warnings
741 except AttributeError:
742 pass
743 else:
744 delayed_warnings.extend(dw)
745 for warning_type, message in delayed_warnings:
746 SCons.Warnings.warn(warning_type, message)
747
748 if options.diskcheck:
749 SCons.Node.FS.set_diskcheck(options.diskcheck)
750
751
752
753
754
755
756 if options.directory:
757 cdir = _create_path(options.directory)
758 try:
759 os.chdir(cdir)
760 except OSError:
761 sys.stderr.write("Could not change directory to %s\n" % cdir)
762
763 target_top = None
764 if options.climb_up:
765 target_top = '.'
766 script_dir = os.getcwd()
767 while script_dir and not _SConstruct_exists(script_dir, options.repository):
768 script_dir, last_part = os.path.split(script_dir)
769 if last_part:
770 target_top = os.path.join(last_part, target_top)
771 else:
772 script_dir = ''
773 if script_dir:
774 display("scons: Entering directory `%s'" % script_dir)
775 os.chdir(script_dir)
776
777
778
779
780 fs = SCons.Node.FS.get_default_fs()
781
782 for rep in options.repository:
783 fs.Repository(rep)
784
785
786
787
788 scripts = []
789 if options.file:
790 scripts.extend(options.file)
791 if not scripts:
792 sfile = _SConstruct_exists(repositories=options.repository)
793 if sfile:
794 scripts.append(sfile)
795
796 if not scripts:
797 if options.help:
798
799
800
801 raise SConsPrintHelpException
802 raise SCons.Errors.UserError, "No SConstruct file found."
803
804 if scripts[0] == "-":
805 d = fs.getcwd()
806 else:
807 d = fs.File(scripts[0]).dir
808 fs.set_SConstruct_dir(d)
809
810 _set_debug_values(options)
811 SCons.Node.implicit_cache = options.implicit_cache
812 SCons.Node.implicit_deps_changed = options.implicit_deps_changed
813 SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged
814
815 if options.no_exec:
816 SCons.SConf.dryrun = 1
817 SCons.Action.execute_actions = None
818 if options.question:
819 SCons.SConf.dryrun = 1
820 if options.clean:
821 SCons.SConf.SetBuildType('clean')
822 if options.help:
823 SCons.SConf.SetBuildType('help')
824 SCons.SConf.SetCacheMode(options.config)
825 SCons.SConf.SetProgressDisplay(progress_display)
826
827 if options.no_progress or options.silent:
828 progress_display.set_mode(0)
829
830 if options.site_dir:
831 _load_site_scons_dir(d, options.site_dir)
832 elif not options.no_site_dir:
833 _load_site_scons_dir(d)
834
835 if options.include_dir:
836 sys.path = options.include_dir + sys.path
837
838
839
840
841 targets = []
842 xmit_args = []
843 for a in parser.largs:
844 if a[0] == '-':
845 continue
846 if '=' in a:
847 xmit_args.append(a)
848 else:
849 targets.append(a)
850 SCons.Script._Add_Targets(targets + parser.rargs)
851 SCons.Script._Add_Arguments(xmit_args)
852
853
854
855
856
857
858
859
860
861 if not sys.stdout.isatty():
862 sys.stdout = SCons.Util.Unbuffered(sys.stdout)
863 if not sys.stderr.isatty():
864 sys.stderr = SCons.Util.Unbuffered(sys.stderr)
865
866 memory_stats.append('before reading SConscript files:')
867 count_stats.append(('pre-', 'read'))
868
869
870
871 progress_display("scons: Reading SConscript files ...")
872
873 start_time = time.time()
874 try:
875 for script in scripts:
876 SCons.Script._SConscript._SConscript(fs, script)
877 except SCons.Errors.StopError, e:
878
879
880
881
882
883 sys.stderr.write("scons: *** %s Stop.\n" % e)
884 exit_status = 2
885 sys.exit(exit_status)
886 global sconscript_time
887 sconscript_time = time.time() - start_time
888
889 progress_display("scons: done reading SConscript files.")
890
891 memory_stats.append('after reading SConscript files:')
892 count_stats.append(('post-', 'read'))
893
894
895
896
897
898
899
900
901
902 SCons.Warnings.enableWarningClass(SCons.Warnings.PythonVersionWarning)
903 SCons.Warnings.process_warn_strings(options.warn)
904
905
906
907
908 if python_version_deprecated():
909 msg = "Support for pre-2.2 Python (%s) is deprecated.\n" + \
910 " If this will cause hardship, contact dev@scons.tigris.org."
911 SCons.Warnings.warn(SCons.Warnings.PythonVersionWarning,
912 msg % python_version_string())
913
914 if not options.help:
915 SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
916
917
918
919
920
921
922
923 parser.preserve_unknown_options = False
924 parser.parse_args(parser.largs, options)
925
926 if options.help:
927 help_text = SCons.Script.help_text
928 if help_text is None:
929
930
931 raise SConsPrintHelpException
932 else:
933 print help_text
934 print "Use scons -H for help about command-line options."
935 exit_status = 0
936 return
937
938
939
940
941
942
943
944 fs.chdir(fs.Top)
945
946 SCons.Node.FS.save_strings(1)
947
948
949
950 SCons.Node.implicit_cache = options.implicit_cache
951 SCons.Node.FS.set_duplicate(options.duplicate)
952 fs.set_max_drift(options.max_drift)
953 if not options.stack_size is None:
954 SCons.Job.stack_size = options.stack_size
955
956 platform = SCons.Platform.platform_module()
957
958 if options.interactive:
959 SCons.Script.Interactive.interact(fs, OptionsParser, options,
960 targets, target_top)
961
962 else:
963
964
965 nodes = _build_targets(fs, options, targets, target_top)
966 if not nodes:
967 exit_status = 2
968
1032 d = filter(check_dir, SCons.Script.DEFAULT_TARGETS)
1033 SCons.Script.DEFAULT_TARGETS[:] = d
1034 target_top = None
1035 lookup_top = None
1036
1037 targets = SCons.Script._Get_Default_Targets(d, fs)
1038
1039 if not targets:
1040 sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n")
1041 return None
1042
1043 def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
1044 if isinstance(x, SCons.Node.Node):
1045 node = x
1046 else:
1047 node = None
1048
1049 if ltop == None: ltop = ''
1050
1051
1052
1053 curdir = os.path.join(os.getcwd(), str(ltop))
1054 for lookup in SCons.Node.arg2nodes_lookups:
1055 node = lookup(x, curdir=curdir)
1056 if node != None:
1057 break
1058 if node is None:
1059 node = fs.Entry(x, directory=ltop, create=1)
1060 if ttop and not node.is_under(ttop):
1061 if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node):
1062 node = ttop
1063 else:
1064 node = None
1065 return node
1066
1067 nodes = filter(None, map(Entry, targets))
1068
1069 task_class = BuildTask
1070 opening_message = "Building targets ..."
1071 closing_message = "done building targets."
1072 if options.keep_going:
1073 failure_message = "done building targets (errors occurred during build)."
1074 else:
1075 failure_message = "building terminated because of errors."
1076 if options.question:
1077 task_class = QuestionTask
1078 try:
1079 if options.clean:
1080 task_class = CleanTask
1081 opening_message = "Cleaning targets ..."
1082 closing_message = "done cleaning targets."
1083 if options.keep_going:
1084 failure_message = "done cleaning targets (errors occurred during clean)."
1085 else:
1086 failure_message = "cleaning terminated because of errors."
1087 except AttributeError:
1088 pass
1089
1090 task_class.progress = ProgressObject
1091
1092 if options.random:
1093 def order(dependencies):
1094 """Randomize the dependencies."""
1095 import random
1096
1097
1098 d = dependencies
1099 for i in xrange(len(d)-1, 0, -1):
1100 j = int(random.random() * (i+1))
1101 d[i], d[j] = d[j], d[i]
1102 return d
1103 else:
1104 def order(dependencies):
1105 """Leave the order of dependencies alone."""
1106 return dependencies
1107
1108 if options.taskmastertrace_file == '-':
1109 tmtrace = sys.stdout
1110 elif options.taskmastertrace_file:
1111 tmtrace = open(options.taskmastertrace_file, 'wb')
1112 else:
1113 tmtrace = None
1114 taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order, tmtrace)
1115
1116
1117
1118 BuildTask.options = options
1119
1120 global num_jobs
1121 num_jobs = options.num_jobs
1122 jobs = SCons.Job.Jobs(num_jobs, taskmaster)
1123 if num_jobs > 1:
1124 msg = None
1125 if jobs.num_jobs == 1:
1126 msg = "parallel builds are unsupported by this version of Python;\n" + \
1127 "\tignoring -j or num_jobs option.\n"
1128 elif sys.platform == 'win32':
1129 msg = fetch_win32_parallel_msg()
1130 if msg:
1131 SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
1132
1133 memory_stats.append('before building targets:')
1134 count_stats.append(('pre-', 'build'))
1135
1136 try:
1137 progress_display("scons: " + opening_message)
1138 try:
1139 jobs.run()
1140 except KeyboardInterrupt:
1141
1142
1143
1144 if options.interactive:
1145 print "Build interrupted."
1146
1147 finally:
1148 jobs.cleanup()
1149 if exit_status:
1150 progress_display("scons: " + failure_message)
1151 else:
1152 progress_display("scons: " + closing_message)
1153 if not options.no_exec:
1154 SCons.SConsign.write()
1155
1156 memory_stats.append('after building targets:')
1157 count_stats.append(('post-', 'build'))
1158
1159 return nodes
1160
1161 -def _exec_main(parser, values):
1162 sconsflags = os.environ.get('SCONSFLAGS', '')
1163 all_args = string.split(sconsflags) + sys.argv[1:]
1164
1165 options, args = parser.parse_args(all_args, values)
1166
1167 if type(options.debug) == type([]) and "pdb" in options.debug:
1168 import pdb
1169 pdb.Pdb().runcall(_main, parser)
1170 elif options.profile_file:
1171 from profile import Profile
1172
1173
1174
1175
1176
1177
1178 try:
1179 dispatch = Profile.dispatch
1180 except AttributeError:
1181 pass
1182 else:
1183 dispatch['c_exception'] = Profile.trace_dispatch_return
1184
1185 prof = Profile()
1186 try:
1187 prof.runcall(_main, parser)
1188 except SConsPrintHelpException, e:
1189 prof.dump_stats(options.profile_file)
1190 raise e
1191 except SystemExit:
1192 pass
1193 prof.dump_stats(options.profile_file)
1194 else:
1195 _main(parser)
1196
1198 global OptionsParser
1199 global exit_status
1200 global first_command_start
1201
1202
1203
1204
1205
1206 if python_version_unsupported():
1207 msg = "scons: *** SCons version %s does not run under Python version %s.\n"
1208 sys.stderr.write(msg % (SCons.__version__, python_version_string()))
1209 sys.exit(1)
1210
1211 parts = ["SCons by Steven Knight et al.:\n"]
1212 try:
1213 parts.append(version_string("script", __main__))
1214 except KeyboardInterrupt:
1215 raise
1216 except:
1217
1218
1219 pass
1220 parts.append(version_string("engine", SCons))
1221 parts.append("Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation")
1222 version = string.join(parts, '')
1223
1224 import SConsOptions
1225 parser = SConsOptions.Parser(version)
1226 values = SConsOptions.SConsValues(parser.get_default_values())
1227
1228 OptionsParser = parser
1229
1230 try:
1231 _exec_main(parser, values)
1232 except SystemExit, s:
1233 if s:
1234 exit_status = s
1235 except KeyboardInterrupt:
1236 print "Build interrupted."
1237 sys.exit(2)
1238 except SyntaxError, e:
1239 _scons_syntax_error(e)
1240 except SCons.Errors.InternalError:
1241 _scons_internal_error()
1242 except SCons.Errors.UserError, e:
1243 _scons_user_error(e)
1244 except SConsPrintHelpException:
1245 parser.print_help()
1246 exit_status = 0
1247 except:
1248
1249
1250
1251 SCons.Script._SConscript.SConscript_exception()
1252 sys.exit(2)
1253
1254 memory_stats.print_stats()
1255 count_stats.print_stats()
1256
1257 if print_objects:
1258 SCons.Debug.listLoggedInstances('*')
1259
1260
1261 if print_memoizer:
1262 SCons.Memoize.Dump("Memoizer (memory cache) hits and misses:")
1263
1264
1265
1266
1267
1268 SCons.Debug.dump_caller_counts()
1269 SCons.Taskmaster.dump_stats()
1270
1271 if print_time:
1272 total_time = time.time() - SCons.Script.start_time
1273 if num_jobs == 1:
1274 ct = cumulative_command_time
1275 else:
1276 if last_command_end is None or first_command_start is None:
1277 ct = 0.0
1278 else:
1279 ct = last_command_end - first_command_start
1280 scons_time = total_time - sconscript_time - ct
1281 print "Total build time: %f seconds"%total_time
1282 print "Total SConscript file execution time: %f seconds"%sconscript_time
1283 print "Total SCons execution time: %f seconds"%scons_time
1284 print "Total command execution time: %f seconds"%ct
1285
1286 sys.exit(exit_status)
1287