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