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