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