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