summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Script
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2007-07-11 11:26:34 (GMT)
committerSteven Knight <knight@baldmt.com>2007-07-11 11:26:34 (GMT)
commit20f1ce98ac72261e08700a16c023f503fc706242 (patch)
tree7e54fb6d2f1c0a35051f70c1da04fccb18966cae /src/engine/SCons/Script
parentf311f5ac8b8da71b93166bf566aa0a89c91abd50 (diff)
downloadSCons-20f1ce98ac72261e08700a16c023f503fc706242.zip
SCons-20f1ce98ac72261e08700a16c023f503fc706242.tar.gz
SCons-20f1ce98ac72261e08700a16c023f503fc706242.tar.bz2
Merged revisions 1968-2115 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core ........ r1970 | stevenknight | 2007-06-01 18:22:37 -0500 (Fri, 01 Jun 2007) | 4 lines Import a vanilla Python 2.3 version of textwrap.py into the compatibility library, so we can track the changes we'll make to it. (This isn't actually used yet.) ........ r1971 | stevenknight | 2007-06-02 00:38:20 -0500 (Sat, 02 Jun 2007) | 2 lines Add a compatibility module for the textwrap.py module introduced in Python 2.3. ........ r1972 | stevenknight | 2007-06-02 00:39:26 -0500 (Sat, 02 Jun 2007) | 2 lines Remove spurious <para> tags. ........ r1973 | stevenknight | 2007-06-03 08:57:05 -0500 (Sun, 03 Jun 2007) | 2 lines Improved help-text generation using a textwrap.TextWrapper object. ........ r1991 | stevenknight | 2007-06-10 16:03:18 -0500 (Sun, 10 Jun 2007) | 3 lines Add compatibility versions of the all() and any() functions introduced in Python 2.5. ........ r1992 | stevenknight | 2007-06-10 17:02:18 -0500 (Sun, 10 Jun 2007) | 8 lines SCons-time portability fixes for Python 2.[12]: -- Use "from __future__ import nested_scopes". -- Create "False" and "True" builtins -- Work around the lack of a "prefix =" keyword argument to the Python 2.[12] version of the mktemp module. -- Accomodate pickier single-element tuple syntax. ........ r1993 | stevenknight | 2007-06-10 17:27:43 -0500 (Sun, 10 Jun 2007) | 3 lines Delay instantiation of pstat.Stats objects until after we override sys.stdout, which as of Python 2.5 is captured when the object is created. ........ r1994 | stevenknight | 2007-06-10 21:22:42 -0500 (Sun, 10 Jun 2007) | 6 lines Update various tests to handle the File "SConstruct", line 1, in <module> Messages in Python 2.5. ........ r1995 | stevenknight | 2007-06-10 21:32:16 -0500 (Sun, 10 Jun 2007) | 3 lines Update tests to not raise strings as exceptions, which has been deprecated in Python 2.5. ........ r1996 | stevenknight | 2007-06-10 21:41:57 -0500 (Sun, 10 Jun 2007) | 3 lines Fix the Scanner hash unit test for Python 2.5. (Yes, it still works on previous versions, too.) ........ r1997 | stevenknight | 2007-06-10 21:55:46 -0500 (Sun, 10 Jun 2007) | 3 lines Make the mock Node object's side_effect attribute a list, so it's iterable in Python 2.1 as well. ........ r1998 | stevenknight | 2007-06-10 22:04:26 -0500 (Sun, 10 Jun 2007) | 3 lines Append an explicit tuple to the delayed_warnings list if there are problems interpreting --debug=memoizer. ........ r1999 | stevenknight | 2007-06-11 11:09:07 -0500 (Mon, 11 Jun 2007) | 2 lines Fix --debug=time with -j when no arguments are rebuilt (all up-to-date). ........ r2007 | stevenknight | 2007-06-14 13:56:35 -0500 (Thu, 14 Jun 2007) | 4 lines Performance improvement when looking up Nodes: don't use is_String(), just check for the initial '#' that specifies a top-relative lookup, and handle the exceptions. ........ r2008 | stevenknight | 2007-06-14 16:57:47 -0500 (Thu, 14 Jun 2007) | 11 lines First step in refactoring command-line flag processing: Split out the current processing into its own module, with minimal additional changes. Among the minimal changes: -- Store delayed warnings (for deprecated --debug= keywords) in the option parser object, not in a global variable. -- Remove the OptParser variable itself from the SCons.Script globals. It's going to change significantly (and no one's probably using it anyway). -- Don't move definition of the --version output with the OptParser, keep it in Main.py. ........ r2009 | stevenknight | 2007-06-15 08:15:25 -0500 (Fri, 15 Jun 2007) | 3 lines Refactor the test/explain.py script into three individual scripts so it's easier to deal with. ........ r2010 | stevenknight | 2007-06-15 09:49:07 -0500 (Fri, 15 Jun 2007) | 3 lines Handle Aliases in --debug=explain. This is kind of hard-coded for the normal lookup, and should be better handled by the signature refactoring. ........ r2011 | stevenknight | 2007-06-15 17:25:37 -0500 (Fri, 15 Jun 2007) | 5 lines Refactor use of the command-line parser object so it's localized to the top-level main() function, and not passed down through _exec_main() or to _main() itself. Replace its functionality with use of an exception to signal that the top-level main() function should print its help message. ........ r2012 | stevenknight | 2007-06-17 23:34:26 -0500 (Sun, 17 Jun 2007) | 2 lines Remove unnecessary import of __main__. ........ r2013 | stevenknight | 2007-06-17 23:48:06 -0500 (Sun, 17 Jun 2007) | 2 lines Pass the options object to _main(), don't use a global. ........ r2014 | stevenknight | 2007-06-18 00:12:09 -0500 (Mon, 18 Jun 2007) | 6 lines Qt test fixes for Windows: Link against a static library created by the test infrastructure, not a shared library. Escape backslashes in Windows path names. Skip test/QT/Tool.py if Qt isn't installed. ........ r2015 | stevenknight | 2007-06-18 10:46:17 -0500 (Mon, 18 Jun 2007) | 3 lines Support GetOption('no_exec'), and update test/NodeOps.py to use it instead of reaching into the SCons.Script.Main internals. ........ r2016 | stevenknight | 2007-06-18 11:04:39 -0500 (Mon, 18 Jun 2007) | 4 lines Restore use of a global delayed_warnings variable so the chicken-and-egg warning from trying to use --debug=memoizer on Python versions without metaclasses has somewhere to go. ........ r2017 | stevenknight | 2007-06-18 11:37:59 -0500 (Mon, 18 Jun 2007) | 3 lines Have the test infrastructure create a mock Qt shared library on UNIX, static library on Windows. ........ r2018 | stevenknight | 2007-06-18 11:48:10 -0500 (Mon, 18 Jun 2007) | 2 lines Pull more globals into the command-line parser options object. ........ r2023 | stevenknight | 2007-06-19 16:46:02 -0500 (Tue, 19 Jun 2007) | 3 lines Refactor the __checkClass() and must_be_a_Dir() methods into a more general and more efficient must_be_same() method. ........ r2025 | stevenknight | 2007-06-19 20:56:10 -0500 (Tue, 19 Jun 2007) | 3 lines More clean up: change various self.fs.Entry() calls to calls through the bound directory.Entry() method. ........ r2033 | stevenknight | 2007-06-20 20:03:23 -0500 (Wed, 20 Jun 2007) | 5 lines The --debug=count option doesn't work when run with Python - O, or from optimized compiled Python modules (*.pyo files), because the counting is all within "#if __debug__:" blocks that get stripped. Print a warning so it doesn't look like --debug=count is broken. ........ r2037 | stevenknight | 2007-06-21 10:42:40 -0500 (Thu, 21 Jun 2007) | 3 lines Replace the _stripixes() function with a more efficient/readable version that was checked in, but commented out, prior to 0.96.96. ........ r2040 | stevenknight | 2007-06-21 12:18:57 -0500 (Thu, 21 Jun 2007) | 2 lines Ignore *.pyo files, too, since one of the tests now generates them. ........ r2051 | stevenknight | 2007-06-26 15:11:57 -0500 (Tue, 26 Jun 2007) | 5 lines Arrange for graceful shutdown of the worker threads by writing None to the requestQueue and having the worker threads terminate their processing loops when they read it. We can then .join() the threads, to wait for their termination, avoiding exceptions in the threading library module. ........ r2052 | stevenknight | 2007-06-26 15:12:53 -0500 (Tue, 26 Jun 2007) | 3 lines Have the SWIG tests that use the Python.h header skip gracefully if the Python development environment isn't installed. ........ r2053 | stevenknight | 2007-06-26 15:23:55 -0500 (Tue, 26 Jun 2007) | 3 lines Massage the datestamp and IDs in the generated PDF so we can compare before-and-after output reliably regardless of when generated. ........ r2054 | stevenknight | 2007-06-26 15:25:56 -0500 (Tue, 26 Jun 2007) | 3 lines Fix the regular expression that matches the Qt warning message when the moc executable is used as a hint. ........ r2055 | stevenknight | 2007-06-26 15:48:21 -0500 (Tue, 26 Jun 2007) | 2 lines Fix 2.5.1 string exception warnings. ........ r2056 | stevenknight | 2007-06-26 19:23:22 -0500 (Tue, 26 Jun 2007) | 2 lines Skip the scons-time tests if the Python version can't import __future__. ........ r2057 | stevenknight | 2007-06-26 22:11:04 -0500 (Tue, 26 Jun 2007) | 3 lines Normalize PDF output in the bibtex rerun test as well. Commonize the PDF normalization logic by putting it in QMTest/TestSCons.py. ........ r2058 | stevenknight | 2007-06-26 22:50:39 -0500 (Tue, 26 Jun 2007) | 3 lines Duplicate a function declaration to suppress compiler warnings about a cast, when using certain systems/compilers. ........ r2059 | stevenknight | 2007-06-26 22:53:12 -0500 (Tue, 26 Jun 2007) | 2 lines Use the frtbegin when compiling Fortran programs using GCC 4. ........ r2060 | stevenknight | 2007-06-26 23:13:35 -0500 (Tue, 26 Jun 2007) | 2 lines Make the object that goes into the shared library a shared object file. ........ r2061 | stevenknight | 2007-06-26 23:53:49 -0500 (Tue, 26 Jun 2007) | 4 lines Split test/AS/AS.py into sub-tests for the live assemblers it tests. Only test nasm for the known configuration of version 0.98* on a 32-bit x86 system. ........ r2063 | stevenknight | 2007-06-27 09:51:43 -0500 (Wed, 27 Jun 2007) | 2 lines Fix searching for the rmic utility. ........ r2064 | stevenknight | 2007-06-27 10:26:42 -0500 (Wed, 27 Jun 2007) | 3 lines Improved worker-thread termination in a separate Job.cleanup() method. (Adam Simpkins) ........ r2087 | stevenknight | 2007-07-03 12:22:10 -0500 (Tue, 03 Jul 2007) | 7 lines Get rid of unnecessary subclassing and complicating overriding of __init__() and parse_args() methods in favor of more straightforward initialization of the OptionParser object. We may need to restore subclassing in the future, but if so we'll do it in a more OO way. ........ r2088 | stevenknight | 2007-07-03 16:12:30 -0500 (Tue, 03 Jul 2007) | 2 lines Fix a cleanup error (no self.p4d attribute) when Perforce isn't installed. ........ r2090 | stevenknight | 2007-07-04 03:23:57 -0500 (Wed, 04 Jul 2007) | 2 lines Import the vanilla Python 2.5 optparse.py for use as a compatibility module. ........ r2091 | stevenknight | 2007-07-04 03:35:17 -0500 (Wed, 04 Jul 2007) | 5 lines Use the new optparse compatibility module for command-line processing, and remove the SCons/Optik/*.py modules, with appropriate subclassing in Script/SConsOptions.py to preserve the way we print help text and SCons error messages. ........ r2108 | stevenknight | 2007-07-08 22:57:08 -0500 (Sun, 08 Jul 2007) | 3 lines Make all of the optparse.add_options calls more-or-less consistent in how they call the keyword arguments. ........ r2109 | stevenknight | 2007-07-09 12:31:01 -0500 (Mon, 09 Jul 2007) | 6 lines Consolidate command-line and {Get,Set}Option() processing and access in a single subclass of the optparse.Values() class. Allow all options, not just those that aren't SConscript-settable, to set their default values when calling op.add_option(). ........ r2110 | stevenknight | 2007-07-09 13:17:58 -0500 (Mon, 09 Jul 2007) | 4 lines Handle initialization of command-line repository options by passing the option arguments directly to the _SConstruct_exists() utility function, not by setting a global variable. ........ r2111 | stevenknight | 2007-07-09 13:42:41 -0500 (Mon, 09 Jul 2007) | 2 lines Remove the unused _varargs() utility function. ........ r2112 | stevenknight | 2007-07-09 15:21:51 -0500 (Mon, 09 Jul 2007) | 2 lines Clean up how we use optparse (mainly for readability). ........ r2113 | stevenknight | 2007-07-10 15:50:08 -0500 (Tue, 10 Jul 2007) | 2 lines More old-Python-version compatibility changes in optparse.py. ........ r2114 | stevenknight | 2007-07-10 16:46:42 -0500 (Tue, 10 Jul 2007) | 3 lines Add support for a new AddOption() function to allow the SConscript file(s) to define new command-line flags. ........
Diffstat (limited to 'src/engine/SCons/Script')
-rw-r--r--src/engine/SCons/Script/Main.py688
-rw-r--r--src/engine/SCons/Script/MainTests.py30
-rw-r--r--src/engine/SCons/Script/SConsOptions.py819
-rw-r--r--src/engine/SCons/Script/SConscript.py4
-rw-r--r--src/engine/SCons/Script/__init__.py23
5 files changed, 994 insertions, 570 deletions
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
index d80050d..53e5129 100644
--- a/src/engine/SCons/Script/Main.py
+++ b/src/engine/SCons/Script/Main.py
@@ -61,7 +61,6 @@ import SCons.Errors
import SCons.Job
import SCons.Node
import SCons.Node.FS
-from SCons.Optik import OptionParser, SUPPRESS_HELP, OptionValueError
import SCons.SConf
import SCons.Script
import SCons.Sig
@@ -70,6 +69,10 @@ import SCons.Util
import SCons.Warnings
#
+
+class SConsPrintHelpException(Exception):
+ pass
+
display = SCons.Util.display
progress_display = SCons.Util.DisplayEngine()
@@ -108,9 +111,9 @@ class BuildTask(SCons.Taskmaster.Task):
def do_failed(self, status=2):
global exit_status
- if ignore_errors:
+ if self.options.ignore_errors:
SCons.Taskmaster.Task.executed(self)
- elif keep_going_on_error:
+ elif self.options.keep_going:
SCons.Taskmaster.Task.fail_continue(self)
exit_status = status
else:
@@ -122,7 +125,7 @@ class BuildTask(SCons.Taskmaster.Task):
if self.top and not t.has_builder() and not t.side_effect:
if not t.exists():
sys.stderr.write("scons: *** Do not know how to make target `%s'." % t)
- if not keep_going_on_error:
+ if not self.options.keep_going:
sys.stderr.write(" Stop.")
sys.stderr.write("\n")
self.do_failed()
@@ -175,7 +178,7 @@ class BuildTask(SCons.Taskmaster.Task):
if e is None:
e = t
s = str(e)
- if t == SCons.Errors.StopError and not keep_going_on_error:
+ if t == SCons.Errors.StopError and not self.options.keep_going:
s = s + ' Stop.'
sys.stderr.write("scons: *** %s\n" % s)
@@ -190,9 +193,9 @@ class BuildTask(SCons.Taskmaster.Task):
def postprocess(self):
if self.top:
t = self.targets[0]
- for tp in tree_printers:
+ for tp in self.options.tree_printers:
tp.display(t)
- if print_includes:
+ if self.options.debug_includes:
tree = t.render_include_tree()
if tree:
print
@@ -202,7 +205,7 @@ class BuildTask(SCons.Taskmaster.Task):
def make_ready(self):
"""Make a task ready for execution"""
SCons.Taskmaster.Task.make_ready(self)
- if self.out_of_date and print_explanations:
+ if self.out_of_date and self.options.debug_explain:
explanation = self.out_of_date[0].explain()
if explanation:
sys.stdout.write("scons: " + explanation)
@@ -316,43 +319,23 @@ class TreePrinter:
# Global variables
-tree_printers = []
-
-keep_going_on_error = 0
-print_explanations = 0
-print_includes = 0
print_objects = 0
print_memoizer = 0
print_stacktrace = 0
print_time = 0
-ignore_errors = 0
sconscript_time = 0
cumulative_command_time = 0
exit_status = 0 # exit status, assume success by default
-repositories = []
num_jobs = None
delayed_warnings = []
-diskcheck_all = SCons.Node.FS.diskcheck_types()
-diskcheck_option_set = None
-
-def diskcheck_convert(value):
- if value is None:
- return []
- if not SCons.Util.is_List(value):
- value = string.split(value, ',')
- result = []
- for v in map(string.lower, value):
- if v == 'all':
- result = diskcheck_all
- elif v == 'none':
- result = []
- elif v in diskcheck_all:
- result.append(v)
- else:
- raise ValueError, v
- return result
+OptionsParser = None
+def AddOption(*args, **kw):
+ if not kw.has_key('default'):
+ kw['default'] = None
+ result = apply(OptionsParser.add_local_option, args, kw)
+ return result
#
class Stats:
def __init__(self):
@@ -482,15 +465,6 @@ def _scons_internal_error():
traceback.print_exc()
sys.exit(2)
-def _varargs(option, parser):
- value = None
- if parser.rargs:
- arg = parser.rargs[0]
- if arg[0] != "-":
- value = arg
- del parser.rargs[0]
- return value
-
def _setup_warn(arg):
"""The --warn option. An argument to this option
should be of the form <warning-class> or no-<warning-class>.
@@ -536,12 +510,11 @@ def _setup_warn(arg):
else:
SCons.Warnings.suppressWarningClass(clazz)
-def _SConstruct_exists(dirname=''):
+def _SConstruct_exists(dirname='', repositories=[]):
"""This function checks that an SConstruct file exists in a directory.
If so, it returns the path of the file. By default, it checks the
current directory.
"""
- global repositories
for file in ['SConstruct', 'Sconstruct', 'sconstruct']:
sfile = os.path.join(dirname, file)
if os.path.isfile(sfile):
@@ -552,49 +525,44 @@ def _SConstruct_exists(dirname=''):
return sfile
return None
-def _set_globals(options):
- global keep_going_on_error, ignore_errors
- global count_stats
- global print_explanations, print_includes, print_memoizer
- global print_objects, print_stacktrace, print_time
- global tree_printers
- global memory_stats
+def _set_debug_values(options):
+ global print_memoizer, print_objects, print_stacktrace, print_time
- keep_going_on_error = options.keep_going
- try:
- debug_values = options.debug
- if debug_values is None:
- debug_values = []
- except AttributeError:
- pass
- else:
- if "count" in debug_values:
+ debug_values = options.debug
+
+ if "count" in debug_values:
+ # All of the object counts are within "if __debug__:" blocks,
+ # which get stripped when running optimized (with python -O or
+ # from compiled *.pyo files). Provide a warning if __debug__ is
+ # stripped, so it doesn't just look like --debug=count is broken.
+ enable_count = False
+ if __debug__: enable_count = True
+ if enable_count:
count_stats.enable(sys.stdout)
- if "dtree" in debug_values:
- tree_printers.append(TreePrinter(derived=True))
- if "explain" in debug_values:
- print_explanations = 1
- if "findlibs" in debug_values:
- SCons.Scanner.Prog.print_find_libs = "findlibs"
- if "includes" in debug_values:
- print_includes = 1
- if "memoizer" in debug_values:
- print_memoizer = 1
- if "memory" in debug_values:
- memory_stats.enable(sys.stdout)
- if "objects" in debug_values:
- print_objects = 1
- if "presub" in debug_values:
- SCons.Action.print_actions_presub = 1
- if "stacktrace" in debug_values:
- print_stacktrace = 1
- if "stree" in debug_values:
- tree_printers.append(TreePrinter(status=True))
- if "time" in debug_values:
- print_time = 1
- if "tree" in debug_values:
- tree_printers.append(TreePrinter())
- ignore_errors = options.ignore_errors
+ else:
+ msg = "--debug=count is not supported when running SCons\n" + \
+ "\twith the python -O option or optimized (.pyo) modules."
+ SCons.Warnings.warn(SCons.Warnings.NoObjectCountWarning, msg)
+ if "dtree" in debug_values:
+ options.tree_printers.append(TreePrinter(derived=True))
+ options.debug_explain = ("explain" in debug_values)
+ if "findlibs" in debug_values:
+ SCons.Scanner.Prog.print_find_libs = "findlibs"
+ options.debug_includes = ("includes" in debug_values)
+ print_memoizer = ("memoizer" in debug_values)
+ if "memory" in debug_values:
+ memory_stats.enable(sys.stdout)
+ print_objects = ("objects" in debug_values)
+ if "presub" in debug_values:
+ SCons.Action.print_actions_presub = 1
+ if "stacktrace" in debug_values:
+ print_stacktrace = 1
+ if "stree" in debug_values:
+ options.tree_printers.append(TreePrinter(status=True))
+ if "time" in debug_values:
+ print_time = 1
+ if "tree" in debug_values:
+ options.tree_printers.append(TreePrinter())
def _create_path(plist):
path = '.'
@@ -655,410 +623,25 @@ def version_string(label, module):
module.__developer__,
module.__buildsys__)
-class OptParser(OptionParser):
- def __init__(self):
- import __main__
-
- parts = ["SCons by Steven Knight et al.:\n"]
- try:
- parts.append(version_string("script", __main__))
- except KeyboardInterrupt:
- raise
- except:
- # On Windows there is no scons.py, so there is no
- # __main__.__version__, hence there is no script version.
- pass
- parts.append(version_string("engine", SCons))
- parts.append("__COPYRIGHT__")
- OptionParser.__init__(self, version=string.join(parts, ''),
- usage="usage: scons [OPTION] [TARGET] ...")
-
- # options ignored for compatibility
- def opt_ignore(option, opt, value, parser):
- sys.stderr.write("Warning: ignoring %s option\n" % opt)
- self.add_option("-b", "-m", "-S", "-t", "--no-keep-going", "--stop",
- "--touch", action="callback", callback=opt_ignore,
- help="Ignored for compatibility.")
-
- self.add_option('-c', '--clean', '--remove', action="store_true",
- dest="clean",
- help="Remove specified targets and dependencies.")
-
- self.add_option('-C', '--directory', type="string", action = "append",
- metavar="DIR",
- help="Change to DIR before doing anything.")
-
- self.add_option('--cache-debug', action="store",
- dest="cache_debug", metavar="FILE",
- help="Print CacheDir debug info to FILE.")
-
- self.add_option('--cache-disable', '--no-cache',
- action="store_true", dest='cache_disable', default=0,
- help="Do not retrieve built targets from CacheDir.")
-
- self.add_option('--cache-force', '--cache-populate',
- action="store_true", dest='cache_force', default=0,
- help="Copy already-built targets into the CacheDir.")
-
- self.add_option('--cache-show',
- action="store_true", dest='cache_show', default=0,
- help="Print build actions for files from CacheDir.")
-
- config_options = ["auto", "force" ,"cache"]
-
- def opt_config(option, opt, value, parser, c_options=config_options):
- if value in c_options:
- parser.values.config = value
- else:
- raise OptionValueError("Warning: %s is not a valid config type" % value)
- self.add_option('--config', action="callback", type="string",
- callback=opt_config, nargs=1, dest="config",
- metavar="MODE", default="auto",
- help="Controls Configure subsystem: "
- "%s." % string.join(config_options, ", "))
-
- def opt_not_yet(option, opt, value, parser):
- sys.stderr.write("Warning: the %s option is not yet implemented\n" % opt)
- sys.exit(0)
- self.add_option('-d', action="callback",
- callback=opt_not_yet,
- help = "Print file dependency information.")
-
- self.add_option('-D', action="store_const", const=2, dest="climb_up",
- help="Search up directory tree for SConstruct, "
- "build all Default() targets.")
-
- debug_options = ["count", "dtree", "explain", "findlibs",
- "includes", "memoizer", "memory", "objects",
- "pdb", "presub", "stacktrace", "stree",
- "time", "tree"]
-
- deprecated_debug_options = {
- "nomemoizer" : ' and has no effect',
- }
-
- def opt_debug(option, opt, value, parser, debug_options=debug_options, deprecated_debug_options=deprecated_debug_options):
- if value in debug_options:
- try:
- if parser.values.debug is None:
- parser.values.debug = []
- except AttributeError:
- parser.values.debug = []
- parser.values.debug.append(value)
- elif value in deprecated_debug_options.keys():
- msg = deprecated_debug_options[value]
- w = "The --debug=%s option is deprecated%s." % (value, msg)
- delayed_warnings.append((SCons.Warnings.DeprecatedWarning, w))
- else:
- raise OptionValueError("Warning: %s is not a valid debug type" % value)
- self.add_option('--debug', action="callback", type="string",
- callback=opt_debug, nargs=1, dest="debug",
- metavar="TYPE",
- help="Print various types of debugging information: "
- "%s." % string.join(debug_options, ", "))
-
- def opt_diskcheck(option, opt, value, parser):
- try:
- global diskcheck_option_set
- diskcheck_option_set = diskcheck_convert(value)
- SCons.Node.FS.set_diskcheck(diskcheck_option_set)
- except ValueError, e:
- raise OptionValueError("Warning: `%s' is not a valid diskcheck type" % e)
-
-
- self.add_option('--diskcheck', action="callback", type="string",
- callback=opt_diskcheck, dest='diskcheck',
- metavar="TYPE",
- help="Enable specific on-disk checks.")
-
- def opt_duplicate(option, opt, value, parser):
- if not value in SCons.Node.FS.Valid_Duplicates:
- raise OptionValueError("`%s' is not a valid duplication style." % value)
- parser.values.duplicate = value
- # Set the duplicate style right away so it can affect linking
- # of SConscript files.
- SCons.Node.FS.set_duplicate(value)
- self.add_option('--duplicate', action="callback", type="string",
- callback=opt_duplicate, nargs=1, dest="duplicate",
- help="Set the preferred duplication methods. Must be one of "
- + string.join(SCons.Node.FS.Valid_Duplicates, ", "))
-
- self.add_option('-f', '--file', '--makefile', '--sconstruct',
- action="append", nargs=1,
- help="Read FILE as the top-level SConstruct file.")
-
- self.add_option('-h', '--help', action="store_true", default=0,
- dest="help",
- help="Print defined help message, or this one.")
-
- self.add_option("-H", "--help-options",
- action="help",
- help="Print this message and exit.")
-
- self.add_option('-i', '--ignore-errors', action="store_true",
- default=0, dest='ignore_errors',
- help="Ignore errors from build actions.")
-
- self.add_option('-I', '--include-dir', action="append",
- dest='include_dir', metavar="DIR",
- help="Search DIR for imported Python modules.")
-
- self.add_option('--implicit-cache', action="store_true",
- dest='implicit_cache',
- help="Cache implicit dependencies")
-
- self.add_option('--implicit-deps-changed', action="store_true",
- default=0, dest='implicit_deps_changed',
- help="Ignore cached implicit dependencies.")
- self.add_option('--implicit-deps-unchanged', action="store_true",
- default=0, dest='implicit_deps_unchanged',
- help="Ignore changes in implicit dependencies.")
-
- def opt_j(option, opt, value, parser):
- value = int(value)
- parser.values.num_jobs = value
- self.add_option('-j', '--jobs', action="callback", type="int",
- callback=opt_j, metavar="N",
- help="Allow N jobs at once.")
-
- self.add_option('-k', '--keep-going', action="store_true", default=0,
- dest='keep_going',
- help="Keep going when a target can't be made.")
-
- self.add_option('--max-drift', type="int", action="store",
- dest='max_drift', metavar="N",
- help="Set maximum system clock drift to N seconds.")
-
- self.add_option('-n', '--no-exec', '--just-print', '--dry-run',
- '--recon', action="store_true", dest='noexec',
- default=0, help="Don't build; just print commands.")
-
- self.add_option('--no-site-dir', action="store_true",
- dest='no_site_dir', default=0,
- help="Don't search or use the usual site_scons dir.")
-
- self.add_option('--profile', action="store",
- dest="profile_file", metavar="FILE",
- help="Profile SCons and put results in FILE.")
-
- self.add_option('-q', '--question', action="store_true", default=0,
- help="Don't build; exit status says if up to date.")
-
- self.add_option('-Q', dest='no_progress', action="store_true",
- default=0,
- help="Suppress \"Reading/Building\" progress messages.")
-
- self.add_option('--random', dest="random", action="store_true",
- default=0, help="Build dependencies in random order.")
-
- self.add_option('-s', '--silent', '--quiet', action="store_true",
- default=0, help="Don't print commands.")
-
- self.add_option('--site-dir', action="store",
- dest='site_dir', metavar="DIR",
- help="Use DIR instead of the usual site_scons dir.")
-
- self.add_option('--taskmastertrace', action="store",
- dest="taskmastertrace_file", metavar="FILE",
- help="Trace Node evaluation to FILE.")
-
- tree_options = ["all", "derived", "prune", "status"]
-
- def opt_tree(option, opt, value, parser, tree_options=tree_options):
- tp = TreePrinter()
- for o in string.split(value, ','):
- if o == 'all':
- tp.derived = False
- elif o == 'derived':
- tp.derived = True
- elif o == 'prune':
- tp.prune = True
- elif o == 'status':
- tp.status = True
- else:
- raise OptionValueError("Warning: %s is not a valid --tree option" % o)
- tree_printers.append(tp)
-
- self.add_option('--tree', action="callback", type="string",
- callback=opt_tree, nargs=1, metavar="OPTIONS",
- help="Print a dependency tree in various formats: "
- "%s." % string.join(tree_options, ", "))
-
- self.add_option('-u', '--up', '--search-up', action="store_const",
- dest="climb_up", default=0, const=1,
- help="Search up directory tree for SConstruct, "
- "build targets at or below current directory.")
- self.add_option('-U', action="store_const", dest="climb_up",
- default=0, const=3,
- help="Search up directory tree for SConstruct, "
- "build Default() targets from local SConscript.")
-
- self.add_option("-v", "--version",
- action="version",
- help="Print the SCons version number and exit.")
-
- self.add_option('--warn', '--warning', nargs=1, action="store",
- metavar="WARNING-SPEC",
- help="Enable or disable warnings.")
-
- self.add_option('-Y', '--repository', '--srcdir',
- nargs=1, action="append",
- help="Search REPOSITORY for source and target files.")
-
- self.add_option('-e', '--environment-overrides', action="callback",
- callback=opt_not_yet,
- # help="Environment variables override makefiles."
- help=SUPPRESS_HELP)
- self.add_option('-l', '--load-average', '--max-load', action="callback",
- callback=opt_not_yet, type="int", dest="load_average",
- # action="store",
- # help="Don't start multiple jobs unless load is below "
- # "LOAD-AVERAGE."
- # type="int",
- help=SUPPRESS_HELP)
- self.add_option('--list-derived', action="callback",
- callback=opt_not_yet,
- # help="Don't build; list files that would be built."
- help=SUPPRESS_HELP)
- self.add_option('--list-actions', action="callback",
- callback=opt_not_yet,
- # help="Don't build; list files and build actions."
- help=SUPPRESS_HELP)
- self.add_option('--list-where', action="callback",
- callback=opt_not_yet,
- # help="Don't build; list files and where defined."
- help=SUPPRESS_HELP)
- self.add_option('-o', '--old-file', '--assume-old', action="callback",
- callback=opt_not_yet, type="string", dest="old_file",
- # help = "Consider FILE to be old; don't rebuild it."
- help=SUPPRESS_HELP)
- self.add_option('--override', action="callback", dest="override",
- callback=opt_not_yet, type="string",
- # help="Override variables as specified in FILE."
- help=SUPPRESS_HELP)
- self.add_option('-p', action="callback",
- callback=opt_not_yet,
- # help="Print internal environments/objects."
- help=SUPPRESS_HELP)
- self.add_option('-r', '-R', '--no-builtin-rules',
- '--no-builtin-variables', action="callback",
- callback=opt_not_yet,
- # help="Clear default environments and variables."
- help=SUPPRESS_HELP)
- self.add_option('-w', '--print-directory', action="callback",
- callback=opt_not_yet,
- # help="Print the current directory."
- help=SUPPRESS_HELP)
- self.add_option('--no-print-directory', action="callback",
- callback=opt_not_yet,
- # help="Turn off -w, even if it was turned on implicitly."
- help=SUPPRESS_HELP)
- self.add_option('--write-filenames', action="callback",
- callback=opt_not_yet, type="string", dest="write_filenames",
- # help="Write all filenames examined into FILE."
- help=SUPPRESS_HELP)
- self.add_option('-W', '--what-if', '--new-file', '--assume-new',
- dest="new_file",
- action="callback", callback=opt_not_yet, type="string",
- # help="Consider FILE to be changed."
- help=SUPPRESS_HELP)
- self.add_option('--warn-undefined-variables', action="callback",
- callback=opt_not_yet,
- # help="Warn when an undefined variable is referenced."
- help=SUPPRESS_HELP)
-
- def parse_args(self, args=None, values=None):
- opt, arglist = OptionParser.parse_args(self, args, values)
- if opt.implicit_deps_changed or opt.implicit_deps_unchanged:
- opt.implicit_cache = 1
- return opt, arglist
-
-class SConscriptSettableOptions:
- """This class wraps an OptParser instance and provides
- uniform access to options that can be either set on the command
- line or from a SConscript file. A value specified on the command
- line always overrides a value set in a SConscript file.
- Not all command line options are SConscript settable, and the ones
- that are must be explicitly added to settable dictionary and optionally
- validated and coerced in the set() method."""
-
- def __init__(self, options):
- self.options = options
-
- # This dictionary stores the defaults for all the SConscript
- # settable options, as well as indicating which options
- # are SConscript settable (and gettable, which for options
- # like 'help' is far more important than being settable).
- self.settable = {
- 'clean' : 0,
- 'diskcheck' : diskcheck_all,
- 'duplicate' : 'hard-soft-copy',
- 'help' : 0,
- 'implicit_cache' : 0,
- 'max_drift' : SCons.Node.FS.default_max_drift,
- 'num_jobs' : 1,
- 'random' : 0,
- }
-
- def get(self, name):
- if not self.settable.has_key(name):
- raise SCons.Errors.UserError, "This option is not settable from a SConscript file: %s"%name
- if hasattr(self.options, name) and getattr(self.options, name) is not None:
- return getattr(self.options, name)
- else:
- return self.settable[name]
-
- def set(self, name, value):
- if not self.settable.has_key(name):
- raise SCons.Errors.UserError, "This option is not settable from a SConscript file: %s"%name
-
- if name == 'num_jobs':
- try:
- value = int(value)
- if value < 1:
- raise ValueError
- except ValueError:
- raise SCons.Errors.UserError, "A positive integer is required: %s"%repr(value)
- elif name == 'max_drift':
- try:
- value = int(value)
- except ValueError:
- raise SCons.Errors.UserError, "An integer is required: %s"%repr(value)
- elif name == 'duplicate':
- try:
- value = str(value)
- except ValueError:
- raise SCons.Errors.UserError, "A string is required: %s"%repr(value)
- if not value in SCons.Node.FS.Valid_Duplicates:
- raise SCons.Errors.UserError, "Not a valid duplication style: %s" % value
- # Set the duplicate stye right away so it can affect linking
- # of SConscript files.
- SCons.Node.FS.set_duplicate(value)
- elif name == 'diskcheck':
- try:
- value = diskcheck_convert(value)
- except ValueError, v:
- raise SCons.Errors.UserError, "Not a valid diskcheck value: %s"%v
- if not diskcheck_option_set:
- SCons.Node.FS.set_diskcheck(value)
-
- self.settable[name] = value
-
-
-def _main(args, parser):
+def _main(parser):
global exit_status
+ options = parser.values
+
# Here's where everything really happens.
- # First order of business: set up default warnings and and then
- # handle the user's warning options, so we can warn about anything
- # that happens appropriately.
+ # First order of business: set up default warnings and then
+ # handle the user's warning options, so that we can issue (or
+ # suppress) appropriate warnings about anything that might happen,
+ # as configured by the user.
+
default_warnings = [ SCons.Warnings.CorruptSConsignWarning,
SCons.Warnings.DeprecatedWarning,
SCons.Warnings.DuplicateEnvironmentWarning,
SCons.Warnings.MissingSConscriptWarning,
SCons.Warnings.NoMD5ModuleWarning,
SCons.Warnings.NoMetaclassSupportWarning,
+ SCons.Warnings.NoObjectCountWarning,
SCons.Warnings.NoParallelSupportWarning,
SCons.Warnings.MisleadingKeywordsWarning, ]
for warning in default_warnings:
@@ -1067,9 +650,21 @@ def _main(args, parser):
if options.warn:
_setup_warn(options.warn)
+ # Now that we have the warnings configuration set up, we can actually
+ # issue (or suppress) any warnings about warning-worthy things that
+ # occurred while the command-line options were getting parsed.
+ try:
+ dw = options.delayed_warnings
+ except AttributeError:
+ pass
+ else:
+ delayed_warnings.extend(dw)
for warning_type, message in delayed_warnings:
SCons.Warnings.warn(warning_type, message)
+ if options.diskcheck:
+ SCons.Node.FS.set_diskcheck(options.diskcheck)
+
# Next, we want to create the FS object that represents the outside
# world's file system, as that's central to a lot of initialization.
# To do this, however, we need to be in the directory from which we
@@ -1082,17 +677,11 @@ def _main(args, parser):
except OSError:
sys.stderr.write("Could not change directory to %s\n" % cdir)
- # The SConstruct file may be in a repository, so initialize those
- # before we start the search up our path for one.
- global repositories
- if options.repository:
- repositories.extend(options.repository)
-
target_top = None
if options.climb_up:
target_top = '.' # directory to prepend to targets
script_dir = os.getcwd() # location of script
- while script_dir and not _SConstruct_exists(script_dir):
+ while script_dir and not _SConstruct_exists(script_dir, options.repository):
script_dir, last_part = os.path.split(script_dir)
if last_part:
target_top = os.path.join(last_part, target_top)
@@ -1107,7 +696,7 @@ def _main(args, parser):
# and make it the build engine default.
fs = SCons.Node.FS.default_fs = SCons.Node.FS.FS()
- for rep in repositories:
+ for rep in options.repository:
fs.Repository(rep)
# Now that we have the FS object, the next order of business is to
@@ -1117,7 +706,7 @@ def _main(args, parser):
if options.file:
scripts.extend(options.file)
if not scripts:
- sfile = _SConstruct_exists()
+ sfile = _SConstruct_exists(repositories=options.repository)
if sfile:
scripts.append(sfile)
@@ -1126,9 +715,7 @@ def _main(args, parser):
# There's no SConstruct, but they specified -h.
# Give them the options usage now, before we fail
# trying to read a non-existent SConstruct file.
- parser.print_help()
- exit_status = 0
- return
+ raise SConsPrintHelpException
raise SCons.Errors.UserError, "No SConstruct file found."
if scripts[0] == "-":
@@ -1137,16 +724,11 @@ def _main(args, parser):
d = fs.File(scripts[0]).dir
fs.set_SConstruct_dir(d)
- # Now that we have the FS object and it's intialized, set up (most
- # of) the rest of the options.
- global ssoptions
- ssoptions = SConscriptSettableOptions(options)
-
- _set_globals(options)
+ _set_debug_values(options)
SCons.Node.implicit_cache = options.implicit_cache
SCons.Node.implicit_deps_changed = options.implicit_deps_changed
SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged
- if options.noexec:
+ if options.no_exec:
SCons.SConf.dryrun = 1
SCons.Action.execute_actions = None
CleanTask.execute = CleanTask.show
@@ -1185,12 +767,14 @@ def _main(args, parser):
# read and execute have access to them.
targets = []
xmit_args = []
- for a in args:
+ for a in parser.largs:
+ if a[0] == '-':
+ continue
if '=' in a:
xmit_args.append(a)
else:
targets.append(a)
- SCons.Script._Add_Targets(targets)
+ SCons.Script._Add_Targets(targets + parser.rargs)
SCons.Script._Add_Arguments(xmit_args)
sys.stdout = SCons.Util.Unbuffered(sys.stdout)
@@ -1198,6 +782,8 @@ def _main(args, parser):
memory_stats.append('before reading SConscript files:')
count_stats.append(('pre-', 'read'))
+ # And here's where we (finally) read the SConscript files.
+
progress_display("scons: Reading SConscript files ...")
start_time = time.time()
@@ -1215,37 +801,50 @@ def _main(args, parser):
sys.exit(exit_status)
global sconscript_time
sconscript_time = time.time() - start_time
- SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
- progress_display("scons: done reading SConscript files.")
- # Tell the Node.FS subsystem that we're all done reading the
- # SConscript files and calling Repository() and BuildDir() and the
- # like, so it can go ahead and start memoizing the string values of
- # file system nodes.
- SCons.Node.FS.save_strings(1)
+ progress_display("scons: done reading SConscript files.")
memory_stats.append('after reading SConscript files:')
count_stats.append(('post-', 'read'))
- fs.chdir(fs.Top)
+ SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
+
+ # Now re-parse the command-line options (any to the left of a '--'
+ # argument, that is) with any user-defined command-line options that
+ # the SConscript files may have added to the parser object. This will
+ # emit the appropriate error message and exit if any unknown option
+ # was specified on the command line.
+
+ parser.preserve_unknown_options = False
+ parser.parse_args(parser.largs, options)
- if ssoptions.get('help'):
+ if options.help:
help_text = SCons.Script.help_text
if help_text is None:
# They specified -h, but there was no Help() inside the
# SConscript files. Give them the options usage.
- parser.print_help(sys.stdout)
+ raise SConsPrintHelpException
else:
print help_text
print "Use scons -H for help about command-line options."
exit_status = 0
return
+ # Change directory to the top-level SConstruct directory, then tell
+ # the Node.FS subsystem that we're all done reading the SConscript
+ # files and calling Repository() and BuildDir() and changing
+ # directories and the like, so it can go ahead and start memoizing
+ # the string values of file system nodes.
+
+ fs.chdir(fs.Top)
+
+ SCons.Node.FS.save_strings(1)
+
# Now that we've read the SConscripts we can set the options
# that are SConscript settable:
- SCons.Node.implicit_cache = ssoptions.get('implicit_cache')
- SCons.Node.FS.set_duplicate(ssoptions.get('duplicate'))
- fs.set_max_drift(ssoptions.get('max_drift'))
+ SCons.Node.implicit_cache = options.implicit_cache
+ SCons.Node.FS.set_duplicate(options.duplicate)
+ fs.set_max_drift(options.max_drift)
lookup_top = None
if targets or SCons.Script.BUILD_TARGETS != SCons.Script._build_plus_default:
@@ -1324,18 +923,18 @@ def _main(args, parser):
task_class = BuildTask # default action is to build targets
opening_message = "Building targets ..."
closing_message = "done building targets."
- if keep_going_on_error:
+ if options.keep_going:
failure_message = "done building targets (errors occurred during build)."
else:
failure_message = "building terminated because of errors."
if options.question:
task_class = QuestionTask
try:
- if ssoptions.get('clean'):
+ if options.clean:
task_class = CleanTask
opening_message = "Cleaning targets ..."
closing_message = "done cleaning targets."
- if keep_going_on_error:
+ if options.keep_going:
closing_message = "done cleaning targets (errors occurred during clean)."
else:
failure_message = "cleaning terminated because of errors."
@@ -1367,8 +966,12 @@ def _main(args, parser):
tmtrace = None
taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order, tmtrace)
+ # Let the BuildTask objects get at the options to respond to the
+ # various print_* settings, tree_printer list, etc.
+ BuildTask.options = options
+
global num_jobs
- num_jobs = ssoptions.get('num_jobs')
+ num_jobs = options.num_jobs
jobs = SCons.Job.Jobs(num_jobs, taskmaster)
if num_jobs > 1 and jobs.num_jobs == 1:
msg = "parallel builds are unsupported by this version of Python;\n" + \
@@ -1381,26 +984,26 @@ def _main(args, parser):
try:
jobs.run()
finally:
+ jobs.cleanup()
if exit_status:
progress_display("scons: " + failure_message)
else:
progress_display("scons: " + closing_message)
- if not options.noexec:
+ if not options.no_exec:
SCons.SConsign.write()
memory_stats.append('after building targets:')
count_stats.append(('post-', 'build'))
-def _exec_main():
+def _exec_main(parser, values):
sconsflags = os.environ.get('SCONSFLAGS', '')
all_args = string.split(sconsflags) + sys.argv[1:]
- parser = OptParser()
- global options
- options, args = parser.parse_args(all_args)
+ options, args = parser.parse_args(all_args, values)
+
if type(options.debug) == type([]) and "pdb" in options.debug:
import pdb
- pdb.Pdb().runcall(_main, args, parser)
+ pdb.Pdb().runcall(_main, parser)
elif options.profile_file:
from profile import Profile
@@ -1418,19 +1021,42 @@ def _exec_main():
prof = Profile()
try:
- prof.runcall(_main, args, parser)
+ prof.runcall(_main, parser)
+ except SConsPrintHelpException, e:
+ prof.dump_stats(options.profile_file)
+ raise e
except SystemExit:
pass
prof.dump_stats(options.profile_file)
else:
- _main(args, parser)
+ _main(parser)
def main():
+ global OptionsParser
global exit_status
global first_command_start
+
+ parts = ["SCons by Steven Knight et al.:\n"]
+ try:
+ parts.append(version_string("script", __main__))
+ except KeyboardInterrupt:
+ raise
+ except:
+ # On Windows there is no scons.py, so there is no
+ # __main__.__version__, hence there is no script version.
+ pass
+ parts.append(version_string("engine", SCons))
+ parts.append("__COPYRIGHT__")
+ version = string.join(parts, '')
+
+ import SConsOptions
+ parser = SConsOptions.Parser(version)
+ values = SConsOptions.SConsValues(parser.get_default_values())
+
+ OptionsParser = parser
try:
- _exec_main()
+ _exec_main(parser, values)
except SystemExit, s:
if s:
exit_status = s
@@ -1443,6 +1069,9 @@ def main():
_scons_internal_error()
except SCons.Errors.UserError, e:
_scons_user_error(e)
+ except SConsPrintHelpException:
+ parser.print_help()
+ exit_status = 0
except:
# An exception here is likely a builtin Python exception Python
# code in an SConscript file. Show them precisely what the
@@ -1472,7 +1101,10 @@ def main():
if num_jobs == 1:
ct = cumulative_command_time
else:
- ct = last_command_end - first_command_start
+ if last_command_end is None or first_command_start is None:
+ ct = 0.0
+ else:
+ ct = last_command_end - first_command_start
scons_time = total_time - sconscript_time - ct
print "Total build time: %f seconds"%total_time
print "Total SConscript file execution time: %f seconds"%sconscript_time
diff --git a/src/engine/SCons/Script/MainTests.py b/src/engine/SCons/Script/MainTests.py
index aaf1482..fe32df9 100644
--- a/src/engine/SCons/Script/MainTests.py
+++ b/src/engine/SCons/Script/MainTests.py
@@ -37,37 +37,9 @@ import SCons.Script.Main
# have to reach into SCons.Script.Main for various classes or other bits
# of private functionality.
-class SConscriptSettableOptionsTestCase(unittest.TestCase):
-
- def setUp(self):
- class fake_option:
- pass
- option = fake_option()
- self.ssoptions = SCons.Script.Main.SConscriptSettableOptions(option)
-
- def test_get(self):
- """Test trying to get an option that is not SConscript-gettable"""
- try:
- self.ssoptions.get('memoizer')
- except SCons.Errors.UserError:
- pass
- else:
- raise ValueError, "expected a UserError trying to get('memoizer')"
-
- def test_set(self):
- """Test trying to set an option that is not SConscript-settable"""
- try:
- self.ssoptions.set('count', 1)
- except SCons.Errors.UserError:
- pass
- else:
- raise ValueError, "expected a UserError trying to set('count', 1)"
-
-
-
if __name__ == "__main__":
suite = unittest.TestSuite()
- tclasses = [ SConscriptSettableOptionsTestCase, ]
+ tclasses = []
for tclass in tclasses:
names = unittest.getTestCaseNames(tclass, 'test_')
suite.addTests(map(tclass, names))
diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py
new file mode 100644
index 0000000..053fff1
--- /dev/null
+++ b/src/engine/SCons/Script/SConsOptions.py
@@ -0,0 +1,819 @@
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.compat
+
+import optparse
+import string
+import sys
+import textwrap
+
+try:
+ from gettext import gettext
+except ImportError:
+ def gettext(message):
+ return message
+_ = gettext
+
+import SCons.Node.FS
+
+OptionValueError = optparse.OptionValueError
+SUPPRESS_HELP = optparse.SUPPRESS_HELP
+
+diskcheck_all = SCons.Node.FS.diskcheck_types()
+
+def diskcheck_convert(value):
+ if value is None:
+ return []
+ if not SCons.Util.is_List(value):
+ value = string.split(value, ',')
+ result = []
+ for v in map(string.lower, value):
+ if v == 'all':
+ result = diskcheck_all
+ elif v == 'none':
+ result = []
+ elif v in diskcheck_all:
+ result.append(v)
+ else:
+ raise ValueError, v
+ return result
+
+class SConsValues(optparse.Values):
+ """
+ Holder class for uniform access to SCons options, regardless
+ of whether or not they can be set on the command line or in the
+ SConscript files (using the SetOption() function).
+
+ A SCons option value can originate three different ways:
+
+ 1) set on the command line;
+ 2) set in an SConscript file;
+ 3) the default setting (from the the op.add_option()
+ calls in the Parser() function, below).
+
+ The command line always overrides a value set in a SConscript file,
+ which in turn always overrides default settings. Because we want
+ to support user-specified options in the SConscript file itself,
+ though, we may not know about all of the options when the command
+ line is first parsed, so we can't make all the necessary precedence
+ decisions at the time the option is configured.
+
+ The solution implemented in this class is to keep these different sets
+ of settings separate (command line, SConscript file, and default)
+ and to override the __getattr__() method to check them in turn.
+ This should allow the rest of the code to just fetch values as
+ attributes of an instance of this class, without having to worry
+ about where they came from.
+
+ Note that not all command line options are settable from SConscript
+ files, and the ones that are must be explicitly added to the
+ "settable" list in this class, and optionally validated and coerced
+ in the set_option() method.
+ """
+
+ def __init__(self, defaults):
+ self.__dict__['__defaults__'] = defaults
+ self.__dict__['__SConscript_settings__'] = {}
+
+ def __getattr__(self, attr):
+ """
+ Fetches an options value, checking first for explicit settings
+ from the command line (which are direct attributes), then the
+ SConscript file settings, then the default values.
+ """
+ try:
+ return self.__dict__[attr]
+ except KeyError:
+ try:
+ return self.__dict__['__SConscript_settings__'][attr]
+ except KeyError:
+ return getattr(self.__dict__['__defaults__'], attr)
+
+ settable = [
+ 'clean',
+ 'diskcheck',
+ 'duplicate',
+ 'help',
+ 'implicit_cache',
+ 'max_drift',
+ 'no_exec',
+ 'num_jobs',
+ 'random',
+ ]
+
+ def set_option(self, name, value):
+ """
+ Sets an option from an SConscript file.
+ """
+ if not name in self.settable:
+ raise SCons.Errors.UserError, "This option is not settable from a SConscript file: %s"%name
+
+ if name == 'num_jobs':
+ try:
+ value = int(value)
+ if value < 1:
+ raise ValueError
+ except ValueError:
+ raise SCons.Errors.UserError, "A positive integer is required: %s"%repr(value)
+ elif name == 'max_drift':
+ try:
+ value = int(value)
+ except ValueError:
+ raise SCons.Errors.UserError, "An integer is required: %s"%repr(value)
+ elif name == 'duplicate':
+ try:
+ value = str(value)
+ except ValueError:
+ raise SCons.Errors.UserError, "A string is required: %s"%repr(value)
+ if not value in SCons.Node.FS.Valid_Duplicates:
+ raise SCons.Errors.UserError, "Not a valid duplication style: %s" % value
+ # Set the duplicate style right away so it can affect linking
+ # of SConscript files.
+ SCons.Node.FS.set_duplicate(value)
+ elif name == 'diskcheck':
+ try:
+ value = diskcheck_convert(value)
+ except ValueError, v:
+ raise SCons.Errors.UserError, "Not a valid diskcheck value: %s"%v
+ if not self.__dict__.has_key('diskcheck'):
+ # No --diskcheck= option was specified on the command line.
+ # Set this right away so it can affect the rest of the
+ # file/Node lookups while processing the SConscript files.
+ SCons.Node.FS.set_diskcheck(value)
+
+ self.__SConscript_settings__[name] = value
+
+class SConsOptionGroup(optparse.OptionGroup):
+ """
+ A subclass for SCons-specific option groups.
+
+ The only difference between this and the base class is that we print
+ the group's help text flush left, underneath their own title but
+ lined up with the normal "SCons Options".
+ """
+ def format_help(self, formatter):
+ """
+ Format an option group's help text, outdenting the title so it's
+ flush with the "SCons Options" title we print at the top.
+ """
+ formatter.dedent()
+ result = formatter.format_heading(self.title)
+ formatter.indent()
+ result = result + optparse.OptionContainer.format_help(self, formatter)
+ return result
+
+class SConsOptionParser(optparse.OptionParser):
+ preserve_unknown_options = False
+
+ def error(self, msg):
+ self.print_usage(sys.stderr)
+ sys.stderr.write("SCons error: %s\n" % msg)
+ sys.exit(2)
+
+ def _process_long_opt(self, rargs, values):
+ """
+ SCons-specific processing of long options.
+
+ This is copied directly from the normal
+ optparse._process_long_opt() method, except that, if configured
+ to do so, we catch the exception thrown when an unknown option
+ is encountered and just stick it back on the "leftover" arguments
+ for later (re-)processing.
+ """
+ arg = rargs.pop(0)
+
+ # Value explicitly attached to arg? Pretend it's the next
+ # argument.
+ if "=" in arg:
+ (opt, next_arg) = string.split(arg, "=", 1)
+ rargs.insert(0, next_arg)
+ had_explicit_value = True
+ else:
+ opt = arg
+ had_explicit_value = False
+
+ try:
+ opt = self._match_long_opt(opt)
+ except optparse.BadOptionError:
+ if self.preserve_unknown_options:
+ # SCons-specific: if requested, add unknown options to
+ # the "leftover arguments" list for later processing.
+ self.largs.append(arg)
+ if had_explicit_value:
+ # The unknown option will be re-processed later,
+ # so undo the insertion of the explicit value.
+ rargs.pop(0)
+ return
+ raise
+
+ option = self._long_opt[opt]
+ if option.takes_value():
+ nargs = option.nargs
+ if len(rargs) < nargs:
+ if nargs == 1:
+ self.error(_("%s option requires an argument") % opt)
+ else:
+ self.error(_("%s option requires %d arguments")
+ % (opt, nargs))
+ elif nargs == 1:
+ value = rargs.pop(0)
+ else:
+ value = tuple(rargs[0:nargs])
+ del rargs[0:nargs]
+
+ elif had_explicit_value:
+ self.error(_("%s option does not take a value") % opt)
+
+ else:
+ value = None
+
+ option.process(opt, value, values, self)
+
+ def add_local_option(self, *args, **kw):
+ """
+ Adds a local option to the parser.
+
+ This is initiated by a SetOption() call to add a user-defined
+ command-line option. We add the option to a separate option
+ group for the local options, creating the group if necessary.
+ """
+ try:
+ group = self.local_option_group
+ except AttributeError:
+ group = SConsOptionGroup(self, 'Local Options')
+ group = self.add_option_group(group)
+ self.local_option_group = group
+
+ result = apply(group.add_option, args, kw)
+
+ if result:
+ # The option was added succesfully. We now have to add the
+ # default value to our object that holds the default values
+ # (so that an attempt to fetch the option's attribute will
+ # yield the default value when not overridden) and then
+ # we re-parse the leftover command-line options, so that
+ # any value overridden on the command line is immediately
+ # available if the user turns around and does a GetOption()
+ # right away.
+ setattr(self.values.__defaults__, result.dest, result.default)
+ self.parse_args(self.largs, self.values)
+
+ return result
+
+class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter):
+ def format_usage(self, usage):
+ return "usage: %s\n" % usage
+
+ def format_heading(self, heading):
+ """
+ This translates any heading of "options" or "Options" into
+ "SCons Options." Unfortunately, we have to do this here,
+ because those titles are hard-coded in the optparse calls.
+ """
+ if heading == 'options':
+ # The versions of optparse.py shipped with Pythons 2.3 and
+ # 2.4 pass this in uncapitalized; override that so we get
+ # consistent output on all versions.
+ heading = "Options"
+ if heading == 'Options':
+ heading = "SCons Options"
+ return optparse.IndentedHelpFormatter.format_heading(self, heading)
+
+ def format_option(self, option):
+ """
+ A copy of the normal optparse.IndentedHelpFormatter.format_option()
+ method, snarfed so we can set the subsequent_indent on the
+ textwrap.wrap() call below...
+ """
+ # The help for each option consists of two parts:
+ # * the opt strings and metavars
+ # eg. ("-x", or "-fFILENAME, --file=FILENAME")
+ # * the user-supplied help string
+ # eg. ("turn on expert mode", "read data from FILENAME")
+ #
+ # If possible, we write both of these on the same line:
+ # -x turn on expert mode
+ #
+ # But if the opt string list is too long, we put the help
+ # string on a second line, indented to the same column it would
+ # start in if it fit on the first line.
+ # -fFILENAME, --file=FILENAME
+ # read data from FILENAME
+ result = []
+
+ try:
+ opts = self.option_strings[option]
+ except AttributeError:
+ # The Python 2.3 version of optparse attaches this to
+ # to the option argument, not to this object.
+ opts = option.option_strings
+
+ opt_width = self.help_position - self.current_indent - 2
+ if len(opts) > opt_width:
+ opts = "%*s%s\n" % (self.current_indent, "", opts)
+ indent_first = self.help_position
+ else: # start help on same line as opts
+ opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts)
+ indent_first = 0
+ result.append(opts)
+ if option.help:
+
+ try:
+ expand_default = self.expand_default
+ except AttributeError:
+ # The HelpFormatter base class in the Python 2.3 version
+ # of optparse has no expand_default() method.
+ help_text = option.help
+ else:
+ help_text = expand_default(option)
+
+ # SCons: indent every line of the help text but the first.
+ help_lines = textwrap.wrap(help_text, self.help_width,
+ subsequent_indent = ' ')
+ result.append("%*s%s\n" % (indent_first, "", help_lines[0]))
+ for line in help_lines[1:]:
+ result.append("%*s%s\n" % (self.help_position, "", line))
+ elif opts[-1] != "\n":
+ result.append("\n")
+ return string.join(result, "")
+
+ # For consistent help output across Python versions, we provide a
+ # subclass copy of format_option_strings() and these two variables.
+ # This is necessary (?) for Python2.3, which otherwise concatenates
+ # a short option with its metavar.
+ _short_opt_fmt = "%s %s"
+ _long_opt_fmt = "%s=%s"
+
+ def format_option_strings(self, option):
+ """Return a comma-separated list of option strings & metavariables."""
+ if option.takes_value():
+ metavar = option.metavar or string.upper(option.dest)
+ short_opts = []
+ for sopt in option._short_opts:
+ short_opts.append(self._short_opt_fmt % (sopt, metavar))
+ long_opts = []
+ for lopt in option._long_opts:
+ long_opts.append(self._long_opt_fmt % (lopt, metavar))
+ else:
+ short_opts = option._short_opts
+ long_opts = option._long_opts
+
+ if self.short_first:
+ opts = short_opts + long_opts
+ else:
+ opts = long_opts + short_opts
+
+ return string.join(opts, ", ")
+
+def Parser(version):
+ """
+ Returns an options parser object initialized with the standard
+ SCons options.
+ """
+
+ formatter = SConsIndentedHelpFormatter(max_help_position=30)
+
+ op = SConsOptionParser(add_help_option=False,
+ formatter=formatter,
+ usage="usage: scons [OPTION] [TARGET] ...",)
+
+ op.preserve_unknown_options = True
+
+ # Add the options to the parser we just created.
+ #
+ # These are in the order we want them to show up in the -H help
+ # text, basically alphabetical. Each op.add_option() call below
+ # should have a consistent format:
+ #
+ # op.add_option("-L", "--long-option-name",
+ # nargs=1, type="string",
+ # dest="long_option_name", default='foo',
+ # action="callback", callback=opt_long_option,
+ # help="help text goes here",
+ # metavar="VAR")
+ #
+ # Even though the optparse module constructs reasonable default
+ # destination names from the long option names, we're going to be
+ # explicit about each one for easier readability and so this code
+ # will at least show up when grepping the source for option attribute
+ # names, or otherwise browsing the source code.
+
+ # options ignored for compatibility
+ def opt_ignore(option, opt, value, parser):
+ sys.stderr.write("Warning: ignoring %s option\n" % opt)
+ op.add_option("-b", "-m", "-S", "-t",
+ "--no-keep-going", "--stop", "--touch",
+ action="callback", callback=opt_ignore,
+ help="Ignored for compatibility.")
+
+ op.add_option('-c', '--clean', '--remove',
+ dest="clean", default=False,
+ action="store_true",
+ help="Remove specified targets and dependencies.")
+
+ op.add_option('-C', '--directory',
+ nargs=1, type="string",
+ dest="directory", default=[],
+ action="append",
+ help="Change to DIR before doing anything.",
+ metavar="DIR")
+
+ op.add_option('--cache-debug',
+ nargs=1,
+ dest="cache_debug", default=None,
+ action="store",
+ help="Print CacheDir debug info to FILE.",
+ metavar="FILE")
+
+ op.add_option('--cache-disable', '--no-cache',
+ dest='cache_disable', default=False,
+ action="store_true",
+ help="Do not retrieve built targets from CacheDir.")
+
+ op.add_option('--cache-force', '--cache-populate',
+ dest='cache_force', default=False,
+ action="store_true",
+ help="Copy already-built targets into the CacheDir.")
+
+ op.add_option('--cache-show',
+ dest='cache_show', default=False,
+ action="store_true",
+ help="Print build actions for files from CacheDir.")
+
+ config_options = ["auto", "force" ,"cache"]
+
+ def opt_config(option, opt, value, parser, c_options=config_options):
+ if not value in c_options:
+ raise OptionValueError("Warning: %s is not a valid config type" % value)
+ setattr(parser.values, option.dest, value)
+ opt_config_help = "Controls Configure subsystem: %s." \
+ % string.join(config_options, ", ")
+ op.add_option('--config',
+ nargs=1, type="string",
+ dest="config", default="auto",
+ action="callback", callback=opt_config,
+ help = opt_config_help,
+ metavar="MODE")
+
+ def opt_not_yet(option, opt, value, parser):
+ sys.stderr.write("Warning: the %s option is not yet implemented\n" % opt)
+ sys.exit(0)
+ op.add_option('-d',
+ action="callback", callback=opt_not_yet,
+ help = "Print file dependency information.")
+
+ op.add_option('-D',
+ dest="climb_up", default=None,
+ action="store_const", const=2,
+ help="Search up directory tree for SConstruct, "
+ "build all Default() targets.")
+
+ debug_options = ["count", "dtree", "explain", "findlibs",
+ "includes", "memoizer", "memory", "objects",
+ "pdb", "presub", "stacktrace", "stree",
+ "time", "tree"]
+
+ deprecated_debug_options = {
+ "nomemoizer" : ' and has no effect',
+ }
+
+ def opt_debug(option, opt, value, parser,
+ debug_options=debug_options,
+ deprecated_debug_options=deprecated_debug_options):
+ if value in debug_options:
+ parser.values.debug.append(value)
+ elif value in deprecated_debug_options.keys():
+ try:
+ parser.values.delayed_warnings
+ except AttributeError:
+ parser.values.delayed_warnings = []
+ msg = deprecated_debug_options[value]
+ w = "The --debug=%s option is deprecated%s." % (value, msg)
+ t = (SCons.Warnings.DeprecatedWarning, w)
+ parser.values.delayed_warnings.append(t)
+ else:
+ raise OptionValueError("Warning: %s is not a valid debug type" % value)
+ opt_debug_help = "Print various types of debugging information: %s." \
+ % string.join(debug_options, ", ")
+ op.add_option('--debug',
+ nargs=1, type="string",
+ dest="debug", default=[],
+ action="callback", callback=opt_debug,
+ help=opt_debug_help,
+ metavar="TYPE")
+
+ def opt_diskcheck(option, opt, value, parser):
+ try:
+ diskcheck_value = diskcheck_convert(value)
+ except ValueError, e:
+ raise OptionValueError("Warning: `%s' is not a valid diskcheck type" % e)
+ setattr(parser.values, option.dest, diskcheck_value)
+
+ op.add_option('--diskcheck',
+ nargs=1, type="string",
+ dest='diskcheck', default=None,
+ action="callback", callback=opt_diskcheck,
+ help="Enable specific on-disk checks.",
+ metavar="TYPE")
+
+ def opt_duplicate(option, opt, value, parser):
+ if not value in SCons.Node.FS.Valid_Duplicates:
+ raise OptionValueError("`%s' is not a valid duplication style." % value)
+ setattr(parser.values, option.dest, value)
+ # Set the duplicate style right away so it can affect linking
+ # of SConscript files.
+ SCons.Node.FS.set_duplicate(value)
+
+ opt_duplicate_help = "Set the preferred duplication methods. Must be one of " \
+ + string.join(SCons.Node.FS.Valid_Duplicates, ", ")
+
+ op.add_option('--duplicate',
+ nargs=1, type="string",
+ dest="duplicate", default='hard-soft-copy',
+ action="callback", callback=opt_duplicate,
+ help=opt_duplicate_help)
+
+ op.add_option('-f', '--file', '--makefile', '--sconstruct',
+ nargs=1, type="string",
+ dest="file", default=[],
+ action="append",
+ help="Read FILE as the top-level SConstruct file.")
+
+ op.add_option('-h', '--help',
+ dest="help", default=False,
+ action="store_true",
+ help="Print defined help message, or this one.")
+
+ op.add_option("-H", "--help-options",
+ action="help",
+ help="Print this message and exit.")
+
+ op.add_option('-i', '--ignore-errors',
+ dest='ignore_errors', default=False,
+ action="store_true",
+ help="Ignore errors from build actions.")
+
+ op.add_option('-I', '--include-dir',
+ nargs=1,
+ dest='include_dir', default=[],
+ action="append",
+ help="Search DIR for imported Python modules.",
+ metavar="DIR")
+
+ op.add_option('--implicit-cache',
+ dest='implicit_cache', default=False,
+ action="store_true",
+ help="Cache implicit dependencies")
+
+ def opt_implicit_deps(option, opt, value, parser):
+ setattr(parser.values, 'implicit_cache', True)
+ setattr(parser.values, option.dest, True)
+
+ op.add_option('--implicit-deps-changed',
+ dest="implicit_deps_changed", default=False,
+ action="callback", callback=opt_implicit_deps,
+ help="Ignore cached implicit dependencies.")
+
+ op.add_option('--implicit-deps-unchanged',
+ dest="implicit_deps_unchanged", default=False,
+ action="callback", callback=opt_implicit_deps,
+ help="Ignore changes in implicit dependencies.")
+
+ op.add_option('-j', '--jobs',
+ nargs=1, type="int",
+ dest="num_jobs", default=1,
+ action="store",
+ help="Allow N jobs at once.",
+ metavar="N")
+
+ op.add_option('-k', '--keep-going',
+ dest='keep_going', default=False,
+ action="store_true",
+ help="Keep going when a target can't be made.")
+
+ op.add_option('--max-drift',
+ nargs=1, type="int",
+ dest='max_drift', default=SCons.Node.FS.default_max_drift,
+ action="store",
+ help="Set maximum system clock drift to N seconds.",
+ metavar="N")
+
+ op.add_option('-n', '--no-exec', '--just-print', '--dry-run', '--recon',
+ dest='no_exec', default=False,
+ action="store_true",
+ help="Don't build; just print commands.")
+
+ op.add_option('--no-site-dir',
+ dest='no_site_dir', default=False,
+ action="store_true",
+ help="Don't search or use the usual site_scons dir.")
+
+ op.add_option('--profile',
+ nargs=1,
+ dest="profile_file", default=None,
+ action="store",
+ help="Profile SCons and put results in FILE.",
+ metavar="FILE")
+
+ op.add_option('-q', '--question',
+ dest="question", default=False,
+ action="store_true",
+ help="Don't build; exit status says if up to date.")
+
+ op.add_option('-Q',
+ dest='no_progress', default=False,
+ action="store_true",
+ help="Suppress \"Reading/Building\" progress messages.")
+
+ op.add_option('--random',
+ dest="random", default=False,
+ action="store_true",
+ help="Build dependencies in random order.")
+
+ op.add_option('-s', '--silent', '--quiet',
+ dest="silent", default=False,
+ action="store_true",
+ help="Don't print commands.")
+
+ op.add_option('--site-dir',
+ nargs=1,
+ dest='site_dir', default=None,
+ action="store",
+ help="Use DIR instead of the usual site_scons dir.",
+ metavar="DIR")
+
+ op.add_option('--taskmastertrace',
+ nargs=1,
+ dest="taskmastertrace_file", default=None,
+ action="store",
+ help="Trace Node evaluation to FILE.",
+ metavar="FILE")
+
+ tree_options = ["all", "derived", "prune", "status"]
+
+ def opt_tree(option, opt, value, parser, tree_options=tree_options):
+ import Main
+ tp = Main.TreePrinter()
+ for o in string.split(value, ','):
+ if o == 'all':
+ tp.derived = False
+ elif o == 'derived':
+ tp.derived = True
+ elif o == 'prune':
+ tp.prune = True
+ elif o == 'status':
+ tp.status = True
+ else:
+ raise OptionValueError("Warning: %s is not a valid --tree option" % o)
+ parser.values.tree_printers.append(tp)
+
+ opt_tree_help = "Print a dependency tree in various formats: %s." \
+ % string.join(tree_options, ", ")
+
+ op.add_option('--tree',
+ nargs=1, type="string",
+ dest="tree_printers", default=[],
+ action="callback", callback=opt_tree,
+ help=opt_tree_help,
+ metavar="OPTIONS")
+
+ op.add_option('-u', '--up', '--search-up',
+ dest="climb_up", default=0,
+ action="store_const", const=1,
+ help="Search up directory tree for SConstruct, "
+ "build targets at or below current directory.")
+
+ op.add_option('-U',
+ dest="climb_up", default=0,
+ action="store_const", const=3,
+ help="Search up directory tree for SConstruct, "
+ "build Default() targets from local SConscript.")
+
+ def opt_version(option, opt, value, parser, version=version):
+ sys.stdout.write(version + '\n')
+ sys.exit(0)
+ op.add_option("-v", "--version",
+ action="callback", callback=opt_version,
+ help="Print the SCons version number and exit.")
+
+ op.add_option('--warn', '--warning',
+ nargs=1,
+ dest="warn", default=None,
+ action="store",
+ help="Enable or disable warnings.",
+ metavar="WARNING-SPEC")
+
+ op.add_option('-Y', '--repository', '--srcdir',
+ nargs=1,
+ dest="repository", default=[],
+ action="append",
+ help="Search REPOSITORY for source and target files.")
+
+ # Options from Make and Cons classic that we do not yet support,
+ # but which we may support someday and whose (potential) meanings
+ # we don't want to change. These all get a "the -X option is not
+ # yet implemented" message and don't show up in the help output.
+
+ op.add_option('-e', '--environment-overrides',
+ dest="environment_overrides",
+ action="callback", callback=opt_not_yet,
+ # help="Environment variables override makefiles."
+ help=SUPPRESS_HELP)
+ op.add_option('-l', '--load-average', '--max-load',
+ nargs=1, type="int",
+ dest="load_average", default=0,
+ action="callback", callback=opt_not_yet,
+ # action="store",
+ # help="Don't start multiple jobs unless load is below "
+ # "LOAD-AVERAGE."
+ help=SUPPRESS_HELP)
+ op.add_option('--list-actions',
+ dest="list_actions",
+ action="callback", callback=opt_not_yet,
+ # help="Don't build; list files and build actions."
+ help=SUPPRESS_HELP)
+ op.add_option('--list-derived',
+ dest="list_derived",
+ action="callback", callback=opt_not_yet,
+ # help="Don't build; list files that would be built."
+ help=SUPPRESS_HELP)
+ op.add_option('--list-where',
+ dest="list_where",
+ action="callback", callback=opt_not_yet,
+ # help="Don't build; list files and where defined."
+ help=SUPPRESS_HELP)
+ op.add_option('-o', '--old-file', '--assume-old',
+ nargs=1, type="string",
+ dest="old_file", default=[],
+ action="callback", callback=opt_not_yet,
+ # action="append",
+ # help = "Consider FILE to be old; don't rebuild it."
+ help=SUPPRESS_HELP)
+ op.add_option('--override',
+ nargs=1, type="string",
+ action="callback", callback=opt_not_yet,
+ dest="override",
+ # help="Override variables as specified in FILE."
+ help=SUPPRESS_HELP)
+ op.add_option('-p',
+ action="callback", callback=opt_not_yet,
+ dest="p",
+ # help="Print internal environments/objects."
+ help=SUPPRESS_HELP)
+ op.add_option('-r', '-R', '--no-builtin-rules', '--no-builtin-variables',
+ action="callback", callback=opt_not_yet,
+ dest="no_builtin_rules",
+ # help="Clear default environments and variables."
+ help=SUPPRESS_HELP)
+ op.add_option('-w', '--print-directory',
+ action="callback", callback=opt_not_yet,
+ dest="print_directory",
+ # help="Print the current directory."
+ help=SUPPRESS_HELP)
+ op.add_option('--no-print-directory',
+ action="callback", callback=opt_not_yet,
+ dest="no_print_directory",
+ # help="Turn off -w, even if it was turned on implicitly."
+ help=SUPPRESS_HELP)
+ op.add_option('--write-filenames',
+ nargs=1, type="string",
+ dest="write_filenames",
+ action="callback", callback=opt_not_yet,
+ # help="Write all filenames examined into FILE."
+ help=SUPPRESS_HELP)
+ op.add_option('-W', '--new-file', '--assume-new', '--what-if',
+ nargs=1, type="string",
+ dest="new_file",
+ action="callback", callback=opt_not_yet,
+ # help="Consider FILE to be changed."
+ help=SUPPRESS_HELP)
+ op.add_option('--warn-undefined-variables',
+ dest="warn_undefined_variables",
+ action="callback", callback=opt_not_yet,
+ # help="Warn when an undefined variable is referenced."
+ help=SUPPRESS_HELP)
+
+ return op
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index d25e44c..7326c0c 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -469,7 +469,7 @@ class SConsEnvironment(SCons.Environment.Base):
def GetOption(self, name):
name = self.subst(name)
- return SCons.Script.Main.ssoptions.get(name)
+ return getattr(SCons.Script.Main.OptionsParser.values, name)
def Help(self, text):
text = self.subst(text, raw=1)
@@ -525,7 +525,7 @@ class SConsEnvironment(SCons.Environment.Base):
def SetOption(self, name, value):
name = self.subst(name)
- SCons.Script.Main.ssoptions.set(name, value)
+ SCons.Script.Main.OptionsParser.values.set_option(name, value)
#
#
diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py
index e970989..8f97c41 100644
--- a/src/engine/SCons/Script/__init__.py
+++ b/src/engine/SCons/Script/__init__.py
@@ -70,7 +70,7 @@ if "--debug=memoizer" in _args:
# for it to be displayed or not after warnings are configured.
import Main
exc_type, exc_value, tb = sys.exc_info()
- Main.delayed_warnings.append(exc_type, exc_value)
+ Main.delayed_warnings.append((exc_type, exc_value))
del _args
import SCons.Action
@@ -105,23 +105,23 @@ BuildTask = Main.BuildTask
CleanTask = Main.CleanTask
QuestionTask = Main.QuestionTask
#PrintHelp = Main.PrintHelp
-OptParser = Main.OptParser
-SConscriptSettableOptions = Main.SConscriptSettableOptions
+#SConscriptSettableOptions = Main.SConscriptSettableOptions
+AddOption = Main.AddOption
-keep_going_on_error = Main.keep_going_on_error
+#keep_going_on_error = Main.keep_going_on_error
#print_dtree = Main.print_dtree
-print_explanations = Main.print_explanations
-print_includes = Main.print_includes
-print_objects = Main.print_objects
-print_time = Main.print_time
+#print_explanations = Main.print_explanations
+#print_includes = Main.print_includes
+#print_objects = Main.print_objects
+#print_time = Main.print_time
#print_tree = Main.print_tree
-memory_stats = Main.memory_stats
-ignore_errors = Main.ignore_errors
+#memory_stats = Main.memory_stats
+#ignore_errors = Main.ignore_errors
#sconscript_time = Main.sconscript_time
#command_time = Main.command_time
#exit_status = Main.exit_status
#profiling = Main.profiling
-repositories = Main.repositories
+#repositories = Main.repositories
#
import SConscript
@@ -138,6 +138,7 @@ Builder = SCons.Builder.Builder
Configure = _SConscript.Configure
EnumOption = SCons.Options.EnumOption
Environment = SCons.Environment.Environment
+#OptParser = SCons.SConsOptions.OptParser
FindPathDirs = SCons.Scanner.FindPathDirs
ListOption = SCons.Options.ListOption
PackageOption = SCons.Options.PackageOption