Package SCons :: Package Script :: Module Main
[hide private]
[frames] | no frames]

Source Code for Module SCons.Script.Main

   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   
  14  # 
  15  # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation 
  16  # 
  17  # Permission is hereby granted, free of charge, to any person obtaining 
  18  # a copy of this software and associated documentation files (the 
  19  # "Software"), to deal in the Software without restriction, including 
  20  # without limitation the rights to use, copy, modify, merge, publish, 
  21  # distribute, sublicense, and/or sell copies of the Software, and to 
  22  # permit persons to whom the Software is furnished to do so, subject to 
  23  # the following conditions: 
  24  # 
  25  # The above copyright notice and this permission notice shall be included 
  26  # in all copies or substantial portions of the Software. 
  27  # 
  28  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
  29  # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
  30  # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
  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 
  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. 
  35  # 
  36   
  37  __revision__ = "src/engine/SCons/Script/Main.py 2928 2008/04/29 22:44:09 knight" 
  38   
  39  import SCons.compat 
  40   
  41  import os 
  42  import os.path 
  43  import string 
  44  import sys 
  45  import time 
  46  import traceback 
  47   
  48  # Strip the script directory from sys.path() so on case-insensitive 
  49  # (Windows) systems Python doesn't think that the "scons" script is the 
  50  # "SCons" package.  Replace it with our own version directory so, if 
  51  # if they're there, we pick up the right version of the build engine 
  52  # modules. 
  53  #sys.path = [os.path.join(sys.prefix, 
  54  #                         'lib', 
  55  #                         'scons-%d' % SCons.__version__)] + sys.path[1:] 
  56   
  57  import SCons.CacheDir 
  58  import SCons.Debug 
  59  import SCons.Defaults 
  60  import SCons.Environment 
  61  import SCons.Errors 
  62  import SCons.Job 
  63  import SCons.Node 
  64  import SCons.Node.FS 
  65  import SCons.SConf 
  66  import SCons.Script 
  67  import SCons.Taskmaster 
  68  import SCons.Util 
  69  import SCons.Warnings 
  70   
  71  import SCons.Script.Interactive 
  72   
73 -def fetch_win32_parallel_msg():
74 # A subsidiary function that exists solely to isolate this import 75 # so we don't have to pull it in on all platforms, and so that an 76 # in-line "import" statement in the _main() function below doesn't 77 # cause warnings about local names shadowing use of the 'SCons' 78 # globl in nest scopes and UnboundLocalErrors and the like in some 79 # versions (2.1) of Python. 80 import SCons.Platform.win32 81 SCons.Platform.win32.parallel_msg
82 83 # 84
85 -class SConsPrintHelpException(Exception):
86 pass
87 88 display = SCons.Util.display 89 progress_display = SCons.Util.DisplayEngine() 90 91 first_command_start = None 92 last_command_end = None 93
94 -class Progressor:
95 prev = '' 96 count = 0 97 target_string = '$TARGET' 98
99 - def __init__(self, obj, interval=1, file=None, overwrite=False):
100 if file is None: 101 file = sys.stdout 102 103 self.obj = obj 104 self.file = file 105 self.interval = interval 106 self.overwrite = overwrite 107 108 if callable(obj): 109 self.func = obj 110 elif SCons.Util.is_List(obj): 111 self.func = self.spinner 112 elif string.find(obj, self.target_string) != -1: 113 self.func = self.replace_string 114 else: 115 self.func = self.string
116
117 - def write(self, s):
118 self.file.write(s) 119 self.file.flush() 120 self.prev = s
121
122 - def erase_previous(self):
123 if self.prev: 124 length = len(self.prev) 125 if self.prev[-1] in ('\n', '\r'): 126 length = length - 1 127 self.write(' ' * length + '\r') 128 self.prev = ''
129
130 - def spinner(self, node):
131 self.write(self.obj[self.count % len(self.obj)])
132
133 - def string(self, node):
134 self.write(self.obj)
135
136 - def replace_string(self, node):
137 self.write(string.replace(self.obj, self.target_string, str(node)))
138
139 - def __call__(self, node):
140 self.count = self.count + 1 141 if (self.count % self.interval) == 0: 142 if self.overwrite: 143 self.erase_previous() 144 self.func(node)
145 146 ProgressObject = SCons.Util.Null() 147
148 -def Progress(*args, **kw):
149 global ProgressObject 150 ProgressObject = apply(Progressor, args, kw)
151 152 # Task control. 153 # 154 155 _BuildFailures = [] 156
157 -def GetBuildFailures():
158 return _BuildFailures
159
160 -class BuildTask(SCons.Taskmaster.Task):
161 """An SCons build task.""" 162 progress = ProgressObject 163
164 - def display(self, message):
165 display('scons: ' + message)
166
167 - def prepare(self):
168 self.progress(self.targets[0]) 169 return SCons.Taskmaster.Task.prepare(self)
170
171 - def needs_execute(self):
172 target = self.targets[0] 173 if target.get_state() == SCons.Node.executing: 174 return True 175 else: 176 if self.top and target.has_builder(): 177 display("scons: `%s' is up to date." % str(self.node)) 178 return False
179
180 - def execute(self):
181 if print_time: 182 start_time = time.time() 183 global first_command_start 184 if first_command_start is None: 185 first_command_start = start_time 186 SCons.Taskmaster.Task.execute(self) 187 if print_time: 188 global cumulative_command_time 189 global last_command_end 190 finish_time = time.time() 191 last_command_end = finish_time 192 cumulative_command_time = cumulative_command_time+finish_time-start_time 193 sys.stdout.write("Command execution time: %f seconds\n"%(finish_time-start_time))
194
195 - def do_failed(self, status=2):
196 _BuildFailures.append(self.exception[1]) 197 global exit_status 198 if self.options.ignore_errors: 199 SCons.Taskmaster.Task.executed(self) 200 elif self.options.keep_going: 201 SCons.Taskmaster.Task.fail_continue(self) 202 exit_status = status 203 else: 204 SCons.Taskmaster.Task.fail_stop(self) 205 exit_status = status
206
207 - def executed(self):
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 errstr="Do not know how to make target `%s'." % t 212 sys.stderr.write("scons: *** " + errstr) 213 if not self.options.keep_going: 214 sys.stderr.write(" Stop.") 215 sys.stderr.write("\n") 216 try: 217 raise SCons.Errors.BuildError(t, errstr) 218 except: 219 self.exception_set() 220 self.do_failed() 221 else: 222 print "scons: Nothing to be done for `%s'." % t 223 SCons.Taskmaster.Task.executed(self) 224 else: 225 SCons.Taskmaster.Task.executed(self)
226
227 - def failed(self):
228 # Handle the failure of a build task. The primary purpose here 229 # is to display the various types of Errors and Exceptions 230 # appropriately. 231 status = 2 232 exc_info = self.exc_info() 233 try: 234 t, e, tb = exc_info 235 except ValueError: 236 t, e = exc_info 237 tb = None 238 if t is None: 239 # The Taskmaster didn't record an exception for this Task; 240 # see if the sys module has one. 241 t, e = sys.exc_info()[:2] 242 243 def nodestring(n): 244 if not SCons.Util.is_List(n): 245 n = [ n ] 246 return string.join(map(str, n), ', ')
247 248 errfmt = "scons: *** [%s] %s\n" 249 250 if t == SCons.Errors.BuildError: 251 tname = nodestring(e.node) 252 errstr = e.errstr 253 if e.filename: 254 errstr = e.filename + ': ' + errstr 255 sys.stderr.write(errfmt % (tname, errstr)) 256 elif t == SCons.Errors.TaskmasterException: 257 tname = nodestring(e.node) 258 sys.stderr.write(errfmt % (tname, e.errstr)) 259 type, value, trace = e.exc_info 260 traceback.print_exception(type, value, trace) 261 elif t == SCons.Errors.ExplicitExit: 262 status = e.status 263 tname = nodestring(e.node) 264 errstr = 'Explicit exit, status %s' % status 265 sys.stderr.write(errfmt % (tname, errstr)) 266 else: 267 if e is None: 268 e = t 269 s = str(e) 270 if t == SCons.Errors.StopError and not self.options.keep_going: 271 s = s + ' Stop.' 272 sys.stderr.write("scons: *** %s\n" % s) 273 274 if tb and print_stacktrace: 275 sys.stderr.write("scons: internal stack trace:\n") 276 traceback.print_tb(tb, file=sys.stderr) 277 278 self.do_failed(status) 279 280 self.exc_clear()
281
282 - def postprocess(self):
283 if self.top: 284 t = self.targets[0] 285 for tp in self.options.tree_printers: 286 tp.display(t) 287 if self.options.debug_includes: 288 tree = t.render_include_tree() 289 if tree: 290 print 291 print tree 292 SCons.Taskmaster.Task.postprocess(self)
293
294 - def make_ready(self):
295 """Make a task ready for execution""" 296 SCons.Taskmaster.Task.make_ready(self) 297 if self.out_of_date and self.options.debug_explain: 298 explanation = self.out_of_date[0].explain() 299 if explanation: 300 sys.stdout.write("scons: " + explanation)
301
302 -class CleanTask(SCons.Taskmaster.Task):
303 """An SCons clean task."""
304 - def fs_delete(self, path