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