OLD | NEW |
(Empty) | |
| 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, 2009, 2010 The S
Cons 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/__init__.py 5134 2010/08/16 23:02:40 bde
egan" |
| 38 |
| 39 import time |
| 40 start_time = time.time() |
| 41 |
| 42 import collections |
| 43 import os |
| 44 import sys |
| 45 |
| 46 # Special chicken-and-egg handling of the "--debug=memoizer" flag: |
| 47 # |
| 48 # SCons.Memoize contains a metaclass implementation that affects how |
| 49 # the other classes are instantiated. The Memoizer may add shim methods |
| 50 # to classes that have methods that cache computed values in order to |
| 51 # count and report the hits and misses. |
| 52 # |
| 53 # If we wait to enable the Memoization until after we've parsed the |
| 54 # command line options normally, it will be too late, because the Memoizer |
| 55 # will have already analyzed the classes that it's Memoizing and decided |
| 56 # to not add the shims. So we use a special-case, up-front check for |
| 57 # the "--debug=memoizer" flag and enable Memoizer before we import any |
| 58 # of the other modules that use it. |
| 59 |
| 60 _args = sys.argv + os.environ.get('SCONSFLAGS', '').split() |
| 61 if "--debug=memoizer" in _args: |
| 62 import SCons.Memoize |
| 63 import SCons.Warnings |
| 64 try: |
| 65 SCons.Memoize.EnableMemoization() |
| 66 except SCons.Warnings.Warning: |
| 67 # Some warning was thrown. Arrange for it to be displayed |
| 68 # or not after warnings are configured. |
| 69 import Main |
| 70 exc_type, exc_value, tb = sys.exc_info() |
| 71 Main.delayed_warnings.append((exc_type, exc_value)) |
| 72 del _args |
| 73 |
| 74 import SCons.Action |
| 75 import SCons.Builder |
| 76 import SCons.Environment |
| 77 import SCons.Node.FS |
| 78 import SCons.Options |
| 79 import SCons.Platform |
| 80 import SCons.Scanner |
| 81 import SCons.SConf |
| 82 import SCons.Subst |
| 83 import SCons.Tool |
| 84 import SCons.Util |
| 85 import SCons.Variables |
| 86 import SCons.Defaults |
| 87 |
| 88 import Main |
| 89 |
| 90 main = Main.main |
| 91 |
| 92 # The following are global class definitions and variables that used to |
| 93 # live directly in this module back before 0.96.90, when it contained |
| 94 # a lot of code. Some SConscript files in widely-distributed packages |
| 95 # (Blender is the specific example) actually reached into SCons.Script |
| 96 # directly to use some of these. Rather than break those SConscript |
| 97 # files, we're going to propagate these names into the SCons.Script |
| 98 # namespace here. |
| 99 # |
| 100 # Some of these are commented out because it's *really* unlikely anyone |
| 101 # used them, but we're going to leave the comment here to try to make |
| 102 # it obvious what to do if the situation arises. |
| 103 BuildTask = Main.BuildTask |
| 104 CleanTask = Main.CleanTask |
| 105 QuestionTask = Main.QuestionTask |
| 106 #PrintHelp = Main.PrintHelp |
| 107 #SConscriptSettableOptions = Main.SConscriptSettableOptions |
| 108 |
| 109 AddOption = Main.AddOption |
| 110 GetOption = Main.GetOption |
| 111 SetOption = Main.SetOption |
| 112 Progress = Main.Progress |
| 113 GetBuildFailures = Main.GetBuildFailures |
| 114 |
| 115 #keep_going_on_error = Main.keep_going_on_error |
| 116 #print_dtree = Main.print_dtree |
| 117 #print_explanations = Main.print_explanations |
| 118 #print_includes = Main.print_includes |
| 119 #print_objects = Main.print_objects |
| 120 #print_time = Main.print_time |
| 121 #print_tree = Main.print_tree |
| 122 #memory_stats = Main.memory_stats |
| 123 #ignore_errors = Main.ignore_errors |
| 124 #sconscript_time = Main.sconscript_time |
| 125 #command_time = Main.command_time |
| 126 #exit_status = Main.exit_status |
| 127 #profiling = Main.profiling |
| 128 #repositories = Main.repositories |
| 129 |
| 130 # |
| 131 import SConscript |
| 132 _SConscript = SConscript |
| 133 |
| 134 call_stack = _SConscript.call_stack |
| 135 |
| 136 # |
| 137 Action = SCons.Action.Action |
| 138 AddMethod = SCons.Util.AddMethod |
| 139 AllowSubstExceptions = SCons.Subst.SetAllowableExceptions |
| 140 Builder = SCons.Builder.Builder |
| 141 Configure = _SConscript.Configure |
| 142 Environment = SCons.Environment.Environment |
| 143 #OptParser = SCons.SConsOptions.OptParser |
| 144 FindPathDirs = SCons.Scanner.FindPathDirs |
| 145 Platform = SCons.Platform.Platform |
| 146 Return = _SConscript.Return |
| 147 Scanner = SCons.Scanner.Base |
| 148 Tool = SCons.Tool.Tool |
| 149 WhereIs = SCons.Util.WhereIs |
| 150 |
| 151 # |
| 152 BoolVariable = SCons.Variables.BoolVariable |
| 153 EnumVariable = SCons.Variables.EnumVariable |
| 154 ListVariable = SCons.Variables.ListVariable |
| 155 PackageVariable = SCons.Variables.PackageVariable |
| 156 PathVariable = SCons.Variables.PathVariable |
| 157 |
| 158 # Deprecated names that will go away some day. |
| 159 BoolOption = SCons.Options.BoolOption |
| 160 EnumOption = SCons.Options.EnumOption |
| 161 ListOption = SCons.Options.ListOption |
| 162 PackageOption = SCons.Options.PackageOption |
| 163 PathOption = SCons.Options.PathOption |
| 164 |
| 165 # Action factories. |
| 166 Chmod = SCons.Defaults.Chmod |
| 167 Copy = SCons.Defaults.Copy |
| 168 Delete = SCons.Defaults.Delete |
| 169 Mkdir = SCons.Defaults.Mkdir |
| 170 Move = SCons.Defaults.Move |
| 171 Touch = SCons.Defaults.Touch |
| 172 |
| 173 # Pre-made, public scanners. |
| 174 CScanner = SCons.Tool.CScanner |
| 175 DScanner = SCons.Tool.DScanner |
| 176 DirScanner = SCons.Defaults.DirScanner |
| 177 ProgramScanner = SCons.Tool.ProgramScanner |
| 178 SourceFileScanner = SCons.Tool.SourceFileScanner |
| 179 |
| 180 # Functions we might still convert to Environment methods. |
| 181 CScan = SCons.Defaults.CScan |
| 182 DefaultEnvironment = SCons.Defaults.DefaultEnvironment |
| 183 |
| 184 # Other variables we provide. |
| 185 class TargetList(collections.UserList): |
| 186 def _do_nothing(self, *args, **kw): |
| 187 pass |
| 188 def _add_Default(self, list): |
| 189 self.extend(list) |
| 190 def _clear(self): |
| 191 del self[:] |
| 192 |
| 193 ARGUMENTS = {} |
| 194 ARGLIST = [] |
| 195 BUILD_TARGETS = TargetList() |
| 196 COMMAND_LINE_TARGETS = [] |
| 197 DEFAULT_TARGETS = [] |
| 198 |
| 199 # BUILD_TARGETS can be modified in the SConscript files. If so, we |
| 200 # want to treat the modified BUILD_TARGETS list as if they specified |
| 201 # targets on the command line. To do that, though, we need to know if |
| 202 # BUILD_TARGETS was modified through "official" APIs or by hand. We do |
| 203 # this by updating two lists in parallel, the documented BUILD_TARGETS |
| 204 # list, above, and this internal _build_plus_default targets list which |
| 205 # should only have "official" API changes. Then Script/Main.py can |
| 206 # compare these two afterwards to figure out if the user added their |
| 207 # own targets to BUILD_TARGETS. |
| 208 _build_plus_default = TargetList() |
| 209 |
| 210 def _Add_Arguments(alist): |
| 211 for arg in alist: |
| 212 a, b = arg.split('=', 1) |
| 213 ARGUMENTS[a] = b |
| 214 ARGLIST.append((a, b)) |
| 215 |
| 216 def _Add_Targets(tlist): |
| 217 if tlist: |
| 218 COMMAND_LINE_TARGETS.extend(tlist) |
| 219 BUILD_TARGETS.extend(tlist) |
| 220 BUILD_TARGETS._add_Default = BUILD_TARGETS._do_nothing |
| 221 BUILD_TARGETS._clear = BUILD_TARGETS._do_nothing |
| 222 _build_plus_default.extend(tlist) |
| 223 _build_plus_default._add_Default = _build_plus_default._do_nothing |
| 224 _build_plus_default._clear = _build_plus_default._do_nothing |
| 225 |
| 226 def _Set_Default_Targets_Has_Been_Called(d, fs): |
| 227 return DEFAULT_TARGETS |
| 228 |
| 229 def _Set_Default_Targets_Has_Not_Been_Called(d, fs): |
| 230 if d is None: |
| 231 d = [fs.Dir('.')] |
| 232 return d |
| 233 |
| 234 _Get_Default_Targets = _Set_Default_Targets_Has_Not_Been_Called |
| 235 |
| 236 def _Set_Default_Targets(env, tlist): |
| 237 global DEFAULT_TARGETS |
| 238 global _Get_Default_Targets |
| 239 _Get_Default_Targets = _Set_Default_Targets_Has_Been_Called |
| 240 for t in tlist: |
| 241 if t is None: |
| 242 # Delete the elements from the list in-place, don't |
| 243 # reassign an empty list to DEFAULT_TARGETS, so that the |
| 244 # variables will still point to the same object we point to. |
| 245 del DEFAULT_TARGETS[:] |
| 246 BUILD_TARGETS._clear() |
| 247 _build_plus_default._clear() |
| 248 elif isinstance(t, SCons.Node.Node): |
| 249 DEFAULT_TARGETS.append(t) |
| 250 BUILD_TARGETS._add_Default([t]) |
| 251 _build_plus_default._add_Default([t]) |
| 252 else: |
| 253 nodes = env.arg2nodes(t, env.fs.Entry) |
| 254 DEFAULT_TARGETS.extend(nodes) |
| 255 BUILD_TARGETS._add_Default(nodes) |
| 256 _build_plus_default._add_Default(nodes) |
| 257 |
| 258 # |
| 259 help_text = None |
| 260 |
| 261 def HelpFunction(text): |
| 262 global help_text |
| 263 if SCons.Script.help_text is None: |
| 264 SCons.Script.help_text = text |
| 265 else: |
| 266 help_text = help_text + text |
| 267 |
| 268 # |
| 269 # Will be non-zero if we are reading an SConscript file. |
| 270 sconscript_reading = 0 |
| 271 |
| 272 # |
| 273 def Variables(files=[], args=ARGUMENTS): |
| 274 return SCons.Variables.Variables(files, args) |
| 275 |
| 276 def Options(files=[], args=ARGUMENTS): |
| 277 return SCons.Options.Options(files, args) |
| 278 |
| 279 # The list of global functions to add to the SConscript name space |
| 280 # that end up calling corresponding methods or Builders in the |
| 281 # DefaultEnvironment(). |
| 282 GlobalDefaultEnvironmentFunctions = [ |
| 283 # Methods from the SConsEnvironment class, above. |
| 284 'Default', |
| 285 'EnsurePythonVersion', |
| 286 'EnsureSConsVersion', |
| 287 'Exit', |
| 288 'Export', |
| 289 'GetLaunchDir', |
| 290 'Help', |
| 291 'Import', |
| 292 #'SConscript', is handled separately, below. |
| 293 'SConscriptChdir', |
| 294 |
| 295 # Methods from the Environment.Base class. |
| 296 'AddPostAction', |
| 297 'AddPreAction', |
| 298 'Alias', |
| 299 'AlwaysBuild', |
| 300 'BuildDir', |
| 301 'CacheDir', |
| 302 'Clean', |
| 303 #The Command() method is handled separately, below. |
| 304 'Decider', |
| 305 'Depends', |
| 306 'Dir', |
| 307 'NoClean', |
| 308 'NoCache', |
| 309 'Entry', |
| 310 'Execute', |
| 311 'File', |
| 312 'FindFile', |
| 313 'FindInstalledFiles', |
| 314 'FindSourceFiles', |
| 315 'Flatten', |
| 316 'GetBuildPath', |
| 317 'Glob', |
| 318 'Ignore', |
| 319 'Install', |
| 320 'InstallAs', |
| 321 'Literal', |
| 322 'Local', |
| 323 'ParseDepends', |
| 324 'Precious', |
| 325 'Repository', |
| 326 'Requires', |
| 327 'SConsignFile', |
| 328 'SideEffect', |
| 329 'SourceCode', |
| 330 'SourceSignatures', |
| 331 'Split', |
| 332 'Tag', |
| 333 'TargetSignatures', |
| 334 'Value', |
| 335 'VariantDir', |
| 336 ] |
| 337 |
| 338 GlobalDefaultBuilders = [ |
| 339 # Supported builders. |
| 340 'CFile', |
| 341 'CXXFile', |
| 342 'DVI', |
| 343 'Jar', |
| 344 'Java', |
| 345 'JavaH', |
| 346 'Library', |
| 347 'M4', |
| 348 'MSVSProject', |
| 349 'Object', |
| 350 'PCH', |
| 351 'PDF', |
| 352 'PostScript', |
| 353 'Program', |
| 354 'RES', |
| 355 'RMIC', |
| 356 'SharedLibrary', |
| 357 'SharedObject', |
| 358 'StaticLibrary', |
| 359 'StaticObject', |
| 360 'Tar', |
| 361 'TypeLibrary', |
| 362 'Zip', |
| 363 'Package', |
| 364 ] |
| 365 |
| 366 for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders: |
| 367 exec "%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name)) |
| 368 del name |
| 369 |
| 370 # There are a handful of variables that used to live in the |
| 371 # Script/SConscript.py module that some SConscript files out there were |
| 372 # accessing directly as SCons.Script.SConscript.*. The problem is that |
| 373 # "SConscript" in this namespace is no longer a module, it's a global |
| 374 # function call--or more precisely, an object that implements a global |
| 375 # function call through the default Environment. Nevertheless, we can |
| 376 # maintain backwards compatibility for SConscripts that were reaching in |
| 377 # this way by hanging some attributes off the "SConscript" object here. |
| 378 SConscript = _SConscript.DefaultEnvironmentCall('SConscript') |
| 379 |
| 380 # Make SConscript look enough like the module it used to be so |
| 381 # that pychecker doesn't barf. |
| 382 SConscript.__name__ = 'SConscript' |
| 383 |
| 384 SConscript.Arguments = ARGUMENTS |
| 385 SConscript.ArgList = ARGLIST |
| 386 SConscript.BuildTargets = BUILD_TARGETS |
| 387 SConscript.CommandLineTargets = COMMAND_LINE_TARGETS |
| 388 SConscript.DefaultTargets = DEFAULT_TARGETS |
| 389 |
| 390 # The global Command() function must be handled differently than the |
| 391 # global functions for other construction environment methods because |
| 392 # we want people to be able to use Actions that must expand $TARGET |
| 393 # and $SOURCE later, when (and if) the Action is invoked to build |
| 394 # the target(s). We do this with the subst=1 argument, which creates |
| 395 # a DefaultEnvironmentCall instance that wraps up a normal default |
| 396 # construction environment that performs variable substitution, not a |
| 397 # proxy that doesn't. |
| 398 # |
| 399 # There's a flaw here, though, because any other $-variables on a command |
| 400 # line will *also* be expanded, each to a null string, but that should |
| 401 # only be a problem in the unusual case where someone was passing a '$' |
| 402 # on a command line and *expected* the $ to get through to the shell |
| 403 # because they were calling Command() and not env.Command()... This is |
| 404 # unlikely enough that we're going to leave this as is and cross that |
| 405 # bridge if someone actually comes to it. |
| 406 Command = _SConscript.DefaultEnvironmentCall('Command', subst=1) |
| 407 |
| 408 # Local Variables: |
| 409 # tab-width:4 |
| 410 # indent-tabs-mode:nil |
| 411 # End: |
| 412 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |