3 This file implements the main() function used by the scons script.
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,
15 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
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:
25 # The above copyright notice and this permission notice shall be included
26 # in all copies or substantial portions of the Software.
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.
37 __revision__ = "src/engine/SCons/Script/__init__.py 3842 2008/12/20 22:59:52 scons"
40 start_time = time.time()
47 # Special chicken-and-egg handling of the "--debug=memoizer" flag:
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.
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.
61 _args = sys.argv + string.split(os.environ.get('SCONSFLAGS', ''))
62 if "--debug=memoizer" in _args:
66 SCons.Memoize.EnableMemoization()
67 except SCons.Warnings.Warning:
68 # Some warning was thrown (inability to --debug=memoizer on
69 # Python 1.5.2 because it doesn't have metaclasses). Arrange
70 # for it to be displayed or not after warnings are configured.
72 exc_type, exc_value, tb = sys.exc_info()
73 Main.delayed_warnings.append((exc_type, exc_value))
78 import SCons.Environment
87 import SCons.Variables
94 # The following are global class definitions and variables that used to
95 # live directly in this module back before 0.96.90, when it contained
96 # a lot of code. Some SConscript files in widely-distributed packages
97 # (Blender is the specific example) actually reached into SCons.Script
98 # directly to use some of these. Rather than break those SConscript
99 # files, we're going to propagate these names into the SCons.Script
102 # Some of these are commented out because it's *really* unlikely anyone
103 # used them, but we're going to leave the comment here to try to make
104 # it obvious what to do if the situation arises.
105 BuildTask = Main.BuildTask
106 CleanTask = Main.CleanTask
107 QuestionTask = Main.QuestionTask
108 #PrintHelp = Main.PrintHelp
109 #SConscriptSettableOptions = Main.SConscriptSettableOptions
111 AddOption = Main.AddOption
112 GetOption = Main.GetOption
113 SetOption = Main.SetOption
114 Progress = Main.Progress
115 GetBuildFailures = Main.GetBuildFailures
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
134 _SConscript = SConscript
136 call_stack = _SConscript.call_stack
139 Action = SCons.Action.Action
140 AddMethod = SCons.Util.AddMethod
141 AllowSubstExceptions = SCons.Subst.SetAllowableExceptions
142 Builder = SCons.Builder.Builder
143 Configure = _SConscript.Configure
144 Environment = SCons.Environment.Environment
145 #OptParser = SCons.SConsOptions.OptParser
146 FindPathDirs = SCons.Scanner.FindPathDirs
147 Platform = SCons.Platform.Platform
148 Return = _SConscript.Return
149 Scanner = SCons.Scanner.Base
150 Tool = SCons.Tool.Tool
151 WhereIs = SCons.Util.WhereIs
154 BoolVariable = SCons.Variables.BoolVariable
155 EnumVariable = SCons.Variables.EnumVariable
156 ListVariable = SCons.Variables.ListVariable
157 PackageVariable = SCons.Variables.PackageVariable
158 PathVariable = SCons.Variables.PathVariable
160 # Deprecated names that will go away some day.
161 BoolOption = SCons.Options.BoolOption
162 EnumOption = SCons.Options.EnumOption
163 ListOption = SCons.Options.ListOption
164 PackageOption = SCons.Options.PackageOption
165 PathOption = SCons.Options.PathOption
168 Chmod = SCons.Defaults.Chmod
169 Copy = SCons.Defaults.Copy
170 Delete = SCons.Defaults.Delete
171 Mkdir = SCons.Defaults.Mkdir
172 Move = SCons.Defaults.Move
173 Touch = SCons.Defaults.Touch
175 # Pre-made, public scanners.
176 CScanner = SCons.Tool.CScanner
177 DScanner = SCons.Tool.DScanner
178 DirScanner = SCons.Defaults.DirScanner
179 ProgramScanner = SCons.Tool.ProgramScanner
180 SourceFileScanner = SCons.Tool.SourceFileScanner
182 # Functions we might still convert to Environment methods.
183 CScan = SCons.Defaults.CScan
184 DefaultEnvironment = SCons.Defaults.DefaultEnvironment
186 # Other variables we provide.
187 class TargetList(UserList.UserList):
188 def _do_nothing(self, *args, **kw):
190 def _add_Default(self, list):
197 BUILD_TARGETS = TargetList()
198 COMMAND_LINE_TARGETS = []
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()
212 def _Add_Arguments(alist):
214 a, b = string.split(arg, '=', 1)
216 ARGLIST.append((a, b))
218 def _Add_Targets(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
228 def _Set_Default_Targets_Has_Been_Called(d, fs):
229 return DEFAULT_TARGETS
231 def _Set_Default_Targets_Has_Not_Been_Called(d, fs):
236 _Get_Default_Targets = _Set_Default_Targets_Has_Not_Been_Called
238 def _Set_Default_Targets(env, tlist):
239 global DEFAULT_TARGETS
240 global _Get_Default_Targets
241 _Get_Default_Targets = _Set_Default_Targets_Has_Been_Called
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])
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)
263 def HelpFunction(text):
265 if SCons.Script.help_text is None:
266 SCons.Script.help_text = text
268 help_text = help_text + text
271 # Will be non-zero if we are reading an SConscript file.
272 sconscript_reading = 0
275 def Variables(files=[], args=ARGUMENTS):
276 return SCons.Variables.Variables(files, args)
278 def Options(files=[], args=ARGUMENTS):
279 return SCons.Options.Options(files, args)
281 # The list of global functions to add to the SConscript name space
282 # that end up calling corresponding methods or Builders in the
283 # DefaultEnvironment().
284 GlobalDefaultEnvironmentFunctions = [
285 # Methods from the SConsEnvironment class, above.
287 'EnsurePythonVersion',
288 'EnsureSConsVersion',
294 #'SConscript', is handled separately, below.
297 # Methods from the Environment.Base class.
305 #The Command() method is handled separately, below.
315 'FindInstalledFiles',
340 GlobalDefaultBuilders = [
341 # Supported builders.
368 for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
369 exec "%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name))
372 # There are a handful of variables that used to live in the
373 # Script/SConscript.py module that some SConscript files out there were
374 # accessing directly as SCons.Script.SConscript.*. The problem is that
375 # "SConscript" in this namespace is no longer a module, it's a global
376 # function call--or more precisely, an object that implements a global
377 # function call through the default Environment. Nevertheless, we can
378 # maintain backwards compatibility for SConscripts that were reaching in
379 # this way by hanging some attributes off the "SConscript" object here.
380 SConscript = _SConscript.DefaultEnvironmentCall('SConscript')
382 # Make SConscript look enough like the module it used to be so
383 # that pychecker doesn't barf.
384 SConscript.__name__ = 'SConscript'
386 SConscript.Arguments = ARGUMENTS
387 SConscript.ArgList = ARGLIST
388 SConscript.BuildTargets = BUILD_TARGETS
389 SConscript.CommandLineTargets = COMMAND_LINE_TARGETS
390 SConscript.DefaultTargets = DEFAULT_TARGETS
392 # The global Command() function must be handled differently than the
393 # global functions for other construction environment methods because
394 # we want people to be able to use Actions that must expand $TARGET
395 # and $SOURCE later, when (and if) the Action is invoked to build
396 # the target(s). We do this with the subst=1 argument, which creates
397 # a DefaultEnvironmentCall instance that wraps up a normal default
398 # construction environment that performs variable substitution, not a
399 # proxy that doesn't.
401 # There's a flaw here, though, because any other $-variables on a command
402 # line will *also* be expanded, each to a null string, but that should
403 # only be a problem in the unusual case where someone was passing a '$'
404 # on a command line and *expected* the $ to get through to the shell
405 # because they were calling Command() and not env.Command()... This is
406 # unlikely enough that we're going to leave this as is and cross that
407 # bridge if someone actually comes to it.
408 Command = _SConscript.DefaultEnvironmentCall('Command', subst=1)