OLD | NEW |
1 """SCons.Script | 1 """SCons.Script |
2 | 2 |
3 This file implements the main() function used by the scons script. | 3 This file implements the main() function used by the scons script. |
4 | 4 |
5 Architecturally, this *is* the scons script, and will likely only be | 5 Architecturally, this *is* the scons script, and will likely only be |
6 called from the external "scons" wrapper. Consequently, anything here | 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 | 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 | 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, | 9 some other module. If it's specific to the "scons" script invocation, |
10 it goes here. | 10 it goes here. |
(...skipping 16 matching lines...) Expand all Loading... |
27 # | 27 # |
28 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | 28 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
29 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | 29 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
30 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 30 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
31 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | 31 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
32 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | 32 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
33 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | 33 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
34 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 34 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
35 # | 35 # |
36 | 36 |
37 __revision__ = "src/engine/SCons/Script/Main.py 3603 2008/10/10 05:46:45 scons" | 37 __revision__ = "src/engine/SCons/Script/Main.py 3842 2008/12/20 22:59:52 scons" |
38 | 38 |
39 import os | 39 import os |
40 import os.path | 40 import os.path |
41 import string | 41 import string |
42 import sys | 42 import sys |
43 import time | 43 import time |
44 import traceback | 44 import traceback |
45 | 45 |
46 # Strip the script directory from sys.path() so on case-insensitive | 46 # Strip the script directory from sys.path() so on case-insensitive |
47 # (Windows) systems Python doesn't think that the "scons" script is the | 47 # (Windows) systems Python doesn't think that the "scons" script is the |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 t = self.targets[0] | 209 t = self.targets[0] |
210 if self.top and not t.has_builder() and not t.side_effect: | 210 if self.top and not t.has_builder() and not t.side_effect: |
211 if not t.exists(): | 211 if not t.exists(): |
212 errstr="Do not know how to make target `%s'." % t | 212 errstr="Do not know how to make target `%s'." % t |
213 sys.stderr.write("scons: *** " + errstr) | 213 sys.stderr.write("scons: *** " + errstr) |
214 if not self.options.keep_going: | 214 if not self.options.keep_going: |
215 sys.stderr.write(" Stop.") | 215 sys.stderr.write(" Stop.") |
216 sys.stderr.write("\n") | 216 sys.stderr.write("\n") |
217 try: | 217 try: |
218 raise SCons.Errors.BuildError(t, errstr) | 218 raise SCons.Errors.BuildError(t, errstr) |
| 219 except KeyboardInterrupt: |
| 220 raise |
219 except: | 221 except: |
220 self.exception_set() | 222 self.exception_set() |
221 self.do_failed() | 223 self.do_failed() |
222 else: | 224 else: |
223 print "scons: Nothing to be done for `%s'." % t | 225 print "scons: Nothing to be done for `%s'." % t |
224 SCons.Taskmaster.Task.executed(self) | 226 SCons.Taskmaster.Task.executed(self) |
225 else: | 227 else: |
226 SCons.Taskmaster.Task.executed(self) | 228 SCons.Taskmaster.Task.executed(self) |
227 | 229 |
228 def failed(self): | 230 def failed(self): |
229 # Handle the failure of a build task. The primary purpose here | 231 # Handle the failure of a build task. The primary purpose here |
230 # is to display the various types of Errors and Exceptions | 232 # is to display the various types of Errors and Exceptions |
231 # appropriately. | 233 # appropriately. |
232 status = 2 | |
233 exc_info = self.exc_info() | 234 exc_info = self.exc_info() |
234 try: | 235 try: |
235 t, e, tb = exc_info | 236 t, e, tb = exc_info |
236 except ValueError: | 237 except ValueError: |
237 t, e = exc_info | 238 t, e = exc_info |
238 tb = None | 239 tb = None |
| 240 |
239 if t is None: | 241 if t is None: |
240 # The Taskmaster didn't record an exception for this Task; | 242 # The Taskmaster didn't record an exception for this Task; |
241 # see if the sys module has one. | 243 # see if the sys module has one. |
242 t, e = sys.exc_info()[:2] | 244 try: |
| 245 t, e, tb = sys.exc_info()[:] |
| 246 except ValueError: |
| 247 t, e = exc_info |
| 248 tb = None |
| 249 |
| 250 # Deprecated string exceptions will have their string stored |
| 251 # in the first entry of the tuple. |
| 252 if e is None: |
| 253 e = t |
243 | 254 |
244 def nodestring(n): | 255 buildError = SCons.Errors.convert_to_BuildError(e) |
245 if not SCons.Util.is_List(n): | 256 if not buildError.node: |
246 n = [ n ] | 257 buildError.node = self.node |
247 return string.join(map(str, n), ', ') | 258 |
| 259 node = buildError.node |
| 260 if not SCons.Util.is_List(node): |
| 261 node = [ node ] |
| 262 nodename = string.join(map(str, node), ', ') |
248 | 263 |
249 errfmt = "scons: *** [%s] %s\n" | 264 errfmt = "scons: *** [%s] %s\n" |
| 265 sys.stderr.write(errfmt % (nodename, buildError)) |
250 | 266 |
251 if t == SCons.Errors.BuildError: | 267 if (buildError.exc_info[2] and buildError.exc_info[1] and |
252 tname = nodestring(e.node) | 268 # TODO(1.5) |
253 errstr = e.errstr | 269 #not isinstance( |
254 if e.filename: | 270 # buildError.exc_info[1], |
255 errstr = e.filename + ': ' + errstr | 271 # (EnvironmentError, SCons.Errors.StopError, SCons.Errors.UserErro
r))): |
256 sys.stderr.write(errfmt % (tname, errstr)) | 272 not isinstance(buildError.exc_info[1], EnvironmentError) and |
257 elif t == SCons.Errors.TaskmasterException: | 273 not isinstance(buildError.exc_info[1], SCons.Errors.StopError) and |
258 tname = nodestring(e.node) | 274 not isinstance(buildError.exc_info[1], SCons.Errors.UserError)): |
259 sys.stderr.write(errfmt % (tname, e.errstr)) | 275 type, value, trace = buildError.exc_info |
260 type, value, trace = e.exc_info | |
261 traceback.print_exception(type, value, trace) | 276 traceback.print_exception(type, value, trace) |
262 elif t == SCons.Errors.ExplicitExit: | 277 elif tb and print_stacktrace: |
263 status = e.status | 278 sys.stderr.write("scons: internal stack trace:\n") |
264 tname = nodestring(e.node) | 279 traceback.print_tb(tb, file=sys.stderr) |
265 errstr = 'Explicit exit, status %s' % status | |
266 sys.stderr.write(errfmt % (tname, errstr)) | |
267 else: | |
268 if e is None: | |
269 e = t | |
270 s = str(e) | |
271 if t == SCons.Errors.StopError and not self.options.keep_going: | |
272 s = s + ' Stop.' | |
273 sys.stderr.write("scons: *** %s\n" % s) | |
274 | 280 |
275 if tb and print_stacktrace: | 281 self.exception = (e, buildError, tb) # type, value, traceback |
276 sys.stderr.write("scons: internal stack trace:\n") | 282 self.do_failed(buildError.exitstatus) |
277 traceback.print_tb(tb, file=sys.stderr) | |
278 | |
279 self.do_failed(status) | |
280 | 283 |
281 self.exc_clear() | 284 self.exc_clear() |
282 | 285 |
283 def postprocess(self): | 286 def postprocess(self): |
284 if self.top: | 287 if self.top: |
285 t = self.targets[0] | 288 t = self.targets[0] |
286 for tp in self.options.tree_printers: | 289 for tp in self.options.tree_printers: |
287 tp.display(t) | 290 tp.display(t) |
288 if self.options.debug_includes: | 291 if self.options.debug_includes: |
289 tree = t.render_include_tree() | 292 tree = t.render_include_tree() |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine)
) | 594 sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine)
) |
592 | 595 |
593 def _scons_internal_error(): | 596 def _scons_internal_error(): |
594 """Handle all errors but user errors. Print out a message telling | 597 """Handle all errors but user errors. Print out a message telling |
595 the user what to do in this case and print a normal trace. | 598 the user what to do in this case and print a normal trace. |
596 """ | 599 """ |
597 print 'internal error' | 600 print 'internal error' |
598 traceback.print_exc() | 601 traceback.print_exc() |
599 sys.exit(2) | 602 sys.exit(2) |
600 | 603 |
601 def _SConstruct_exists(dirname='', repositories=[]): | 604 def _SConstruct_exists(dirname='', repositories=[], filelist=None): |
602 """This function checks that an SConstruct file exists in a directory. | 605 """This function checks that an SConstruct file exists in a directory. |
603 If so, it returns the path of the file. By default, it checks the | 606 If so, it returns the path of the file. By default, it checks the |
604 current directory. | 607 current directory. |
605 """ | 608 """ |
606 for file in ['SConstruct', 'Sconstruct', 'sconstruct']: | 609 if not filelist: |
| 610 filelist = ['SConstruct', 'Sconstruct', 'sconstruct'] |
| 611 for file in filelist: |
607 sfile = os.path.join(dirname, file) | 612 sfile = os.path.join(dirname, file) |
608 if os.path.isfile(sfile): | 613 if os.path.isfile(sfile): |
609 return sfile | 614 return sfile |
610 if not os.path.isabs(sfile): | 615 if not os.path.isabs(sfile): |
611 for rep in repositories: | 616 for rep in repositories: |
612 if os.path.isfile(os.path.join(rep, sfile)): | 617 if os.path.isfile(os.path.join(rep, sfile)): |
613 return sfile | 618 return sfile |
614 return None | 619 return None |
615 | 620 |
616 def _set_debug_values(options): | 621 def _set_debug_values(options): |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 # Here's where everything really happens. | 730 # Here's where everything really happens. |
726 | 731 |
727 # First order of business: set up default warnings and then | 732 # First order of business: set up default warnings and then |
728 # handle the user's warning options, so that we can issue (or | 733 # handle the user's warning options, so that we can issue (or |
729 # suppress) appropriate warnings about anything that might happen, | 734 # suppress) appropriate warnings about anything that might happen, |
730 # as configured by the user. | 735 # as configured by the user. |
731 | 736 |
732 default_warnings = [ SCons.Warnings.CorruptSConsignWarning, | 737 default_warnings = [ SCons.Warnings.CorruptSConsignWarning, |
733 SCons.Warnings.DeprecatedWarning, | 738 SCons.Warnings.DeprecatedWarning, |
734 SCons.Warnings.DuplicateEnvironmentWarning, | 739 SCons.Warnings.DuplicateEnvironmentWarning, |
| 740 SCons.Warnings.FutureReservedVariableWarning, |
735 SCons.Warnings.LinkWarning, | 741 SCons.Warnings.LinkWarning, |
736 SCons.Warnings.MissingSConscriptWarning, | 742 SCons.Warnings.MissingSConscriptWarning, |
737 SCons.Warnings.NoMD5ModuleWarning, | 743 SCons.Warnings.NoMD5ModuleWarning, |
738 SCons.Warnings.NoMetaclassSupportWarning, | 744 SCons.Warnings.NoMetaclassSupportWarning, |
739 SCons.Warnings.NoObjectCountWarning, | 745 SCons.Warnings.NoObjectCountWarning, |
740 SCons.Warnings.NoParallelSupportWarning, | 746 SCons.Warnings.NoParallelSupportWarning, |
741 SCons.Warnings.MisleadingKeywordsWarning, | 747 SCons.Warnings.MisleadingKeywordsWarning, |
742 SCons.Warnings.StackSizeWarning, ] | 748 SCons.Warnings.ReservedVariableWarning, |
| 749 SCons.Warnings.StackSizeWarning, |
| 750 ] |
743 | 751 |
744 for warning in default_warnings: | 752 for warning in default_warnings: |
745 SCons.Warnings.enableWarningClass(warning) | 753 SCons.Warnings.enableWarningClass(warning) |
746 SCons.Warnings._warningOut = _scons_internal_warning | 754 SCons.Warnings._warningOut = _scons_internal_warning |
747 SCons.Warnings.process_warn_strings(options.warn) | 755 SCons.Warnings.process_warn_strings(options.warn) |
748 | 756 |
749 # Now that we have the warnings configuration set up, we can actually | 757 # Now that we have the warnings configuration set up, we can actually |
750 # issue (or suppress) any warnings about warning-worthy things that | 758 # issue (or suppress) any warnings about warning-worthy things that |
751 # occurred while the command-line options were getting parsed. | 759 # occurred while the command-line options were getting parsed. |
752 try: | 760 try: |
(...skipping 17 matching lines...) Expand all Loading... |
770 cdir = _create_path(options.directory) | 778 cdir = _create_path(options.directory) |
771 try: | 779 try: |
772 os.chdir(cdir) | 780 os.chdir(cdir) |
773 except OSError: | 781 except OSError: |
774 sys.stderr.write("Could not change directory to %s\n" % cdir) | 782 sys.stderr.write("Could not change directory to %s\n" % cdir) |
775 | 783 |
776 target_top = None | 784 target_top = None |
777 if options.climb_up: | 785 if options.climb_up: |
778 target_top = '.' # directory to prepend to targets | 786 target_top = '.' # directory to prepend to targets |
779 script_dir = os.getcwd() # location of script | 787 script_dir = os.getcwd() # location of script |
780 while script_dir and not _SConstruct_exists(script_dir, options.reposito
ry): | 788 while script_dir and not _SConstruct_exists(script_dir, |
| 789 options.repository, |
| 790 options.file): |
781 script_dir, last_part = os.path.split(script_dir) | 791 script_dir, last_part = os.path.split(script_dir) |
782 if last_part: | 792 if last_part: |
783 target_top = os.path.join(last_part, target_top) | 793 target_top = os.path.join(last_part, target_top) |
784 else: | 794 else: |
785 script_dir = '' | 795 script_dir = '' |
786 if script_dir: | 796 if script_dir and script_dir != os.getcwd(): |
787 display("scons: Entering directory `%s'" % script_dir) | 797 display("scons: Entering directory `%s'" % script_dir) |
788 os.chdir(script_dir) | 798 os.chdir(script_dir) |
789 | 799 |
790 # Now that we're in the top-level SConstruct directory, go ahead | 800 # Now that we're in the top-level SConstruct directory, go ahead |
791 # and initialize the FS object that represents the file system, | 801 # and initialize the FS object that represents the file system, |
792 # and make it the build engine default. | 802 # and make it the build engine default. |
793 fs = SCons.Node.FS.get_default_fs() | 803 fs = SCons.Node.FS.get_default_fs() |
794 | 804 |
795 for rep in options.repository: | 805 for rep in options.repository: |
796 fs.Repository(rep) | 806 fs.Repository(rep) |
797 | 807 |
798 # Now that we have the FS object, the next order of business is to | 808 # Now that we have the FS object, the next order of business is to |
799 # check for an SConstruct file (or other specified config file). | 809 # check for an SConstruct file (or other specified config file). |
800 # If there isn't one, we can bail before doing any more work. | 810 # If there isn't one, we can bail before doing any more work. |
801 scripts = [] | 811 scripts = [] |
802 if options.file: | 812 if options.file: |
803 scripts.extend(options.file) | 813 scripts.extend(options.file) |
804 if not scripts: | 814 if not scripts: |
805 sfile = _SConstruct_exists(repositories=options.repository) | 815 sfile = _SConstruct_exists(repositories=options.repository, |
| 816 filelist=options.file) |
806 if sfile: | 817 if sfile: |
807 scripts.append(sfile) | 818 scripts.append(sfile) |
808 | 819 |
809 if not scripts: | 820 if not scripts: |
810 if options.help: | 821 if options.help: |
811 # There's no SConstruct, but they specified -h. | 822 # There's no SConstruct, but they specified -h. |
812 # Give them the options usage now, before we fail | 823 # Give them the options usage now, before we fail |
813 # trying to read a non-existent SConstruct file. | 824 # trying to read a non-existent SConstruct file. |
814 raise SConsPrintHelpException | 825 raise SConsPrintHelpException |
815 raise SCons.Errors.UserError, "No SConstruct file found." | 826 raise SCons.Errors.UserError, "No SConstruct file found." |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1259 sys.exit(2) | 1270 sys.exit(2) |
1260 except SyntaxError, e: | 1271 except SyntaxError, e: |
1261 _scons_syntax_error(e) | 1272 _scons_syntax_error(e) |
1262 except SCons.Errors.InternalError: | 1273 except SCons.Errors.InternalError: |
1263 _scons_internal_error() | 1274 _scons_internal_error() |
1264 except SCons.Errors.UserError, e: | 1275 except SCons.Errors.UserError, e: |
1265 _scons_user_error(e) | 1276 _scons_user_error(e) |
1266 except SConsPrintHelpException: | 1277 except SConsPrintHelpException: |
1267 parser.print_help() | 1278 parser.print_help() |
1268 exit_status = 0 | 1279 exit_status = 0 |
| 1280 except SCons.Errors.BuildError, e: |
| 1281 exit_status = e.exitstatus |
1269 except: | 1282 except: |
1270 # An exception here is likely a builtin Python exception Python | 1283 # An exception here is likely a builtin Python exception Python |
1271 # code in an SConscript file. Show them precisely what the | 1284 # code in an SConscript file. Show them precisely what the |
1272 # problem was and where it happened. | 1285 # problem was and where it happened. |
1273 SCons.Script._SConscript.SConscript_exception() | 1286 SCons.Script._SConscript.SConscript_exception() |
1274 sys.exit(2) | 1287 sys.exit(2) |
1275 | 1288 |
1276 memory_stats.print_stats() | 1289 memory_stats.print_stats() |
1277 count_stats.print_stats() | 1290 count_stats.print_stats() |
1278 | 1291 |
(...skipping 20 matching lines...) Expand all Loading... |
1299 ct = 0.0 | 1312 ct = 0.0 |
1300 else: | 1313 else: |
1301 ct = last_command_end - first_command_start | 1314 ct = last_command_end - first_command_start |
1302 scons_time = total_time - sconscript_time - ct | 1315 scons_time = total_time - sconscript_time - ct |
1303 print "Total build time: %f seconds"%total_time | 1316 print "Total build time: %f seconds"%total_time |
1304 print "Total SConscript file execution time: %f seconds"%sconscript_time | 1317 print "Total SConscript file execution time: %f seconds"%sconscript_time |
1305 print "Total SCons execution time: %f seconds"%scons_time | 1318 print "Total SCons execution time: %f seconds"%scons_time |
1306 print "Total command execution time: %f seconds"%ct | 1319 print "Total command execution time: %f seconds"%ct |
1307 | 1320 |
1308 sys.exit(exit_status) | 1321 sys.exit(exit_status) |
OLD | NEW |