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