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