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/08/24 12:12:31 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):
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.path, options.site_dir)
950 elif not options.no_site_dir:
951 _load_all_site_scons_dirs(d.path)
952
953 if options.include_dir:
954 sys.path = options.include_dir + sys.path
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.Node.interactive = True
1086 SCons.Script.Interactive.interact(fs, OptionsParser, options,
1087 targets, target_top)
1088
1089 else:
1090
1091
1092 nodes = _build_targets(fs, options, targets, target_top)
1093 if not nodes:
1094 revert_io()
1095 print 'Found nothing to build'
1096 exit_status = 2
1097
1162 d = list(filter(check_dir, SCons.Script.DEFAULT_TARGETS))
1163 SCons.Script.DEFAULT_TARGETS[:] = d
1164 target_top = None
1165 lookup_top = None
1166
1167 targets = SCons.Script._Get_Default_Targets(d, fs)
1168
1169 if not targets:
1170 sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n")
1171 return None
1172
1173 def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
1174 if isinstance(x, SCons.Node.Node):
1175 node = x
1176 else:
1177 node = None
1178
1179 if ltop is None: ltop = ''
1180
1181
1182
1183 curdir = os.path.join(os.getcwd(), str(ltop))
1184 for lookup in SCons.Node.arg2nodes_lookups:
1185 node = lookup(x, curdir=curdir)
1186 if node is not None:
1187 break
1188 if node is None:
1189 node = fs.Entry(x, directory=ltop, create=1)
1190 if ttop and not node.is_under(ttop):
1191 if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node):
1192 node = ttop
1193 else:
1194 node = None
1195 return node
1196
1197 nodes = [_f for _f in map(Entry, targets) if _f]
1198
1199 task_class = BuildTask
1200 opening_message = "Building targets ..."
1201 closing_message = "done building targets."
1202 if options.keep_going:
1203 failure_message = "done building targets (errors occurred during build)."
1204 else:
1205 failure_message = "building terminated because of errors."
1206 if options.question:
1207 task_class = QuestionTask
1208 try:
1209 if options.clean:
1210 task_class = CleanTask
1211 opening_message = "Cleaning targets ..."
1212 closing_message = "done cleaning targets."
1213 if options.keep_going:
1214 failure_message = "done cleaning targets (errors occurred during clean)."
1215 else:
1216 failure_message = "cleaning terminated because of errors."
1217 except AttributeError:
1218 pass
1219
1220 task_class.progress = ProgressObject
1221
1222 if options.random:
1223 def order(dependencies):
1224 """Randomize the dependencies."""
1225 import random
1226
1227
1228 d = dependencies
1229 for i in range(len(d)-1, 0, -1):
1230 j = int(random.random() * (i+1))
1231 d[i], d[j] = d[j], d[i]
1232 return d
1233 else:
1234 def order(dependencies):
1235 """Leave the order of dependencies alone."""
1236 return dependencies
1237
1238 if options.taskmastertrace_file == '-':
1239 tmtrace = sys.stdout
1240 elif options.taskmastertrace_file:
1241 tmtrace = open(options.taskmastertrace_file, 'wb')
1242 else:
1243 tmtrace = None
1244 taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order, tmtrace)
1245
1246
1247
1248 BuildTask.options = options
1249
1250 global num_jobs
1251 num_jobs = options.num_jobs
1252 jobs = SCons.Job.Jobs(num_jobs, taskmaster)
1253 if num_jobs > 1:
1254 msg = None
1255 if jobs.num_jobs == 1:
1256 msg = "parallel builds are unsupported by this version of Python;\n" + \
1257 "\tignoring -j or num_jobs option.\n"
1258 elif sys.platform == 'win32':
1259 msg = fetch_win32_parallel_msg()
1260 if msg:
1261 SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
1262
1263 memory_stats.append('before building targets:')
1264 count_stats.append(('pre-', 'build'))
1265
1266 def jobs_postfunc(
1267 jobs=jobs,
1268 options=options,
1269 closing_message=closing_message,
1270 failure_message=failure_message
1271 ):
1272 if jobs.were_interrupted():
1273 if not options.no_progress and not options.silent:
1274 sys.stderr.write("scons: Build interrupted.\n")
1275 global exit_status
1276 global this_build_status
1277 exit_status = 2
1278 this_build_status = 2
1279
1280 if this_build_status:
1281 progress_display("scons: " + failure_message)
1282 else:
1283 progress_display("scons: " + closing_message)
1284 if not options.no_exec:
1285 if jobs.were_interrupted():
1286 progress_display("scons: writing .sconsign file.")
1287 SCons.SConsign.write()
1288
1289 progress_display("scons: " + opening_message)
1290 jobs.run(postfunc = jobs_postfunc)
1291
1292 memory_stats.append('after building targets:')
1293 count_stats.append(('post-', 'build'))
1294
1295 return nodes
1296
1297 -def _exec_main(parser, values):
1298 sconsflags = os.environ.get('SCONSFLAGS', '')
1299 all_args = sconsflags.split() + sys.argv[1:]
1300
1301 options, args = parser.parse_args(all_args, values)
1302
1303 if isinstance(options.debug, list) and "pdb" in options.debug:
1304 import pdb
1305 pdb.Pdb().runcall(_main, parser)
1306 elif options.profile_file:
1307
1308 from profile import Profile
1309
1310
1311
1312
1313
1314
1315 try:
1316 dispatch = Profile.dispatch
1317 except AttributeError:
1318 pass
1319 else:
1320 dispatch['c_exception'] = Profile.trace_dispatch_return
1321
1322 prof = Profile()
1323 try:
1324 prof.runcall(_main, parser)
1325 finally:
1326 prof.dump_stats(options.profile_file)
1327 else:
1328 _main(parser)
1329
1331 global OptionsParser
1332 global exit_status
1333 global first_command_start
1334
1335
1336
1337
1338
1339 if python_version_unsupported():
1340 msg = "scons: *** SCons version %s does not run under Python version %s.\n"
1341 sys.stderr.write(msg % (SCons.__version__, python_version_string()))
1342 sys.exit(1)
1343
1344 parts = ["SCons by Steven Knight et al.:\n"]
1345 try:
1346 import __main__
1347 parts.append(version_string("script", __main__))
1348 except (ImportError, AttributeError):
1349
1350
1351 pass
1352 parts.append(version_string("engine", SCons))
1353 parts.append(path_string("engine", SCons))
1354 parts.append("Copyright (c) 2001 - 2014 The SCons Foundation")
1355 version = ''.join(parts)
1356
1357 import SConsOptions
1358 parser = SConsOptions.Parser(version)
1359 values = SConsOptions.SConsValues(parser.get_default_values())
1360
1361 OptionsParser = parser
1362
1363 try:
1364 try:
1365 _exec_main(parser, values)
1366 finally:
1367 revert_io()
1368 except SystemExit, s:
1369 if s:
1370 exit_status = s
1371 except KeyboardInterrupt:
1372 print("scons: Build interrupted.")
1373 sys.exit(2)
1374 except SyntaxError, e:
1375 _scons_syntax_error(e)
1376 except SCons.Errors.InternalError:
1377 _scons_internal_error()
1378 except SCons.Errors.UserError, e:
1379 _scons_user_error(e)
1380 except SConsPrintHelpException:
1381 parser.print_help()
1382 exit_status = 0
1383 except SCons.Errors.BuildError, e:
1384 print e
1385 exit_status = e.exitstatus
1386 except:
1387
1388
1389
1390 SCons.Script._SConscript.SConscript_exception()
1391 sys.exit(2)
1392
1393 memory_stats.print_stats()
1394 count_stats.print_stats()
1395
1396 if print_objects:
1397 SCons.Debug.listLoggedInstances('*')
1398
1399
1400 if print_memoizer:
1401 SCons.Memoize.Dump("Memoizer (memory cache) hits and misses:")
1402
1403
1404
1405
1406
1407 SCons.Debug.dump_caller_counts()
1408 SCons.Taskmaster.dump_stats()
1409
1410 if print_time:
1411 total_time = time.time() - SCons.Script.start_time
1412 if num_jobs == 1:
1413 ct = cumulative_command_time
1414 else:
1415 if last_command_end is None or first_command_start is None:
1416 ct = 0.0
1417 else:
1418 ct = last_command_end - first_command_start
1419 scons_time = total_time - sconscript_time - ct
1420 print "Total build time: %f seconds"%total_time
1421 print "Total SConscript file execution time: %f seconds"%sconscript_time
1422 print "Total SCons execution time: %f seconds"%scons_time
1423 print "Total command execution time: %f seconds"%ct
1424
1425 sys.exit(exit_status)
1426
1427
1428
1429
1430
1431
1432