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, 7, 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 rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog"
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.Platform
64 import SCons.SConf
65 import SCons.Script
66 import SCons.Taskmaster
67 import SCons.Util
68 import SCons.Warnings
69
70 import SCons.Script.Interactive
71
81
83
84
85
86 sys.stderr = sys.__stderr__
87 sys.stdout = sys.__stdout__
88
91
92 display = SCons.Util.display
93 progress_display = SCons.Util.DisplayEngine()
94
95 first_command_start = None
96 last_command_end = None
97
99 prev = ''
100 count = 0
101 target_string = '$TARGET'
102
103 - def __init__(self, obj, interval=1, file=None, overwrite=False):
104 if file is None:
105 file = sys.stdout
106
107 self.obj = obj
108 self.file = file
109 self.interval = interval
110 self.overwrite = overwrite
111
112 if callable(obj):
113 self.func = obj
114 elif SCons.Util.is_List(obj):
115 self.func = self.spinner
116 elif obj.find(self.target_string) != -1:
117 self.func = self.replace_string
118 else:
119 self.func = self.string
120
125
127 if self.prev:
128 length = len(self.prev)
129 if self.prev[-1] in ('\n', '\r'):
130 length = length - 1
131 self.write(' ' * length + '\r')
132 self.prev = ''
133
135 self.write(self.obj[self.count % len(self.obj)])
136
139
142
149
150 ProgressObject = SCons.Util.Null()
151
155
156
157
158
159 _BuildFailures = []
160
163
164 -class BuildTask(SCons.Taskmaster.OutOfDateTask):
165 """An SCons build task."""
166 progress = ProgressObject
167
170
174
181
196
211
236
238
239
240
241 exc_info = self.exc_info()
242 try:
243 t, e, tb = exc_info
244 except ValueError:
245 t, e = exc_info
246 tb = None
247
248 if t is None:
249
250
251 try:
252 t, e, tb = sys.exc_info()[:]
253 except ValueError:
254 t, e = exc_info
255 tb = None
256
257
258
259 if e is None:
260 e = t
261
262 buildError = SCons.Errors.convert_to_BuildError(e)
263 if not buildError.node:
264 buildError.node = self.node
265
266 node = buildError.node
267 if not SCons.Util.is_List(node):
268 node = [ node ]
269 nodename = ', '.join(map(str, node))
270
271 errfmt = "scons: *** [%s] %s\n"
272 sys.stderr.write(errfmt % (nodename, buildError))
273
274 if (buildError.exc_info[2] and buildError.exc_info[1] and
275 not isinstance(
276 buildError.exc_info[1],
277 (EnvironmentError, SCons.Errors.StopError,
278 SCons.Errors.UserError))):
279 type, value, trace = buildError.exc_info
280 if tb and print_stacktrace:
281 sys.stderr.write("scons: internal stack trace:\n")
282 traceback.print_tb(tb, file=sys.stderr)
283 traceback.print_exception(type, value, trace)
284 elif tb and print_stacktrace:
285 sys.stderr.write("scons: internal stack trace:\n")
286 traceback.print_tb(tb, file=sys.stderr)
287
288 self.exception = (e, buildError, tb)
289 self.do_failed(buildError.exitstatus)
290
291 self.exc_clear()
292
293 - def postprocess(self):
294 if self.top:
295 t = self.targets[0]
296 for tp in self.options.tree_printers:
297 tp.display(t)
298 if self.options.debug_includes:
299 tree = t.render_include_tree()
300 if tree:
301 print
302 print tree
303 SCons.Taskmaster.OutOfDateTask.postprocess(self)
304
306 """Make a task ready for execution"""
307 SCons.Taskmaster.OutOfDateTask.make_ready(self)
308 if self.out_of_date and self.options.debug_explain:
309 explanation = self.out_of_date[0].explain()
310 if explanation:
311 sys.stdout.write("scons: " + explanation)
312
313 -class CleanTask(SCons.Taskmaster.AlwaysTask):
393
395 """An SCons task for the -q (question) option."""
398
407
410
411
413 - def __init__(self, derived=False, prune=False, status=False):
414 self.derived = derived
415 self.prune = prune
416 self.status = status
429
430
432 return sys.version.split()[0]
433
436
439
440
441
442
443 print_objects = 0
444 print_memoizer = 0
445 print_stacktrace = 0
446 print_time = 0
447 sconscript_time = 0
448 cumulative_command_time = 0
449 exit_status = 0
450 this_build_status = 0
451 num_jobs = None
452 delayed_warnings = []
453
455 """
456 A do-nothing option parser, used for the initial OptionsParser variable.
457
458 During normal SCons operation, the OptionsParser is created right
459 away by the main() function. Certain tests scripts however, can
460 introspect on different Tool modules, the initialization of which
461 can try to add a new, local option to an otherwise uninitialized
462 OptionsParser object. This allows that introspection to happen
463 without blowing up.
464
465 """
469 values = FakeOptionValues()
472
473 OptionsParser = FakeOptionParser()
474
480
483
486
489
490
503
509 stats_table = {}
510 for s in self.stats:
511 for n in [t[0] for t in s]:
512 stats_table[n] = [0, 0, 0, 0]
513 i = 0
514 for s in self.stats:
515 for n, c in s:
516 stats_table[n][i] = c
517 i = i + 1
518 self.outfp.write("Object counts:\n")
519 pre = [" "]
520 post = [" %s\n"]
521 l = len(self.stats)
522 fmt1 = ''.join(pre + [' %7s']*l + post)
523 fmt2 = ''.join(pre + [' %7d']*l + post)
524 labels = self.labels[:l]
525 labels.append(("", "Class"))
526 self.outfp.write(fmt1 % tuple([x[0] for x in labels]))
527 self.outfp.write(fmt1 % tuple([x[1] for x in labels]))
528 for k in sorted(stats_table.keys()):
529 r = stats_table[k][:l] + [k]
530 self.outfp.write(fmt2 % tuple(r))
531
532 count_stats = CountStats()
533
539 fmt = 'Memory %-32s %12d\n'
540 for label, stats in zip(self.labels, self.stats):
541 self.outfp.write(fmt % (label, stats))
542
543 memory_stats = MemStats()
544
545
546
548 """Handle syntax errors. Print out a message and show where the error
549 occurred.
550 """
551 etype, value, tb = sys.exc_info()
552 lines = traceback.format_exception_only(etype, value)
553 for line in lines:
554 sys.stderr.write(line+'\n')
555 sys.exit(2)
556
558 """
559 Find the deepest stack frame that is not part of SCons.
560
561 Input is a "pre-processed" stack trace in the form
562 returned by traceback.extract_tb() or traceback.extract_stack()
563 """
564
565 tb.reverse()
566
567
568
569 for frame in tb:
570 filename = frame[0]
571 if filename.find(os.sep+'SCons'+os.sep) == -1:
572 return frame
573 return tb[0]
574
576 """Handle user errors. Print out a message and a description of the
577 error, along with the line number and routine where it occured.
578 The file and line number will be the deepest stack frame that is
579 not part of SCons itself.
580 """
581 global print_stacktrace
582 etype, value, tb = sys.exc_info()
583 if print_stacktrace:
584 traceback.print_exception(etype, value, tb)
585 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
586 sys.stderr.write("\nscons: *** %s\n" % value)
587 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
588 sys.exit(2)
589
591 """Handle user warnings. Print out a message and a description of
592 the warning, along with the line number and routine where it occured.
593 The file and line number will be the deepest stack frame that is
594 not part of SCons itself.
595 """
596 etype, value, tb = sys.exc_info()
597 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
598 sys.stderr.write("\nscons: warning: %s\n" % e)
599 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
600
602 """Slightly different from _scons_user_warning in that we use the
603 *current call stack* rather than sys.exc_info() to get our stack trace.
604 This is used by the warnings framework to print warnings."""
605 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_stack())
606 sys.stderr.write("\nscons: warning: %s\n" % e.args[0])
607 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
608
610 """Handle all errors but user errors. Print out a message telling
611 the user what to do in this case and print a normal trace.
612 """
613 print 'internal error'
614 traceback.print_exc()
615 sys.exit(2)
616
618 """This function checks that an SConstruct file exists in a directory.
619 If so, it returns the path of the file. By default, it checks the
620 current directory.
621 """
622 if not filelist:
623 filelist = ['SConstruct', 'Sconstruct', 'sconstruct']
624 for file in filelist:
625 sfile = os.path.join(dirname, file)
626 if os.path.isfile(sfile):
627 return sfile
628 if not os.path.isabs(sfile):
629 for rep in repositories:
630 if os.path.isfile(os.path.join(rep, sfile)):
631 return sfile
632 return None
633
679
688
690 """Load the site_scons dir under topdir.
691 Prepends site_scons to sys.path, imports site_scons/site_init.py,
692 and prepends site_scons/site_tools to default toolpath."""
693 if site_dir_name:
694 err_if_not_found = True
695 else:
696 site_dir_name = "site_scons"
697 err_if_not_found = False
698
699 site_dir = os.path.join(topdir, site_dir_name)
700 if not os.path.exists(site_dir):
701 if err_if_not_found:
702 raise SCons.Errors.UserError("site dir %s not found."%site_dir)
703 return
704
705 site_init_filename = "site_init.py"
706 site_init_modname = "site_init"
707 site_tools_dirname = "site_tools"
708
709 sys.path = [os.path.abspath(site_dir)] + sys.path
710 site_init_file = os.path.join(site_dir, site_init_filename)
711 site_tools_dir = os.path.join(site_dir, site_tools_dirname)
712 if os.path.exists(site_init_file):
713 import imp, re
714
715 try:
716 try:
717 fp, pathname, description = imp.find_module(site_init_modname,
718 [site_dir])
719
720
721
722
723
724
725
726 try:
727 m = sys.modules['SCons.Script']
728 except Exception, e:
729 fmt = 'cannot import site_init.py: missing SCons.Script module %s'
730 raise SCons.Errors.InternalError(fmt % repr(e))
731 try:
732 sfx = description[0]
733 modname = os.path.basename(pathname)[:-len(sfx)]
734 site_m = {"__file__": pathname, "__name__": modname, "__doc__": None}
735 re_special = re.compile("__[^_]+__")
736 for k in m.__dict__.keys():
737 if not re_special.match(k):
738 site_m[k] = m.__dict__[k]
739
740
741 exec fp in site_m
742 except KeyboardInterrupt:
743 raise
744 except Exception, e:
745 fmt = '*** Error loading site_init file %s:\n'
746 sys.stderr.write(fmt % repr(site_init_file))
747 raise
748 else:
749 for k in site_m:
750 if not re_special.match(k):
751 m.__dict__[k] = site_m[k]
752 except KeyboardInterrupt:
753 raise
754 except ImportError, e:
755 fmt = '*** cannot import site init file %s:\n'
756 sys.stderr.write(fmt % repr(site_init_file))
757 raise
758 finally:
759 if fp:
760 fp.close()
761 if os.path.exists(site_tools_dir):
762
763 SCons.Tool.DefaultToolpath.insert(0, os.path.abspath(site_tools_dir))
764
766 """Load all of the predefined site_scons dir.
767 Order is significant; we load them in order from most generic
768 (machine-wide) to most specific (topdir).
769 The verbose argument is only for testing.
770 """
771 platform = SCons.Platform.platform_default()
772
773 def homedir(d):
774 return os.path.expanduser('~/'+d)
775
776 if platform == 'win32' or platform == 'cygwin':
777
778
779
780 sysdirs=[
781 os.path.expandvars('$ALLUSERSPROFILE\\Application Data\\scons'),
782 os.path.expandvars('$USERPROFILE\\Local Settings\\Application Data\\scons')]
783 appdatadir = os.path.expandvars('$APPDATA\\scons')
784 if appdatadir not in sysdirs:
785 sysdirs.append(appdatadir)
786 sysdirs.append(homedir('.scons'))
787
788 elif platform == 'darwin':
789 sysdirs=['/Library/Application Support/SCons',
790 '/opt/local/share/scons',
791 '/sw/share/scons',
792 homedir('Library/Application Support/SCons'),
793 homedir('.scons')]
794 elif platform == 'sunos':
795 sysdirs=['/opt/sfw/scons',
796 '/usr/share/scons',
797 homedir('.scons')]
798 else:
799
800 sysdirs=['/usr/share/scons',
801 homedir('.scons')]
802
803 dirs=sysdirs + [topdir]
804 for d in dirs:
805 if verbose:
806 print "Loading site dir ", d
807 _load_site_scons_dir(d)
808
811
825
827 path = module.__path__
828 return "\t%s path: %s\n"%(label,path)
829
831 global exit_status
832 global this_build_status
833
834 options = parser.values
835
836
837
838
839
840
841
842
843 default_warnings = [ SCons.Warnings.WarningOnByDefault,
844 SCons.Warnings.DeprecatedWarning,
845 ]
846
847 for warning in default_warnings:
848 SCons.Warnings.enableWarningClass(warning)
849 SCons.Warnings._warningOut = _scons_internal_warning
850 SCons.Warnings.process_warn_strings(options.warn)
851
852
853
854
855 try:
856 dw = options.delayed_warnings
857 except AttributeError:
858 pass
859 else:
860 delayed_warnings.extend(dw)
861 for warning_type, message in delayed_warnings:
862 SCons.Warnings.warn(warning_type, message)
863
864 if options.diskcheck:
865 SCons.Node.FS.set_diskcheck(options.diskcheck)
866
867
868
869
870
871
872 if options.directory:
873 script_dir = os.path.abspath(_create_path(options.directory))
874 else:
875 script_dir = os.getcwd()
876
877 target_top = None
878 if options.climb_up:
879 target_top = '.'
880 while script_dir and not _SConstruct_exists(script_dir,
881 options.repository,
882 options.file):
883 script_dir, last_part = os.path.split(script_dir)
884 if last_part:
885 target_top = os.path.join(last_part, target_top)
886 else:
887 script_dir = ''
888
889 if script_dir and script_dir != os.getcwd():
890 if not options.silent:
891 display("scons: Entering directory `%s'" % script_dir)
892 try:
893 os.chdir(script_dir)
894 except OSError:
895 sys.stderr.write("Could not change directory to %s\n" % script_dir)
896
897
898
899
900 fs = SCons.Node.FS.get_default_fs()
901
902 for rep in options.repository:
903 fs.Repository(rep)
904
905
906
907
908 scripts = []
909 if options.file:
910 scripts.extend(options.file)
911 if not scripts:
912 sfile = _SConstruct_exists(repositories=options.repository,
913 filelist=options.file)
914 if sfile:
915 scripts.append(sfile)
916
917 if not scripts:
918 if options.help:
919
920
921
922 raise SConsPrintHelpException
923 raise SCons.Errors.UserError("No SConstruct file found.")
924
925 if scripts[0] == "-":
926 d = fs.getcwd()
927 else:
928 d = fs.File(scripts[0]).dir
929 fs.set_SConstruct_dir(d)
930
931 _set_debug_values(options)
932 SCons.Node.implicit_cache = options.implicit_cache
933 SCons.Node.implicit_deps_changed = options.implicit_deps_changed
934 SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged
935
936 if options.no_exec:
937 SCons.SConf.dryrun = 1
938 SCons.Action.execute_actions = None
939 if options.question:
940 SCons.SConf.dryrun = 1
941 if options.clean:
942 SCons.SConf.SetBuildType('clean')
943 if options.help:
944 SCons.SConf.SetBuildType('help')
945 SCons.SConf.SetCacheMode(options.config)
946 SCons.SConf.SetProgressDisplay(progress_display)
947
948 if options.no_progress or options.silent:
949 progress_display.set_mode(0)
950
951 if options.site_dir:
952 _load_site_scons_dir(d.get_internal_path(), options.site_dir)
953 elif not options.no_site_dir:
954 _load_all_site_scons_dirs(d.get_internal_path())
955
956 if options.include_dir:
957 sys.path = options.include_dir + sys.path
958
959
960
961
962
963
964 if options.interactive:
965 SCons.Node.interactive = True
966
967
968
969
970 targets = []
971 xmit_args = []
972 for a in parser.largs:
973 if a[:1] == '-':
974 continue
975 if '=' in a:
976 xmit_args.append(a)
977 else:
978 targets.append(a)
979 SCons.Script._Add_Targets(targets + parser.rargs)
980 SCons.Script._Add_Arguments(xmit_args)
981
982
983
984
985
986
987
988
989
990 if not hasattr(sys.stdout, 'isatty') or not sys.stdout.isatty():
991 sys.stdout = SCons.Util.Unbuffered(sys.stdout)
992 if not hasattr(sys.stderr, 'isatty') or not sys.stderr.isatty():
993 sys.stderr = SCons.Util.Unbuffered(sys.stderr)
994
995 memory_stats.append('before reading SConscript files:')
996 count_stats.append(('pre-', 'read'))
997
998
999
1000 progress_display("scons: Reading SConscript files ...")
1001
1002 start_time = time.time()
1003 try:
1004 for script in scripts:
1005 SCons.Script._SConscript._SConscript(fs, script)
1006 except SCons.Errors.StopError, e:
1007
1008
1009
1010
1011
1012 revert_io()
1013 sys.stderr.write("scons: *** %s Stop.\n" % e)
1014 sys.exit(2)
1015 global sconscript_time
1016 sconscript_time = time.time() - start_time
1017
1018 progress_display("scons: done reading SConscript files.")
1019
1020 memory_stats.append('after reading SConscript files:')
1021 count_stats.append(('post-', 'read'))
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032 SCons.Warnings.process_warn_strings(options.warn)
1033
1034
1035
1036
1037 if python_version_deprecated():
1038 msg = "Support for pre-%s Python version (%s) is deprecated.\n" + \
1039 " If this will cause hardship, contact scons-dev@scons.org"
1040 deprecated_version_string = ".".join(map(str, deprecated_python_version))
1041 SCons.Warnings.warn(SCons.Warnings.PythonVersionWarning,
1042 msg % (deprecated_version_string, python_version_string()))
1043
1044 if not options.help:
1045
1046
1047
1048 if SCons.SConf.NeedConfigHBuilder():
1049 SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
1050
1051
1052
1053
1054
1055
1056
1057 parser.preserve_unknown_options = False
1058 parser.parse_args(parser.largs, options)
1059
1060 if options.help:
1061 help_text = SCons.Script.help_text
1062 if help_text is None:
1063
1064
1065 raise SConsPrintHelpException
1066 else:
1067 print help_text
1068 print "Use scons -H for help about command-line options."
1069 exit_status = 0
1070 return
1071
1072
1073
1074
1075
1076
1077
1078 fs.chdir(fs.Top)
1079
1080 SCons.Node.FS.save_strings(1)
1081
1082
1083
1084 SCons.Node.implicit_cache = options.implicit_cache
1085 SCons.Node.FS.set_duplicate(options.duplicate)
1086 fs.set_max_drift(options.max_drift)
1087
1088 SCons.Job.explicit_stack_size = options.stack_size
1089
1090 if options.md5_chunksize:
1091 SCons.Node.FS.File.md5_chunksize = options.md5_chunksize
1092
1093 platform = SCons.Platform.platform_module()
1094
1095 if options.interactive:
1096 SCons.Script.Interactive.interact(fs, OptionsParser, options,
1097 targets, target_top)
1098
1099 else:
1100
1101
1102 nodes = _build_targets(fs, options, targets, target_top)
1103 if not nodes:
1104 revert_io()
1105 print 'Found nothing to build'
1106 exit_status = 2
1107
1171 d = list(filter(check_dir, SCons.Script.DEFAULT_TARGETS))
1172 SCons.Script.DEFAULT_TARGETS[:] = d
1173 target_top = None
1174 lookup_top = None
1175
1176 targets = SCons.Script._Get_Default_Targets(d, fs)
1177
1178 if not targets:
1179 sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n")
1180 return None
1181
1182 def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
1183 if isinstance(x, SCons.Node.Node):
1184 node = x
1185 else:
1186 node = None
1187
1188 if ltop is None: ltop = ''
1189
1190
1191
1192 curdir = os.path.join(os.getcwd(), str(ltop))
1193 for lookup in SCons.Node.arg2nodes_lookups:
1194 node = lookup(x, curdir=curdir)
1195 if node is not None:
1196 break
1197 if node is None:
1198 node = fs.Entry(x, directory=ltop, create=1)
1199 if ttop and not node.is_under(ttop):
1200 if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node):
1201 node = ttop
1202 else:
1203 node = None
1204 return node
1205
1206 nodes = [_f for _f in map(Entry, targets) if _f]
1207
1208 task_class = BuildTask
1209 opening_message = "Building targets ..."
1210 closing_message = "done building targets."
1211 if options.keep_going:
1212 failure_message = "done building targets (errors occurred during build)."
1213 else:
1214 failure_message = "building terminated because of errors."
1215 if options.question:
1216 task_class = QuestionTask
1217 try:
1218 if options.clean:
1219 task_class = CleanTask
1220 opening_message = "Cleaning targets ..."
1221 closing_message = "done cleaning targets."
1222 if options.keep_going:
1223 failure_message = "done cleaning targets (errors occurred during clean)."
1224 else:
1225 failure_message = "cleaning terminated because of errors."
1226 except AttributeError:
1227 pass
1228
1229 task_class.progress = ProgressObject
1230
1231 if options.random:
1232 def order(dependencies):
1233 """Randomize the dependencies."""
1234 import random
1235
1236
1237 d = dependencies
1238 for i in range(len(d)-1, 0, -1):
1239 j = int(random.random() * (i+1))
1240 d[i], d[j] = d[j], d[i]
1241 return d
1242 else:
1243 def order(dependencies):
1244 """Leave the order of dependencies alone."""
1245 return dependencies
1246
1247 if options.taskmastertrace_file == '-':
1248 tmtrace = sys.stdout
1249 elif options.taskmastertrace_file:
1250 tmtrace = open(options.taskmastertrace_file, 'wb')
1251 else:
1252 tmtrace = None
1253 taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order, tmtrace)
1254
1255
1256
1257 BuildTask.options = options
1258
1259 global num_jobs
1260 num_jobs = options.num_jobs
1261 jobs = SCons.Job.Jobs(num_jobs, taskmaster)
1262 if num_jobs > 1:
1263 msg = None
1264 if jobs.num_jobs == 1:
1265 msg = "parallel builds are unsupported by this version of Python;\n" + \
1266 "\tignoring -j or num_jobs option.\n"
1267 elif sys.platform == 'win32':
1268 msg = fetch_win32_parallel_msg()
1269 if msg:
1270 SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
1271
1272 memory_stats.append('before building targets:')
1273 count_stats.append(('pre-', 'build'))
1274
1275 def jobs_postfunc(
1276 jobs=jobs,
1277 options=options,
1278 closing_message=closing_message,
1279 failure_message=failure_message
1280 ):
1281 if jobs.were_interrupted():
1282 if not options.no_progress and not options.silent:
1283 sys.stderr.write("scons: Build interrupted.\n")
1284 global exit_status
1285 global this_build_status
1286 exit_status = 2
1287 this_build_status = 2
1288
1289 if this_build_status:
1290 progress_display("scons: " + failure_message)
1291 else:
1292 progress_display("scons: " + closing_message)
1293 if not options.no_exec:
1294 if jobs.were_interrupted():
1295 progress_display("scons: writing .sconsign file.")
1296 SCons.SConsign.write()
1297
1298 progress_display("scons: " + opening_message)
1299 jobs.run(postfunc = jobs_postfunc)
1300
1301 memory_stats.append('after building targets:')
1302 count_stats.append(('post-', 'build'))
1303
1304 return nodes
1305
1306 -def _exec_main(parser, values):
1307 sconsflags = os.environ.get('SCONSFLAGS', '')
1308 all_args = sconsflags.split() + sys.argv[1:]
1309
1310 options, args = parser.parse_args(all_args, values)
1311
1312 if isinstance(options.debug, list) and "pdb" in options.debug:
1313 import pdb
1314 pdb.Pdb().runcall(_main, parser)
1315 elif options.profile_file:
1316
1317 from profile import Profile
1318
1319
1320
1321
1322
1323
1324 try:
1325 dispatch = Profile.dispatch
1326 except AttributeError:
1327 pass
1328 else:
1329 dispatch['c_exception'] = Profile.trace_dispatch_return
1330
1331 prof = Profile()
1332 try:
1333 prof.runcall(_main, parser)
1334 finally:
1335 prof.dump_stats(options.profile_file)
1336 else:
1337 _main(parser)
1338
1340 global OptionsParser
1341 global exit_status
1342 global first_command_start
1343
1344
1345
1346
1347
1348 if python_version_unsupported():
1349 msg = "scons: *** SCons version %s does not run under Python version %s.\n"
1350 sys.stderr.write(msg % (SCons.__version__, python_version_string()))
1351 sys.exit(1)
1352
1353 parts = ["SCons by Steven Knight et al.:\n"]
1354 try:
1355 import __main__
1356 parts.append(version_string("script", __main__))
1357 except (ImportError, AttributeError):
1358
1359
1360 pass
1361 parts.append(version_string("engine", SCons))
1362 parts.append(path_string("engine", SCons))
1363 parts.append("Copyright (c) 2001 - 2015 The SCons Foundation")
1364 version = ''.join(parts)
1365
1366 import SConsOptions
1367 parser = SConsOptions.Parser(version)
1368 values = SConsOptions.SConsValues(parser.get_default_values())
1369
1370 OptionsParser = parser
1371
1372 try:
1373 try:
1374 _exec_main(parser, values)
1375 finally:
1376 revert_io()
1377 except SystemExit, s:
1378 if s:
1379 exit_status = s
1380 except KeyboardInterrupt:
1381 print("scons: Build interrupted.")
1382 sys.exit(2)
1383 except SyntaxError, e:
1384 _scons_syntax_error(e)
1385 except SCons.Errors.InternalError:
1386 _scons_internal_error()
1387 except SCons.Errors.UserError, e:
1388 _scons_user_error(e)
1389 except SConsPrintHelpException:
1390 parser.print_help()
1391 exit_status = 0
1392 except SCons.Errors.BuildError, e:
1393 print e
1394 exit_status = e.exitstatus
1395 except:
1396
1397
1398
1399 SCons.Script._SConscript.SConscript_exception()
1400 sys.exit(2)
1401
1402 memory_stats.print_stats()
1403 count_stats.print_stats()
1404
1405 if print_objects:
1406 SCons.Debug.listLoggedInstances('*')
1407
1408
1409 if print_memoizer:
1410 SCons.Memoize.Dump("Memoizer (memory cache) hits and misses:")
1411
1412
1413
1414
1415
1416 SCons.Debug.dump_caller_counts()
1417 SCons.Taskmaster.dump_stats()
1418
1419 if print_time:
1420 total_time = time.time() - SCons.Script.start_time
1421 if num_jobs == 1:
1422 ct = cumulative_command_time
1423 else:
1424 if last_command_end is None or first_command_start is None:
1425 ct = 0.0
1426 else:
1427 ct = last_command_end - first_command_start
1428 scons_time = total_time - sconscript_time - ct
1429 print "Total build time: %f seconds"%total_time
1430 print "Total SConscript file execution time: %f seconds"%sconscript_time
1431 print "Total SCons execution time: %f seconds"%scons_time
1432 print "Total command execution time: %f seconds"%ct
1433
1434 sys.exit(exit_status)
1435
1436
1437
1438
1439
1440
1441