| 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 |