summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Script
diff options
context:
space:
mode:
authorRussel Winder <russel@winder.org.uk>2015-12-24 16:32:14 (GMT)
committerRussel Winder <russel@winder.org.uk>2015-12-24 16:32:14 (GMT)
commit2a270c8f314e959c78e9deda29c8f250bb934dd6 (patch)
tree7008e644357036404f0861c8ba1bbbf43b2b4123 /src/engine/SCons/Script
parenta7d764ed831fa3243aa0bd3307f641e1e1f9f8a8 (diff)
parent9d558dd65deacc958edc1f0da2dab1ec56ff4e4e (diff)
downloadSCons-2a270c8f314e959c78e9deda29c8f250bb934dd6.zip
SCons-2a270c8f314e959c78e9deda29c8f250bb934dd6.tar.gz
SCons-2a270c8f314e959c78e9deda29c8f250bb934dd6.tar.bz2
Post merge commit for safety. Building Fortran code works, but tests fail.
Diffstat (limited to 'src/engine/SCons/Script')
-rw-r--r--src/engine/SCons/Script/Interactive.py6
-rw-r--r--src/engine/SCons/Script/Main.py71
-rw-r--r--src/engine/SCons/Script/SConsOptions.py70
-rw-r--r--src/engine/SCons/Script/SConscript.py23
-rw-r--r--src/engine/SCons/Script/SConscript.xml16
-rw-r--r--src/engine/SCons/Script/__init__.py20
6 files changed, 69 insertions, 137 deletions
diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py
index 0b28f1a..e7a0658 100644
--- a/src/engine/SCons/Script/Interactive.py
+++ b/src/engine/SCons/Script/Interactive.py
@@ -305,14 +305,8 @@ class SConsInteractiveCmd(cmd.Cmd):
return self._strip_initial_spaces(doc)
def _strip_initial_spaces(self, s):
- #lines = s.split('\n')
lines = s.split('\n')
spaces = re.match(' *', lines[0]).group(0)
- #def strip_spaces(l):
- # if l.startswith(spaces):
- # l = l[len(spaces):]
- # return l
- #return '\n'.join([ strip_spaces(l) for l in lines ])
def strip_spaces(l, spaces=spaces):
if l[:len(spaces)] == spaces:
l = l[len(spaces):]
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
index 3ef88c7..71d64fc 100644
--- a/src/engine/SCons/Script/Main.py
+++ b/src/engine/SCons/Script/Main.py
@@ -10,11 +10,7 @@ some other module. If it's specific to the "scons" script invocation,
it goes here.
"""
-# Would affect exec()'d site_init.py:
-## from __future__ import print_function
-from SCons.compat.six import print_
-
-unsupported_python_version = (2, 3, 0)
+unsupported_python_version = (2, 6, 0)
deprecated_python_version = (2, 7, 0)
# __COPYRIGHT__
@@ -47,15 +43,6 @@ import sys
import time
import traceback
-# Strip the script directory from sys.path() so on case-insensitive
-# (Windows) systems Python doesn't think that the "scons" script is the
-# "SCons" package. Replace it with our own version directory so, if
-# if they're there, we pick up the right version of the build engine
-# modules.
-#sys.path = [os.path.join(sys.prefix,
-# 'lib',
-# 'scons-%d' % SCons.__version__)] + sys.path[1:]
-
import SCons.CacheDir
import SCons.Debug
import SCons.Defaults
@@ -78,7 +65,7 @@ def fetch_win32_parallel_msg():
# so we don't have to pull it in on all platforms, and so that an
# in-line "import" statement in the _main() function below doesn't
# cause warnings about local names shadowing use of the 'SCons'
- # globl in nest scopes and UnboundLocalErrors and the like in some
+ # global in nest scopes and UnboundLocalErrors and the like in some
# versions (2.1) of Python.
import SCons.Platform.win32
return SCons.Platform.win32.parallel_msg
@@ -218,7 +205,7 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask):
if self.top and not t.has_builder() and not t.side_effect:
if not t.exists():
if t.__class__.__name__ in ('File', 'Dir', 'Entry'):
- errstr="Do not know how to make %s target `%s' (%s)." % (t.__class__.__name__, t, t.abspath)
+ errstr="Do not know how to make %s target `%s' (%s)." % (t.__class__.__name__, t, t.get_abspath())
else: # Alias or Python or ...
errstr="Do not know how to make %s target `%s'." % (t.__class__.__name__, t)
sys.stderr.write("scons: *** " + errstr)
@@ -355,7 +342,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask):
if target in SCons.Environment.CleanTargets:
files = SCons.Environment.CleanTargets[target]
for f in files:
- self.fs_delete(f.abspath, str(f), remove)
+ self.fs_delete(f.get_abspath(), str(f), remove)
def show(self):
for t in self._get_files_to_clean():
@@ -372,8 +359,8 @@ class CleanTask(SCons.Taskmaster.AlwaysTask):
# issue, an IOError would indicate something like
# the file not existing. In either case, print a
# message and keep going to try to remove as many
- # targets aa possible.
- print(("scons: Could not remove '%s':" % str(t), e.strerror)
+ # targets as possible.
+ print("scons: Could not remove '{}':".format(str(t)), e.strerror)
else:
if removed:
display("Removed " + str(t))
@@ -387,7 +374,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask):
# we don't want, like store .sconsign information.
executed = SCons.Taskmaster.Task.executed_without_callbacks
- # Have the taskmaster arrange to "execute" all of the targets, because
+ # Have the Taskmaster arrange to "execute" all of the targets, because
# we'll figure out ourselves (in remove() or show() above) whether
# anything really needs to be done.
make_ready = SCons.Taskmaster.Task.make_ready_all
@@ -488,7 +475,9 @@ def GetOption(name):
def SetOption(name, value):
return OptionsParser.values.set_option(name, value)
-#
+def PrintHelp(file=None):
+ OptionsParser.print_help(file=file)
+
class Stats(object):
def __init__(self):
self.stats = []
@@ -676,7 +665,7 @@ def _set_debug_values(options):
if "prepare" in debug_values:
SCons.Taskmaster.print_prepare = 1
if "duplicate" in debug_values:
- SCons.Node.FS.print_duplicate = 1
+ SCons.Node.print_duplicate = 1
def _create_path(plist):
path = '.'
@@ -712,7 +701,6 @@ def _load_site_scons_dir(topdir, site_dir_name=None):
site_tools_dir = os.path.join(site_dir, site_tools_dirname)
if os.path.exists(site_init_file):
import imp, re
- # TODO(2.4): turn this into try:-except:-finally:
try:
try:
fp, pathname, description = imp.find_module(site_init_modname,
@@ -950,13 +938,21 @@ def _main(parser):
progress_display.set_mode(0)
if options.site_dir:
- _load_site_scons_dir(d.path, options.site_dir)
+ _load_site_scons_dir(d.get_internal_path(), options.site_dir)
elif not options.no_site_dir:
- _load_all_site_scons_dirs(d.path)
+ _load_all_site_scons_dirs(d.get_internal_path())
if options.include_dir:
sys.path = options.include_dir + sys.path
+ # If we're about to start SCons in the interactive mode,
+ # inform the FS about this right here. Else, the release_target_info
+ # method could get called on some nodes, like the used "gcc" compiler,
+ # when using the Configure methods within the SConscripts.
+ # This would then cause subtle bugs, as already happened in #2971.
+ if options.interactive:
+ SCons.Node.interactive = True
+
# That should cover (most of) the options. Next, set up the variables
# that hold command-line arguments, so the SConscript files that we
# read and execute have access to them.
@@ -1017,7 +1013,7 @@ def _main(parser):
# the SConscript file.
#
# We delay enabling the PythonVersionWarning class until here so that,
- # if they explicity disabled it in either in the command line or in
+ # if they explicitly disabled it in either in the command line or in
# $SCONSFLAGS, or in the SConscript file, then the search through
# the list of deprecated warning classes will find that disabling
# first and not issue the warning.
@@ -1086,7 +1082,6 @@ def _main(parser):
platform = SCons.Platform.platform_module()
if options.interactive:
- SCons.Node.interactive = True
SCons.Script.Interactive.interact(fs, OptionsParser, options,
targets, target_top)
@@ -1108,7 +1103,6 @@ def _build_targets(fs, options, targets, target_top):
display.set_mode(not options.silent)
SCons.Action.print_actions = not options.silent
SCons.Action.execute_actions = not options.no_exec
- SCons.Node.FS.do_store_info = not options.no_exec
SCons.Node.do_store_info = not options.no_exec
SCons.SConf.dryrun = options.no_exec
@@ -1227,13 +1221,8 @@ def _build_targets(fs, options, targets, target_top):
def order(dependencies):
"""Randomize the dependencies."""
import random
- # This is cribbed from the implementation of
- # random.shuffle() in Python 2.X.
- d = dependencies
- for i in range(len(d)-1, 0, -1):
- j = int(random.random() * (i+1))
- d[i], d[j] = d[j], d[i]
- return d
+ random.shuffle(dependencies)
+ return dependencies
else:
def order(dependencies):
"""Leave the order of dependencies alone."""
@@ -1311,18 +1300,6 @@ def _exec_main(parser, values):
# compat layer imports "cProfile" for us if it's available.
from profile import Profile
- # Some versions of Python 2.4 shipped a profiler that had the
- # wrong 'c_exception' entry in its dispatch table. Make sure
- # we have the right one. (This may put an unnecessary entry
- # in the table in earlier versions of Python, but its presence
- # shouldn't hurt anything).
- try:
- dispatch = Profile.dispatch
- except AttributeError:
- pass
- else:
- dispatch['c_exception'] = Profile.trace_dispatch_return
-
prof = Profile()
try:
prof.runcall(_main, parser)
diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py
index 1250e6b..b2f2858 100644
--- a/src/engine/SCons/Script/SConsOptions.py
+++ b/src/engine/SCons/Script/SConsOptions.py
@@ -268,7 +268,7 @@ class SConsOptionParser(optparse.OptionParser):
preserve_unknown_options = False
def error(self, msg):
- # overriden OptionValueError exception handler
+ # overridden OptionValueError exception handler
self.print_usage(sys.stderr)
sys.stderr.write("SCons Error: %s\n" % msg)
sys.exit(2)
@@ -319,7 +319,13 @@ class SConsOptionParser(optparse.OptionParser):
value = option.const
elif len(rargs) < nargs:
if nargs == 1:
- self.error(_("%s option requires an argument") % opt)
+ if not option.choices:
+ self.error(_("%s option requires an argument") % opt)
+ else:
+ msg = _("%s option requires an argument " % opt)
+ msg += _("(choose from %s)"
+ % ', '.join(option.choices))
+ self.error(msg)
else:
self.error(_("%s option requires %d arguments")
% (opt, nargs))
@@ -420,7 +426,7 @@ class SConsOptionParser(optparse.OptionParser):
result = group.add_option(*args, **kw)
if result:
- # The option was added succesfully. We now have to add the
+ # The option was added successfully. 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
@@ -443,11 +449,6 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter):
"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)
@@ -482,13 +483,7 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter):
# 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
-
+ opts = self.option_strings[option]
opt_width = self.help_position - self.current_indent - 2
if len(opts) > opt_width:
wrapper = textwrap.TextWrapper(width=self.width,
@@ -503,14 +498,7 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter):
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)
+ help_text = self.expand_default(option)
# SCons: indent every line of the help text but the first.
wrapper = textwrap.TextWrapper(width=self.help_width,
@@ -524,34 +512,6 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter):
result.append("\n")
return "".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 option.dest.upper()
- 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 ", ".join(opts)
-
def Parser(version):
"""
Returns an options parser object initialized with the standard
@@ -645,18 +605,12 @@ def Parser(version):
config_options = ["auto", "force" ,"cache"]
- def opt_config(option, opt, value, parser, c_options=config_options):
- if not value in c_options:
- raise OptionValueError(opt_invalid('config', value, c_options))
- setattr(parser.values, option.dest, value)
-
opt_config_help = "Controls Configure subsystem: %s." \
% ", ".join(config_options)
op.add_option('--config',
- nargs=1, type="string",
+ nargs=1, choices=config_options,
dest="config", default="auto",
- action="callback", callback=opt_config,
help = opt_config_help,
metavar="MODE")
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index d50951d..ab032be 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -51,16 +51,6 @@ import re
import sys
import traceback
-# The following variables used to live in this module. Some
-# SConscript files out there may have referred to them directly as
-# SCons.Script.SConscript.*. This is now supported by some special
-# handling towards the bottom of the SConscript.__init__.py module.
-#Arguments = {}
-#ArgList = []
-#BuildTargets = TargetList()
-#CommandLineTargets = []
-#DefaultTargets = []
-
class SConscriptReturn(Exception):
pass
@@ -265,7 +255,7 @@ def _SConscript(fs, *files, **kw):
call_stack[-1].globals.update({__file__:old_file})
else:
SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning,
- "Ignoring missing SConscript '%s'" % f.path)
+ "Ignoring missing SConscript '%s'" % f.get_internal_path())
finally:
SCons.Script.sconscript_reading = SCons.Script.sconscript_reading - 1
@@ -438,7 +428,7 @@ class SConsEnvironment(SCons.Environment.Base):
fname = fn.get_path(src_dir)
files = [os.path.join(str(variant_dir), fname)]
else:
- files = [fn.abspath]
+ files = [fn.get_abspath()]
kw['src_dir'] = variant_dir
self.fs.VariantDir(variant_dir, src_dir, duplicate)
@@ -446,7 +436,7 @@ class SConsEnvironment(SCons.Environment.Base):
#
# Public methods of an SConsEnvironment. These get
- # entry points in the global name space so they can be called
+ # entry points in the global namespace so they can be called
# as global functions.
#
@@ -461,7 +451,8 @@ class SConsEnvironment(SCons.Environment.Base):
def EnsureSConsVersion(self, major, minor, revision=0):
"""Exit abnormally if the SCons version is not late enough."""
- if SCons.__version__ == '__VERSION__':
+ # split string to avoid replacement during build process
+ if SCons.__version__ == '__' + 'VERSION__':
SCons.Warnings.warn(SCons.Warnings.DevelopmentVersionWarning,
"EnsureSConsVersion is ignored for development version")
return
@@ -498,9 +489,9 @@ class SConsEnvironment(SCons.Environment.Base):
name = self.subst(name)
return SCons.Script.Main.GetOption(name)
- def Help(self, text):
+ def Help(self, text, append=False):
text = self.subst(text, raw=1)
- SCons.Script.HelpFunction(text)
+ SCons.Script.HelpFunction(text, append=append)
def Import(self, *vars):
try:
diff --git a/src/engine/SCons/Script/SConscript.xml b/src/engine/SCons/Script/SConscript.xml
index c74ad5e..8553fbe 100644
--- a/src/engine/SCons/Script/SConscript.xml
+++ b/src/engine/SCons/Script/SConscript.xml
@@ -240,7 +240,7 @@ file is found.
<scons_function name="Help">
<arguments>
-(text)
+(text, append=False)
</arguments>
<summary>
<para>
@@ -248,12 +248,18 @@ This specifies help text to be printed if the
<option>-h</option>
argument is given to
&scons;.
-If
+If
&f-Help;
-is called multiple times, the text is appended together in the order
-that
+is called multiple times, the text is appended together in the order that
&f-Help;
-is called.
+is called. With append set to False, any
+&f-Help;
+text generated with
+&f-AddOption;
+is clobbered. If append is True, the AddOption help is prepended to the help
+string, thus preserving the
+<option>-h</option>
+message.
</para>
</summary>
</scons_function>
diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py
index e9e8b71..974841c 100644
--- a/src/engine/SCons/Script/__init__.py
+++ b/src/engine/SCons/Script/__init__.py
@@ -41,6 +41,7 @@ start_time = time.time()
import collections
import os
+import StringIO
import sys
# Special chicken-and-egg handling of the "--debug=memoizer" flag:
@@ -107,6 +108,7 @@ QuestionTask = Main.QuestionTask
#SConscriptSettableOptions = Main.SConscriptSettableOptions
AddOption = Main.AddOption
+PrintHelp = Main.PrintHelp
GetOption = Main.GetOption
SetOption = Main.SetOption
Progress = Main.Progress
@@ -258,12 +260,19 @@ def _Set_Default_Targets(env, tlist):
#
help_text = None
-def HelpFunction(text):
+def HelpFunction(text, append=False):
global help_text
- if SCons.Script.help_text is None:
- SCons.Script.help_text = text
- else:
- help_text = help_text + text
+ if help_text is None:
+ if append:
+ s = StringIO.StringIO()
+ PrintHelp(s)
+ help_text = s.getvalue()
+ s.close()
+ else:
+ help_text = ""
+
+ help_text= help_text + text
+
#
# Will be non-zero if we are reading an SConscript file.
@@ -318,6 +327,7 @@ GlobalDefaultEnvironmentFunctions = [
'Ignore',
'Install',
'InstallAs',
+ 'InstallVersionedLib',
'Literal',
'Local',
'ParseDepends',