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 3842 2008/12/20 22:59:52 scons"
38
39 import os
40 import os.path
41 import string
42 import sys
43 import time
44 import traceback
45
46
47
48
49
50
51
52
53
54
55 import SCons.CacheDir
56 import SCons.Debug
57 import SCons.Defaults
58 import SCons.Environment
59 import SCons.Errors
60 import SCons.Job
61 import SCons.Node
62 import SCons.Node.FS
63 import SCons.SConf
64 import SCons.Script
65 import SCons.Taskmaster
66 import SCons.Util
67 import SCons.Warnings
68
69 import SCons.Script.Interactive
70
80
81
82
85
86 display = SCons.Util.display
87 progress_display = SCons.Util.DisplayEngine()
88
89 first_command_start = None
90 last_command_end = None
91
93 prev = ''
94 count = 0
95 target_string = '$TARGET'
96
98 if file is None:
99 file = sys.stdout
100
101 self.obj = obj
102 self.file = file
103 self.interval = interval
104 self.overwrite = overwrite
105
106 if callable(obj):
107 self.func = obj
108 elif SCons.Util.is_List(obj):
109 self.func = self.spinner
110 elif string.find(obj, self.target_string) != -1:
111 self.func = self.replace_string
112 else:
113 self.func = self.string
114
119
121 if self.prev:
122 length = len(self.prev)
123 if self.prev[-1] in ('\n', '\r'):
124 length = length - 1
125 self.write(' ' * length + '\r')
126 self.prev = ''
127
129 self.write(self.obj[self.count % len(self.obj)])
130
133
136
143
144 ProgressObject = SCons.Util.Null()
145
149
150
151
152
153 _BuildFailures = []
154
157
159 """An SCons build task."""
160 progress = ProgressObject
161
164
168
177
192
207
229
231
232
233
234 exc_info = self.exc_info()
235 try:
236 t, e, tb = exc_info
237 except ValueError:
238 t, e = exc_info
239 tb = None
240
241 if t is None:
242
243
244 try:
245 t, e, tb = sys.exc_info()[:]
246 except ValueError:
247 t, e = exc_info
248 tb = None
249
250
251
252 if e is None:
253 e = t
254
255 buildError = SCons.Errors.convert_to_BuildError(e)
256 if not buildError.node:
257 buildError.node = self.node
258
259 node = buildError.node
260 if not SCons.Util.is_List(node):
261 node = [ node ]
262 nodename = string.join(map(str, node), ', ')
263
264 errfmt = "scons: *** [%s] %s\n"
265 sys.stderr.write(errfmt % (nodename, buildError))
266
267 if (buildError.exc_info[2] and buildError.exc_info[1] and
268
269
270
271
272 not isinstance(buildError.exc_info[1], EnvironmentError) and
273 not isinstance(buildError.exc_info[1], SCons.Errors.StopError) and
274 not isinstance(buildError.exc_info[1], SCons.Errors.UserError)):
275 type, value, trace = buildError.exc_info
276 traceback.print_exception(type, value, trace)
277 elif tb and print_stacktrace:
278 sys.stderr.write("scons: internal stack trace:\n")
279 traceback.print_tb(tb, file=sys.stderr)
280
281 self.exception = (e, buildError, tb)
282 self.do_failed(buildError.exitstatus)
283
284 self.exc_clear()
285
286 - def postprocess(self):
287 if self.top:
288 t = self.targets[0]
289 for tp in self.options.tree_printers:
290 tp.display(t)
291 if self.options.debug_includes:
292 tree = t.render_include_tree()
293 if tree:
294 print
295 print tree
296 SCons.Taskmaster.Task.postprocess(self)
297
299 """Make a task ready for execution"""
300 SCons.Taskmaster.Task.make_ready(self)
301 if self.out_of_date and self.options.debug_explain:
302 explanation = self.out_of_date[0].explain()
303 if explanation:
304 sys.stdout.write("scons: " + explanation)
305
381
383 """An SCons task for the -q (question) option."""
386
395
398
399
402 self.derived = derived
403 self.prune = prune
404 self.status = status
417
418
421
423 return version < (1, 5, 2)
424
426 return version < (2, 2, 0)
427
428
429
430
431 print_objects = 0
432 print_memoizer = 0
433 print_stacktrace = 0
434 print_time = 0
435 sconscript_time = 0
436 cumulative_command_time = 0
437 exit_status = 0
438 this_build_status = 0
439 num_jobs = None
440 delayed_warnings = []
441
443 """
444 A do-nothing option parser, used for the initial OptionsParser variable.
445
446 During normal SCons operation, the OptionsParser is created right
447 away by the main() function. Certain tests scripts however, can
448 introspect on different Tool modules, the initialization of which
449 can try to add a new, local option to an otherwise uninitialized
450 OptionsParser object. This allows that introspection to happen
451 without blowing up.
452
453 """
457 values = FakeOptionValues()
460
461 OptionsParser = FakeOptionParser()
462
468
471
474
475
488
494 stats_table = {}
495 for s in self.stats:
496 for n in map(lambda t: t[0], s):
497 stats_table[n] = [0, 0, 0, 0]
498 i = 0
499 for s in self.stats:
500 for n, c in s:
501 stats_table[n][i] = c
502 i = i + 1
503 keys = stats_table.keys()
504 keys.sort()
505 self.outfp.write("Object counts:\n")
506 pre = [" "]
507 post = [" %s\n"]
508 l = len(self.stats)
509 fmt1 = string.join(pre + [' %7s']*l + post, '')
510 fmt2 = string.join(pre + [' %7d']*l + post, '')
511 labels = self.labels[:l]
512 labels.append(("", "Class"))
513 self.outfp.write(fmt1 % tuple(map(lambda x: x[0], labels)))
514 self.outfp.write(fmt1 % tuple(map(lambda x: x[1], labels)))
515 for k in keys:
516 r = stats_table[k][:l] + [k]
517 self.outfp.write(fmt2 % tuple(r))
518
519 count_stats = CountStats()
520
526 fmt = 'Memory %-32s %12d\n'
527 for label, stats in map(None, self.labels, self.stats):
528 self.outfp.write(fmt % (label, stats))
529
530 memory_stats = MemStats()
531
532
533
535 """Handle syntax errors. Print out a message and show where the error
536 occurred.
537 """
538 etype, value, tb = sys.exc_info()
539 lines = traceback.format_exception_only(etype, value)
540 for line in lines:
541 sys.stderr.write(line+'\n')
542 sys.exit(2)
543
545 """
546 Find the deepest stack frame that is not part of SCons.
547
548 Input is a "pre-processed" stack trace in the form
549 returned by traceback.extract_tb() or traceback.extract_stack()
550 """
551
552 tb.reverse()
553
554
555
556 for frame in tb:
557 filename = frame[0]
558 if string.find(filename, os.sep+'SCons'+os.sep) == -1:
559 return frame
560 return tb[0]
561
563 """Handle user errors. Print out a message and a description of the
564 error, along with the line number and routine where it occured.
565 The file and line number will be the deepest stack frame that is
566 not part of SCons itself.
567 """
568 global print_stacktrace
569 etype, value, tb = sys.exc_info()
570 if print_stacktrace:
571 traceback.print_exception(etype, value, tb)
572 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
573 sys.stderr.write("\nscons: *** %s\n" % value)
574 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
575 sys.exit(2)
576
578 """Handle user warnings. Print out a message and a description of
579 the warning, along with the line number and routine where it occured.
580 The file and line number will be the deepest stack frame that is
581 not part of SCons itself.
582 """
583 etype, value, tb = sys.exc_info()
584 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
585 sys.stderr.write("\nscons: warning: %s\n" % e)
586 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
587
589 """Slightly different from _scons_user_warning in that we use the
590 *current call stack* rather than sys.exc_info() to get our stack trace.
591 This is used by the warnings framework to print warnings."""
592 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_stack())
593 sys.stderr.write("\nscons: warning: %s\n" % e[0])
594 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
595
597 """Handle all errors but user errors. Print out a message telling
598 the user what to do in this case and print a normal trace.
599 """
600 print 'internal error'
601 traceback.print_exc()
602 sys.exit(2)
603
605 """This function checks that an SConstruct file exists in a directory.
606 If so, it returns the path of the file. By default, it checks the
607 current directory.
608 """
609 if not filelist:
610 filelist = ['SConstruct', 'Sconstruct', 'sconstruct']
611 for file in filelist:
612 sfile = os.path.join(dirname, file)
613 if os.path.isfile(sfile):
614 return sfile
615 if not os.path.isabs(sfile):
616 for rep in repositories:
617 if os.path.isfile(os.path.join(rep, sfile)):
618 return sfile
619 return None
620
659
668
670 """Load the site_scons dir under topdir.
671 Adds site_scons to sys.path, imports site_scons/site_init.py,
672 and adds site_scons/site_tools to default toolpath."""
673 if site_dir_name:
674 err_if_not_found = True
675 else:
676 site_dir_name = "site_scons"
677 err_if_not_found = False
678
679 site_dir = os.path.join(topdir.path, site_dir_name)
680 if not os.path.exists(site_dir):
681 if err_if_not_found:
682 raise SCons.Errors.UserError, "site dir %s not found."%site_dir
683 return
684
685 site_init_filename = "site_init.py"
686 site_init_modname = "site_init"
687 site_tools_dirname = "site_tools"
688 sys.path = [os.path.abspath(site_dir)] + sys.path
689 site_init_file = os.path.join(site_dir, site_init_filename)
690 site_tools_dir = os.path.join(site_dir, site_tools_dirname)
691 if os.path.exists(site_init_file):
692 import imp
693 try:
694 fp, pathname, description = imp.find_module(site_init_modname,
695 [site_dir])
696 try:
697 imp.load_module(site_init_modname, fp, pathname, description)
698 finally:
699 if fp:
700 fp.close()
701 except ImportError, e:
702 sys.stderr.write("Can't import site init file '%s': %s\n"%(site_init_file, e))
703 raise
704 except Exception, e:
705 sys.stderr.write("Site init file '%s' raised exception: %s\n"%(site_init_file, e))
706 raise
707 if os.path.exists(site_tools_dir):
708 SCons.Tool.DefaultToolpath.append(os.path.abspath(site_tools_dir))
709
723
725 global exit_status
726 global this_build_status
727
728 options = parser.values
729
730
731
732
733
734
735
736
737 default_warnings = [ SCons.Warnings.CorruptSConsignWarning,
738 SCons.Warnings.DeprecatedWarning,
739 SCons.Warnings.DuplicateEnvironmentWarning,
740 SCons.Warnings.FutureReservedVariableWarning,
741 SCons.Warnings.LinkWarning,
742 SCons.Warnings.MissingSConscriptWarning,
743 SCons.Warnings.NoMD5ModuleWarning,
744 SCons.Warnings.NoMetaclassSupportWarning,
745 SCons.Warnings.NoObjectCountWarning,
746 SCons.Warnings.NoParallelSupportWarning,
747 SCons.Warnings.MisleadingKeywordsWarning,
748 SCons.Warnings.ReservedVariableWarning,
749 SCons.Warnings.StackSizeWarning,
750 ]
751
752 for warning in default_warnings:
753 SCons.Warnings.enableWarningClass(warning)
754 SCons.Warnings._warningOut = _scons_internal_warning
755 SCons.Warnings.process_warn_strings(options.warn)
756
757
758
759
760 try:
761 dw = options.delayed_warnings
762 except AttributeError:
763 pass
764 else:
765 delayed_warnings.extend(dw)
766 for warning_type, message in delayed_warnings:
767 SCons.Warnings.warn(warning_type, message)
768
769 if options.diskcheck:
770 SCons.Node.FS.set_diskcheck(options.diskcheck)
771
772
773
774
775
776
777 if options.directory:
778 cdir = _create_path(options.directory)
779 try:
780 os.chdir(cdir)
781 except OSError:
782 sys.stderr.write("Could not change directory to %s\n" % cdir)
783
784 target_top = None
785 if options.climb_up:
786 target_top = '.'
787 script_dir = os.getcwd()
788 while script_dir and not _SConstruct_exists(script_dir,
789 options.repository,
790 options.file):
791 script_dir, last_part = os.path.split(script_dir)
792 if last_part:
793 target_top = os.path.join(last_part, target_top)
794 else:
795 script_dir = ''
796 if script_dir and script_dir != os.getcwd():
797 display("scons: Entering directory `%s'" % script_dir)
798 os.chdir(script_dir)
799
800
801
802
803 fs = SCons.Node.FS.get_default_fs()
804
805 for rep in options.repository:
806 fs.Repository(rep)
807
808
809
810
811 scripts = []
812 if options.file:
813 scripts.extend(options.file)
814 if not scripts:
815 sfile = _SConstruct_exists(repositories=options.repository,
816 filelist=options.file)
817 if sfile:
818 scripts.append(sfile)
819
820 if not scripts:
821 if options.help:
822
823
824
825 raise SConsPrintHelpException
826 raise SCons.Errors.UserError, "No SConstruct file found."
827
828 if scripts[0] == "-":
829 d = fs.getcwd()
830 else:
831 d = fs.File(scripts[0]).dir
832 fs.set_SConstruct_dir(d)
833
834 _set_debug_values(options)
835 SCons.Node.implicit_cache = options.implicit_cache
836 SCons.Node.implicit_deps_changed = options.implicit_deps_changed
837 SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged
838
839 if options.no_exec:
840 SCons.SConf.dryrun = 1
841 SCons.Action.execute_actions = None
842 if options.question:
843 SCons.SConf.dryrun = 1
844 if options.clean:
845 SCons.SConf.SetBuildType('clean')
846 if options.help:
847 SCons.SConf.SetBuildType('help')
848 SCons.SConf.SetCacheMode(options.config)
849 SCons.SConf.SetProgressDisplay(progress_display)
850
851 if options.no_progress or options.silent:
852 progress_display.set_mode(0)
853
854 if options.site_dir:
855 _load_site_scons_dir(d, options.site_dir)
856 elif not options.no_site_dir:
857 _load_site_scons_dir(d)
858
859 if options.include_dir:
860 sys.path = options.include_dir + sys.path
861
862
863
864
865 targets = []
866 xmit_args = []
867 for a in parser.largs:
868 if a[0] == '-':
869 continue
870 if '=' in a:
871 xmit_args.append(a)
872 else:
873 targets.append(a)
874 SCons.Script._Add_Targets(targets + parser.rargs)
875 SCons.Script._Add_Arguments(xmit_args)
876
877
878
879
880
881
882
883
884
885 if not sys.stdout.isatty():
886 sys.stdout = SCons.Util.Unbuffered(sys.stdout)
887 if not sys.stderr.isatty():
888 sys.stderr = SCons.Util.Unbuffered(sys.stderr)
889
890 memory_stats.append('before reading SConscript files:')
891 count_stats.append(('pre-', 'read'))
892
893
894
895 progress_display("scons: Reading SConscript files ...")
896
897 start_time = time.time()
898 try:
899 for script in scripts:
900 SCons.Script._SConscript._SConscript(fs, script)
901 except SCons.Errors.StopError, e:
902
903
904
905
906
907 sys.stderr.write("scons: *** %s Stop.\n" % e)
908 exit_status = 2
909 sys.exit(exit_status)
910 global sconscript_time
911 sconscript_time = time.time() - start_time
912
913 progress_display("scons: done reading SConscript files.")
914
915 memory_stats.append('after reading SConscript files:')
916 count_stats.append(('post-', 'read'))
917
918
919
920
921
922
923
924
925
926 SCons.Warnings.enableWarningClass(SCons.Warnings.PythonVersionWarning)
927 SCons.Warnings.process_warn_strings(options.warn)
928
929
930
931
932 if python_version_deprecated():
933 msg = "Support for pre-2.2 Python (%s) is deprecated.\n" + \
934 " If this will cause hardship, contact dev@scons.tigris.org."
935 SCons.Warnings.warn(SCons.Warnings.PythonVersionWarning,
936 msg % python_version_string())
937
938 if not options.help:
939 SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
940
941
942
943
944
945
946
947 parser.preserve_unknown_options = False
948 parser.parse_args(parser.largs, options)
949
950 if options.help:
951 help_text = SCons.Script.help_text
952 if help_text is None:
953
954
955 raise SConsPrintHelpException
956 else:
957 print help_text
958 print "Use scons -H for help about command-line options."
959 exit_status = 0
960 return
961
962
963
964
965
966
967
968 fs.chdir(fs.Top)
969
970 SCons.Node.FS.save_strings(1)
971
972
973
974 SCons.Node.implicit_cache = options.implicit_cache
975 SCons.Node.FS.set_duplicate(options.duplicate)
976 fs.set_max_drift(options.max_drift)
977
978 SCons.Job.explicit_stack_size = options.stack_size
979
980 if options.md5_chunksize:
981 SCons.Node.FS.File.md5_chunksize = options.md5_chunksize
982
983 platform = SCons.Platform.platform_module()
984
985 if options.interactive:
986 SCons.Script.Interactive.interact(fs, OptionsParser, options,
987 targets, target_top)
988
989 else:
990
991
992 nodes = _build_targets(fs, options, targets, target_top)
993 if not nodes:
994 exit_status = 2
995
1058 d = filter(check_dir, SCons.Script.DEFAULT_TARGETS)
1059 SCons.Script.DEFAULT_TARGETS[:] = d
1060 target_top = None
1061 lookup_top = None
1062
1063 targets = SCons.Script._Get_Default_Targets(d, fs)
1064
1065 if not targets:
1066 sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n")
1067 return None
1068
1069 def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
1070 if isinstance(x, SCons.Node.Node):
1071 node = x
1072 else:
1073 node = None
1074
1075 if ltop == None: ltop = ''
1076
1077
1078
1079 curdir = os.path.join(os.getcwd(), str(ltop))
1080 for lookup in SCons.Node.arg2nodes_lookups:
1081 node = lookup(x, curdir=curdir)
1082 if node != None:
1083 break
1084 if node is None:
1085 node = fs.Entry(x, directory=ltop, create=1)
1086 if ttop and not node.is_under(ttop):
1087 if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node):
1088 node = ttop
1089 else:
1090 node = None
1091 return node
1092
1093 nodes = filter(None, map(Entry, targets))
1094
1095 task_class = BuildTask
1096 opening_message = "Building targets ..."
1097 closing_message = "done building targets."
1098 if options.keep_going:
1099 failure_message = "done building targets (errors occurred during build)."
1100 else:
1101 failure_message = "building terminated because of errors."
1102 if options.question:
1103 task_class = QuestionTask
1104 try:
1105 if options.clean:
1106 task_class = CleanTask
1107 opening_message = "Cleaning targets ..."
1108 closing_message = "done cleaning targets."
1109 if options.keep_going:
1110 failure_message = "done cleaning targets (errors occurred during clean)."
1111 else:
1112 failure_message = "cleaning terminated because of errors."
1113 except AttributeError:
1114 pass
1115
1116 task_class.progress = ProgressObject
1117
1118 if options.random:
1119 def order(dependencies):
1120 """Randomize the dependencies."""
1121 import random
1122
1123
1124 d = dependencies
1125 for i in xrange(len(d)-1, 0, -1):
1126 j = int(random.random() * (i+1))
1127 d[i], d[j] = d[j], d[i]
1128 return d
1129 else:
1130 def order(dependencies):
1131 """Leave the order of dependencies alone."""
1132 return dependencies
1133
1134 if options.taskmastertrace_file == '-':
1135 tmtrace = sys.stdout
1136 elif options.taskmastertrace_file:
1137 tmtrace = open(options.taskmastertrace_file, 'wb')
1138 else:
1139 tmtrace = None
1140 taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order, tmtrace)
1141
1142
1143
1144 BuildTask.options = options
1145
1146 global num_jobs
1147 num_jobs = options.num_jobs
1148 jobs = SCons.Job.Jobs(num_jobs, taskmaster)
1149 if num_jobs > 1:
1150 msg = None
1151 if jobs.num_jobs == 1:
1152 msg = "parallel builds are unsupported by this version of Python;\n" + \
1153 "\tignoring -j or num_jobs option.\n"
1154 elif sys.platform == 'win32':
1155 msg = fetch_win32_parallel_msg()
1156 if msg:
1157 SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
1158
1159 memory_stats.append('before building targets:')
1160 count_stats.append(('pre-', 'build'))
1161
1162 def jobs_postfunc(
1163 jobs=jobs,
1164 options=options,
1165 closing_message=closing_message,
1166 failure_message=failure_message
1167 ):
1168 if jobs.were_interrupted():
1169 progress_display("scons: Build interrupted.")
1170 global exit_status
1171 global this_build_status
1172 exit_status = 2
1173 this_build_status = 2
1174
1175 if this_build_status:
1176 progress_display("scons: " + failure_message)
1177 else:
1178 progress_display("scons: " + closing_message)
1179 if not options.no_exec:
1180 if jobs.were_interrupted():
1181 progress_display("scons: writing .sconsign file.")
1182 SCons.SConsign.write()
1183
1184 progress_display("scons: " + opening_message)
1185 jobs.run(postfunc = jobs_postfunc)
1186
1187 memory_stats.append('after building targets:')
1188 count_stats.append(('post-', 'build'))
1189
1190 return nodes
1191
1192 -def _exec_main(parser, values):
1193 sconsflags = os.environ.get('SCONSFLAGS', '')
1194 all_args = string.split(sconsflags) + sys.argv[1:]
1195
1196 options, args = parser.parse_args(all_args, values)
1197
1198 if type(options.debug) == type([]) and "pdb" in options.debug:
1199 import pdb
1200 pdb.Pdb().runcall(_main, parser)
1201 elif options.profile_file:
1202 try:
1203 from cProfile import Profile
1204 except ImportError, e:
1205 from profile import Profile
1206
1207
1208
1209
1210
1211
1212 try:
1213 dispatch = Profile.dispatch
1214 except AttributeError:
1215 pass
1216 else:
1217 dispatch['c_exception'] = Profile.trace_dispatch_return
1218
1219 prof = Profile()
1220 try:
1221 prof.runcall(_main, parser)
1222 except SConsPrintHelpException, e:
1223 prof.dump_stats(options.profile_file)
1224 raise e
1225 except SystemExit:
1226 pass
1227 prof.dump_stats(options.profile_file)
1228 else:
1229 _main(parser)
1230
1232 global OptionsParser
1233 global exit_status
1234 global first_command_start
1235
1236
1237
1238
1239
1240 if python_version_unsupported():
1241 msg = "scons: *** SCons version %s does not run under Python version %s.\n"
1242 sys.stderr.write(msg % (SCons.__version__, python_version_string()))
1243 sys.exit(1)
1244
1245 parts = ["SCons by Steven Knight et al.:\n"]
1246 try:
1247 import __main__
1248 parts.append(version_string("script", __main__))
1249 except (ImportError, AttributeError):
1250
1251
1252 pass
1253 parts.append(version_string("engine", SCons))
1254 parts.append("Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation")
1255 version = string.join(parts, '')
1256
1257 import SConsOptions
1258 parser = SConsOptions.Parser(version)
1259 values = SConsOptions.SConsValues(parser.get_default_values())
1260
1261 OptionsParser = parser
1262
1263 try:
1264 _exec_main(parser, values)
1265 except SystemExit, s:
1266 if s:
1267 exit_status = s
1268 except KeyboardInterrupt:
1269 print("scons: Build interrupted.")
1270 sys.exit(2)
1271 except SyntaxError, e:
1272 _scons_syntax_error(e)
1273 except SCons.Errors.InternalError:
1274 _scons_internal_error()
1275 except SCons.Errors.UserError, e:
1276 _scons_user_error(e)
1277 except SConsPrintHelpException:
1278 parser.print_help()
1279 exit_status = 0
1280 except SCons.Errors.BuildError, e:
1281 exit_status = e.exitstatus
1282 except:
1283
1284
1285
1286 SCons.Script._SConscript.SConscript_exception()
1287 sys.exit(2)
1288
1289 memory_stats.print_stats()
1290 count_stats.print_stats()
1291
1292 if print_objects:
1293 SCons.Debug.listLoggedInstances('*')
1294
1295
1296 if print_memoizer:
1297 SCons.Memoize.Dump("Memoizer (memory cache) hits and misses:")
1298
1299
1300
1301
1302
1303 SCons.Debug.dump_caller_counts()
1304 SCons.Taskmaster.dump_stats()
1305
1306 if print_time:
1307 total_time = time.time() - SCons.Script.start_time
1308 if num_jobs == 1:
1309 ct = cumulative_command_time
1310 else:
1311 if last_command_end is None or first_command_start is None:
1312 ct = 0.0
1313 else:
1314 ct = last_command_end - first_command_start
1315 scons_time = total_time - sconscript_time - ct
1316 print "Total build time: %f seconds"%total_time
1317 print "Total SConscript file execution time: %f seconds"%sconscript_time
1318 print "Total SCons execution time: %f seconds"%scons_time
1319 print "Total command execution time: %f seconds"%ct
1320
1321 sys.exit(exit_status)
1322