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.0:3365:9259ea1c13d7 2015/09/21 14:03:43 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
487
500
506 stats_table = {}
507 for s in self.stats:
508 for n in [t[0] for t in s]:
509 stats_table[n] = [0, 0, 0, 0]
510 i = 0
511 for s in self.stats:
512 for n, c in s:
513 stats_table[n][i] = c
514 i = i + 1
515 self.outfp.write("Object counts:\n")
516 pre = [" "]
517 post = [" %s\n"]
518 l = len(self.stats)
519 fmt1 = ''.join(pre + [' %7s']*l + post)
520 fmt2 = ''.join(pre + [' %7d']*l + post)
521 labels = self.labels[:l]
522 labels.append(("", "Class"))
523 self.outfp.write(fmt1 % tuple([x[0] for x in labels]))
524 self.outfp.write(fmt1 % tuple([x[1] for x in labels]))
525 for k in sorted(stats_table.keys()):
526 r = stats_table[k][:l] + [k]
527 self.outfp.write(fmt2 % tuple(r))
528
529 count_stats = CountStats()
530
536 fmt = 'Memory %-32s %12d\n'
537 for label, stats in zip(self.labels, self.stats):
538 self.outfp.write(fmt % (label, stats))
539
540 memory_stats = MemStats()
541
542
543
545 """Handle syntax errors. Print out a message and show where the error
546 occurred.
547 """
548 etype, value, tb = sys.exc_info()
549 lines = traceback.format_exception_only(etype, value)
550 for line in lines:
551 sys.stderr.write(line+'\n')
552 sys.exit(2)
553
555 """
556 Find the deepest stack frame that is not part of SCons.
557
558 Input is a "pre-processed" stack trace in the form
559 returned by traceback.extract_tb() or traceback.extract_stack()
560 """
561
562 tb.reverse()
563
564
565
566 for frame in tb:
567 filename = frame[0]
568 if filename.find(os.sep+'SCons'+os.sep) == -1:
569 return frame
570 return tb[0]
571
573 """Handle user errors. Print out a message and a description of the
574 error, along with the line number and routine where it occured.
575 The file and line number will be the deepest stack frame that is
576 not part of SCons itself.
577 """
578 global print_stacktrace
579 etype, value, tb = sys.exc_info()
580 if print_stacktrace:
581 traceback.print_exception(etype, value, tb)
582 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
583 sys.stderr.write("\nscons: *** %s\n" % value)
584 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
585 sys.exit(2)
586
588 """Handle user warnings. Print out a message and a description of
589 the warning, along with the line number and routine where it occured.
590 The file and line number will be the deepest stack frame that is
591 not part of SCons itself.
592 """
593 etype, value, tb = sys.exc_info()
594 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
595 sys.stderr.write("\nscons: warning: %s\n" % e)
596 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
597
599 """Slightly different from _scons_user_warning in that we use the
600 *current call stack* rather than sys.exc_info() to get our stack trace.
601 This is used by the warnings framework to print warnings."""
602 filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_stack())
603 sys.stderr.write("\nscons: warning: %s\n" % e.args[0])
604 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
605
607 """Handle all errors but user errors. Print out a message telling
608 the user what to do in this case and print a normal trace.
609 """
610 print 'internal error'
611 traceback.print_exc()
612 sys.exit(2)
613
615 """This function checks that an SConstruct file exists in a directory.
616 If so, it returns the path of the file. By default, it checks the
617 current directory.
618 """
619 if not filelist:
620 filelist = ['SConstruct', 'Sconstruct', 'sconstruct']
621 for file in filelist:
622 sfile = os.path.join(dirname, file)
623 if os.path.isfile(sfile):
624 return sfile
625 if not os.path.isabs(sfile):
626 for rep in repositories:
627 if os.path.isfile(os.path.join(rep, sfile)):
628 return sfile
629 return None
630
676
685
687 """Load the site_scons dir under topdir.
688 Prepends site_scons to sys.path, imports site_scons/site_init.py,
689 and prepends site_scons/site_tools to default toolpath."""
690 if site_dir_name:
691 err_if_not_found = True
692 else:
693 site_dir_name = "site_scons"
694 err_if_not_found = False
695
696 site_dir = os.path.join(topdir, site_dir_name)
697 if not os.path.exists(site_dir):
698 if err_if_not_found:
699 raise SCons.Errors.UserError("site dir %s not found."%site_dir)
700 return
701
702 site_init_filename = "site_init.py"
703 site_init_modname = "site_init"
704 site_tools_dirname = "site_tools"
705
706 sys.path = [os.path.abspath(site_dir)] + sys.path
707 site_init_file = os.path.join(site_dir, site_init_filename)
708 site_tools_dir = os.path.join(site_dir, site_tools_dirname)
709 if os.path.exists(site_init_file):
710 import imp, re
711
712 try:
713 try:
714 fp, pathname, description = imp.find_module(site_init_modname,
715 [site_dir])
716
717
718
719
720
721
722
723 try:
724 m = sys.modules['SCons.Script']
725 except Exception, e:
726 fmt = 'cannot import site_init.py: missing SCons.Script module %s'
727 raise SCons.Errors.InternalError(fmt % repr(e))
728 try:
729 sfx = description[0]
730 modname = os.path.basename(pathname)[:-len(sfx)]
731 site_m = {"__file__": pathname, "__name__": modname, "__doc__": None}
732 re_special = re.compile("__[^_]+__")
733 for k in m.__dict__.keys():
734 if not re_special.match(k):
735 site_m[k] = m.__dict__[k]
736
737
738 exec fp in site_m
739 except KeyboardInterrupt:
740 raise
741 except Exception, e:
742 fmt = '*** Error loading site_init file %s:\n'
743 sys.stderr.write(fmt % repr(site_init_file))
744 raise
745 else:
746 for k in site_m:
747 if not re_special.match(k):
748 m.__dict__[k] = site_m[k]
749 except KeyboardInterrupt:
750 raise
751 except ImportError, e:
752 fmt = '*** cannot import site init file %s:\n'
753 sys.stderr.write(fmt % repr(site_init_file))
754 raise
755 finally:
756 if fp:
757 fp.close()
758 if os.path.exists(site_tools_dir):
759
760 SCons.Tool.DefaultToolpath.insert(0, os.path.abspath(site_tools_dir))
761
763 """Load all of the predefined site_scons dir.
764 Order is significant; we load them in order from most generic
765 (machine-wide) to most specific (topdir).
766 The verbose argument is only for testing.
767 """
768 platform = SCons.Platform.platform_default()
769
770 def homedir(d):
771 return os.path.expanduser('~/'+d)
772
773 if platform == 'win32' or platform == 'cygwin':
774
775
776
777 sysdirs=[
778 os.path.expandvars('$ALLUSERSPROFILE\\Application Data\\scons'),
779 os.path.expandvars('$USERPROFILE\\Local Settings\\Application Data\\scons')]
780 appdatadir = os.path.expandvars('$APPDATA\\scons')
781 if appdatadir not in sysdirs:
782 sysdirs.append(appdatadir)
783 sysdirs.append(homedir('.scons'))
784
785 elif platform == 'darwin':
786 sysdirs=['/Library/Application Support/SCons',
787 '/opt/local/share/scons',
788 '/sw/share/scons',
789 homedir('Library/Application Support/SCons'),
790 homedir('.scons')]
791 elif platform == 'sunos':
792 sysdirs=['/opt/sfw/scons',
793 '/usr/share/scons',
794 homedir('.scons')]
795 else:
796
797 sysdirs=['/usr/share/scons',
798 homedir('.scons')]
799
800 dirs=sysdirs + [topdir]
801 for d in dirs:
802 if verbose:
803 print "Loading site dir ", d
804 _load_site_scons_dir(d)
805
808
822
824 path = module.__path__
825 return "\t%s path: %s\n"%(label,path)
826
828 global exit_status
829 global this_build_status
830
831 options = parser.values
832
833
834
835
836
837
838
839
840 default_warnings = [ SCons.Warnings.WarningOnByDefault,
841 SCons.Warnings.DeprecatedWarning,
842 ]
843
844 for warning in default_warnings:
845 SCons.Warnings.enableWarningClass(warning)
846 SCons.Warnings._warningOut = _scons_internal_warning
847 SCons.Warnings.process_warn_strings(options.warn)
848
849
850
851
852 try:
853 dw = options.delayed_warnings
854 except AttributeError:
855 pass
856 else:
857 delayed_warnings.extend(dw)
858 for warning_type, message in delayed_warnings:
859 SCons.Warnings.warn(warning_type, message)
860
861 if options.diskcheck:
862 SCons.Node.FS.set_diskcheck(options.diskcheck)
863
864
865
866
867
868
869 if options.directory:
870 script_dir = os.path.abspath(_create_path(options.directory))
871 else:
872 script_dir = os.getcwd()
873
874 target_top = None
875 if options.climb_up:
876 target_top = '.'
877 while script_dir and not _SConstruct_exists(script_dir,
878 options.repository,
879 options.file):
880 script_dir, last_part = os.path.split(script_dir)
881 if last_part:
882 target_top = os.path.join(last_part, target_top)
883 else:
884 script_dir = ''
885
886 if script_dir and script_dir != os.getcwd():
887 if not options.silent:
888 display("scons: Entering directory `%s'" % script_dir)
889 try:
890 os.chdir(script_dir)
891 except OSError:
892 sys.stderr.write("Could not change directory to %s\n" % script_dir)
893
894
895
896
897 fs = SCons.Node.FS.get_default_fs()
898
899 for rep in options.repository:
900 fs.Repository(rep)
901
902
903
904
905 scripts = []
906 if options.file:
907 scripts.extend(options.file)
908 if not scripts:
909 sfile = _SConstruct_exists(repositories=options.repository,
910 filelist=options.file)
911 if sfile:
912 scripts.append(sfile)
913
914 if not scripts:
915 if options.help:
916
917
918
919 raise SConsPrintHelpException
920 raise SCons.Errors.UserError("No SConstruct file found.")
921
922 if scripts[0] == "-":
923 d = fs.getcwd()
924 else:
925 d = fs.File(scripts[0]).dir
926 fs.set_SConstruct_dir(d)
927
928 _set_debug_values(options)
929 SCons.Node.implicit_cache = options.implicit_cache
930 SCons.Node.implicit_deps_changed = options.implicit_deps_changed
931 SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged
932
933 if options.no_exec:
934 SCons.SConf.dryrun = 1
935 SCons.Action.execute_actions = None
936 if options.question:
937 SCons.SConf.dryrun = 1
938 if options.clean:
939 SCons.SConf.SetBuildType('clean')
940 if options.help:
941 SCons.SConf.SetBuildType('help')
942 SCons.SConf.SetCacheMode(options.config)
943 SCons.SConf.SetProgressDisplay(progress_display)
944
945 if options.no_progress or options.silent:
946 progress_display.set_mode(0)
947
948 if options.site_dir:
949 _load_site_scons_dir(d.get_internal_path(), options.site_dir)
950 elif not options.no_site_dir:
951 _load_all_site_scons_dirs(d.get_internal_path())
952
953 if options.include_dir:
954 sys.path = options.include_dir + sys.path
955
956
957
958
959
960
961 if options.interactive:
962 SCons.Node.interactive = True
963
964
965
966
967 targets = []
968 xmit_args = []
969 for a in parser.largs:
970 if a[:1] == '-':
971 continue
972 if '=' in a:
973 xmit_args.append(a)
974 else:
975 targets.append(a)
976 SCons.Script._Add_Targets(targets + parser.rargs)
977 SCons.Script._Add_Arguments(xmit_args)
978
979
980
981
982
983
984
985
986
987 if not hasattr(sys.stdout, 'isatty') or not sys.stdout.isatty():
988 sys.stdout = SCons.Util.Unbuffered(sys.stdout)
989 if not hasattr(sys.stderr, 'isatty') or not sys.stderr.isatty():
990 sys.stderr = SCons.Util.Unbuffered(sys.stderr)
991
992 memory_stats.append('before reading SConscript files:')
993 count_stats.append(('pre-', 'read'))
994
995
996
997 progress_display("scons: Reading SConscript files ...")
998
999 start_time = time.time()
1000 try:
1001 for script in scripts:
1002 SCons.Script._SConscript._SConscript(fs, script)
1003 except SCons.Errors.StopError, e:
1004
1005
1006
1007
1008
1009 revert_io()
1010 sys.stderr.write("scons: *** %s Stop.\n" % e)
1011 sys.exit(2)
1012 global sconscript_time
1013 sconscript_time = time.time() - start_time
1014
1015 progress_display("scons: done reading SConscript files.")
1016
1017 memory_stats.append('after reading SConscript files:')
1018 count_stats.append(('post-', 'read'))
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029 SCons.Warnings.process_warn_strings(options.warn)
1030
1031
1032
1033
1034 if python_version_deprecated():
1035 msg = "Support for pre-%s Python version (%s) is deprecated.\n" + \
1036 " If this will cause hardship, contact scons-dev@scons.org"
1037 deprecated_version_string = ".".join(map(str, deprecated_python_version))
1038 SCons.Warnings.warn(SCons.Warnings.PythonVersionWarning,
1039 msg % (deprecated_version_string, python_version_string()))
1040
1041 if not options.help:
1042
1043
1044
1045 if SCons.SConf.NeedConfigHBuilder():
1046 SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
1047
1048
1049
1050
1051
1052
1053
1054 parser.preserve_unknown_options = False
1055 parser.parse_args(parser.largs, options)
1056
1057 if options.help:
1058 help_text = SCons.Script.help_text
1059 if help_text is None:
1060
1061
1062 raise SConsPrintHelpException
1063 else:
1064 print help_text
1065 print "Use scons -H for help about command-line options."
1066 exit_status = 0
1067 return
1068
1069
1070
1071
1072
1073
1074
1075 fs.chdir(fs.Top)
1076
1077 SCons.Node.FS.save_strings(1)
1078
1079
1080
1081 SCons.Node.implicit_cache = options.implicit_cache
1082 SCons.Node.FS.set_duplicate(options.duplicate)
1083 fs.set_max_drift(options.max_drift)
1084
1085 SCons.Job.explicit_stack_size = options.stack_size
1086
1087 if options.md5_chunksize:
1088 SCons.Node.FS.File.md5_chunksize = options.md5_chunksize
1089
1090 platform = SCons.Platform.platform_module()
1091
1092 if options.interactive:
1093 SCons.Script.Interactive.interact(fs, OptionsParser, options,
1094 targets, target_top)
1095
1096 else:
1097
1098
1099 nodes = _build_targets(fs, options, targets, target_top)
1100 if not nodes:
1101 revert_io()
1102 print 'Found nothing to build'
1103 exit_status = 2
1104
1168 d = list(filter(check_dir, SCons.Script.DEFAULT_TARGETS))
1169 SCons.Script.DEFAULT_TARGETS[:] = d
1170 target_top = None
1171 lookup_top = None
1172
1173 targets = SCons.Script._Get_Default_Targets(d, fs)
1174
1175 if not targets:
1176 sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n")
1177 return None
1178
1179 def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
1180 if isinstance(x, SCons.Node.Node):
1181 node = x
1182 else:
1183 node = None
1184
1185 if ltop is None: ltop = ''
1186
1187
1188
1189 curdir = os.path.join(os.getcwd(), str(ltop))
1190 for lookup in SCons.Node.arg2nodes_lookups:
1191 node = lookup(x, curdir=curdir)
1192 if node is not None:
1193 break
1194 if node is None:
1195 node = fs.Entry(x, directory=ltop, create=1)
1196 if ttop and not node.is_under(ttop):
1197 if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node):
1198 node = ttop
1199 else:
1200 node = None
1201 return node
1202
1203 nodes = [_f for _f in map(Entry, targets) if _f]
1204
1205 task_class = BuildTask
1206 opening_message = "Building targets ..."
1207 closing_message = "done building targets."
1208 if options.keep_going:
1209 failure_message = "done building targets (errors occurred during build)."
1210 else:
1211 failure_message = "building terminated because of errors."
1212 if options.question:
1213 task_class = QuestionTask
1214 try:
1215 if options.clean:
1216 task_class = CleanTask
1217 opening_message = "Cleaning targets ..."
1218 closing_message = "done cleaning targets."
1219 if options.keep_going:
1220 failure_message = "done cleaning targets (errors occurred during clean)."
1221 else:
1222 failure_message = "cleaning terminated because of errors."
1223 except AttributeError:
1224 pass
1225
1226 task_class.progress = ProgressObject
1227
1228 if options.random:
1229 def order(dependencies):
1230 """Randomize the dependencies."""
1231 import random
1232
1233
1234 d = dependencies
1235 for i in range(len(d)-1, 0, -1):
1236 j = int(random.random() * (i+1))
1237 d[i], d[j] = d[j], d[i]
1238 return d
1239 else:
1240 def order(dependencies):
1241 """Leave the order of dependencies alone."""
1242 return dependencies
1243
1244 if options.taskmastertrace_file == '-':
1245 tmtrace = sys.stdout
1246 elif options.taskmastertrace_file:
1247 tmtrace = open(options.taskmastertrace_file, 'wb')
1248 else:
1249 tmtrace = None
1250 taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order, tmtrace)
1251
1252
1253
1254 BuildTask.options = options
1255
1256 global num_jobs
1257 num_jobs = options.num_jobs
1258 jobs = SCons.Job.Jobs(num_jobs, taskmaster)
1259 if num_jobs > 1:
1260 msg = None
1261 if jobs.num_jobs == 1:
1262 msg = "parallel builds are unsupported by this version of Python;\n" + \
1263 "\tignoring -j or num_jobs option.\n"
1264 elif sys.platform == 'win32':
1265 msg = fetch_win32_parallel_msg()
1266 if msg:
1267 SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
1268
1269 memory_stats.append('before building targets:')
1270 count_stats.append(('pre-', 'build'))
1271
1272 def jobs_postfunc(
1273 jobs=jobs,
1274 options=options,
1275 closing_message=closing_message,
1276 failure_message=failure_message
1277 ):
1278 if jobs.were_interrupted():
1279 if not options.no_progress and not options.silent:
1280 sys.stderr.write("scons: Build interrupted.\n")
1281 global exit_status
1282 global this_build_status
1283 exit_status = 2
1284 this_build_status = 2
1285
1286 if this_build_status:
1287 progress_display("scons: " + failure_message)
1288 else:
1289 progress_display("scons: " + closing_message)
1290 if not options.no_exec:
1291 if jobs.were_interrupted():
1292 progress_display("scons: writing .sconsign file.")
1293 SCons.SConsign.write()
1294
1295 progress_display("scons: " + opening_message)
1296 jobs.run(postfunc = jobs_postfunc)
1297
1298 memory_stats.append('after building targets:')
1299 count_stats.append(('post-', 'build'))
1300
1301 return nodes
1302
1303 -def _exec_main(parser, values):
1304 sconsflags = os.environ.get('SCONSFLAGS', '')
1305 all_args = sconsflags.split() + sys.argv[1:]
1306
1307 options, args = parser.parse_args(all_args, values)
1308
1309 if isinstance(options.debug, list) and "pdb" in options.debug:
1310 import pdb
1311 pdb.Pdb().runcall(_main, parser)
1312 elif options.profile_file:
1313
1314 from profile import Profile
1315
1316
1317
1318
1319
1320
1321 try:
1322 dispatch = Profile.dispatch
1323 except AttributeError:
1324 pass
1325 else:
1326 dispatch['c_exception'] = Profile.trace_dispatch_return
1327
1328 prof = Profile()
1329 try:
1330 prof.runcall(_main, parser)
1331 finally:
1332 prof.dump_stats(options.profile_file)
1333 else:
1334 _main(parser)
1335
1337 global OptionsParser
1338 global exit_status
1339 global first_command_start
1340
1341
1342
1343
1344
1345 if python_version_unsupported():
1346 msg = "scons: *** SCons version %s does not run under Python version %s.\n"
1347 sys.stderr.write(msg % (SCons.__version__, python_version_string()))
1348 sys.exit(1)
1349
1350 parts = ["SCons by Steven Knight et al.:\n"]
1351 try:
1352 import __main__
1353 parts.append(version_string("script", __main__))
1354 except (ImportError, AttributeError):
1355
1356
1357 pass
1358 parts.append(version_string("engine", SCons))
1359 parts.append(path_string("engine", SCons))
1360 parts.append("Copyright (c) 2001 - 2015 The SCons Foundation")
1361 version = ''.join(parts)
1362
1363 import SConsOptions
1364 parser = SConsOptions.Parser(version)
1365 values = SConsOptions.SConsValues(parser.get_default_values())
1366
1367 OptionsParser = parser
1368
1369 try:
1370 try:
1371 _exec_main(parser, values)
1372 finally:
1373 revert_io()
1374 except SystemExit, s:
1375 if s:
1376 exit_status = s
1377 except KeyboardInterrupt:
1378 print("scons: Build interrupted.")
1379 sys.exit(2)
1380 except SyntaxError, e:
1381 _scons_syntax_error(e)
1382 except SCons.Errors.InternalError:
1383 _scons_internal_error()
1384 except SCons.Errors.UserError, e:
1385 _scons_user_error(e)
1386 except SConsPrintHelpException:
1387 parser.print_help()
1388 exit_status = 0
1389 except SCons.Errors.BuildError, e:
1390 print e
1391 exit_status = e.exitstatus
1392 except:
1393
1394
1395
1396 SCons.Script._SConscript.SConscript_exception()
1397 sys.exit(2)
1398
1399 memory_stats.print_stats()
1400 count_stats.print_stats()
1401
1402 if print_objects:
1403 SCons.Debug.listLoggedInstances('*')
1404
1405
1406 if print_memoizer:
1407 SCons.Memoize.Dump("Memoizer (memory cache) hits and misses:")
1408
1409
1410
1411
1412
1413 SCons.Debug.dump_caller_counts()
1414 SCons.Taskmaster.dump_stats()
1415
1416 if print_time:
1417 total_time = time.time() - SCons.Script.start_time
1418 if num_jobs == 1:
1419 ct = cumulative_command_time
1420 else:
1421 if last_command_end is None or first_command_start is None:
1422 ct = 0.0
1423 else:
1424 ct = last_command_end - first_command_start
1425 scons_time = total_time - sconscript_time - ct
1426 print "Total build time: %f seconds"%total_time
1427 print "Total SConscript file execution time: %f seconds"%sconscript_time
1428 print "Total SCons execution time: %f seconds"%scons_time
1429 print "Total command execution time: %f seconds"%ct
1430
1431 sys.exit(exit_status)
1432
1433
1434
1435
1436
1437
1438