summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Script
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons/Script')
-rw-r--r--src/engine/SCons/Script/Interactive.py10
-rw-r--r--src/engine/SCons/Script/Main.py87
-rw-r--r--src/engine/SCons/Script/SConsOptions.py69
-rw-r--r--src/engine/SCons/Script/SConscript.py4
-rw-r--r--src/engine/SCons/Script/__init__.py23
5 files changed, 115 insertions, 78 deletions
diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py
index d18eec1..b1774eb 100644
--- a/src/engine/SCons/Script/Interactive.py
+++ b/src/engine/SCons/Script/Interactive.py
@@ -185,6 +185,16 @@ class SConsInteractiveCmd(cmd.Cmd):
if not nodes:
return
+ # Call each of the Node's alter_targets() methods, which may
+ # provide additional targets that ended up as part of the build
+ # (the canonical example being a VariantDir() when we're building
+ # from a source directory) and which we therefore need their
+ # state cleared, too.
+ x = []
+ for n in nodes:
+ x.extend(n.alter_targets()[0])
+ nodes.extend(x)
+
# Clean up so that we can perform the next build correctly.
#
# We do this by walking over all the children of the targets,
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
index 80b9032..75d0117 100644
--- a/src/engine/SCons/Script/Main.py
+++ b/src/engine/SCons/Script/Main.py
@@ -168,28 +168,29 @@ class BuildTask(SCons.Taskmaster.Task):
self.progress(self.targets[0])
return SCons.Taskmaster.Task.prepare(self)
- def execute(self):
- for target in self.targets:
- if target.get_state() == SCons.Node.up_to_date:
- continue
- if target.has_builder() and not hasattr(target.builder, 'status'):
- if print_time:
- start_time = time.time()
- global first_command_start
- if first_command_start is None:
- first_command_start = start_time
- SCons.Taskmaster.Task.execute(self)
- if print_time:
- global cumulative_command_time
- global last_command_end
- finish_time = time.time()
- last_command_end = finish_time
- cumulative_command_time = cumulative_command_time+finish_time-start_time
- sys.stdout.write("Command execution time: %f seconds\n"%(finish_time-start_time))
- break
+ def needs_execute(self):
+ target = self.targets[0]
+ if target.get_state() == SCons.Node.executing:
+ return True
else:
if self.top and target.has_builder():
display("scons: `%s' is up to date." % str(self.node))
+ return False
+
+ def execute(self):
+ if print_time:
+ start_time = time.time()
+ global first_command_start
+ if first_command_start is None:
+ first_command_start = start_time
+ SCons.Taskmaster.Task.execute(self)
+ if print_time:
+ global cumulative_command_time
+ global last_command_end
+ finish_time = time.time()
+ last_command_end = finish_time
+ cumulative_command_time = cumulative_command_time+finish_time-start_time
+ sys.stdout.write("Command execution time: %f seconds\n"%(finish_time-start_time))
def do_failed(self, status=2):
_BuildFailures.append(self.exception[1])
@@ -207,10 +208,15 @@ class BuildTask(SCons.Taskmaster.Task):
t = self.targets[0]
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)
+ errstr="Do not know how to make target `%s'." % t
+ sys.stderr.write("scons: *** " + errstr)
if not self.options.keep_going:
sys.stderr.write(" Stop.")
sys.stderr.write("\n")
+ try:
+ raise SCons.Errors.BuildError(t, errstr)
+ except:
+ self.exception_set()
self.do_failed()
else:
print "scons: Nothing to be done for `%s'." % t
@@ -977,11 +983,6 @@ def _build_targets(fs, options, targets, target_top):
if options.diskcheck:
SCons.Node.FS.set_diskcheck(options.diskcheck)
- _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
-
SCons.CacheDir.cache_enabled = not options.cache_disable
SCons.CacheDir.cache_debug = options.cache_debug
SCons.CacheDir.cache_force = options.cache_force
@@ -1133,26 +1134,29 @@ def _build_targets(fs, options, targets, target_top):
memory_stats.append('before building targets:')
count_stats.append(('pre-', 'build'))
- try:
- progress_display("scons: " + opening_message)
- try:
- jobs.run()
- except KeyboardInterrupt:
- # If we are in interactive mode, a KeyboardInterrupt
- # interrupts only this current run. Return 'nodes' normally
- # so that the outer loop can clean up the nodes and continue.
- if options.interactive:
- print "Build interrupted."
- # Continue and return normally
- finally:
- jobs.cleanup()
+ def jobs_postfunc(
+ jobs=jobs,
+ options=options,
+ closing_message=closing_message,
+ failure_message=failure_message
+ ):
+ if jobs.were_interrupted():
+ progress_display("scons: Build interrupted.")
+ global exit_status
+ exit_status = 2
+
if exit_status:
progress_display("scons: " + failure_message)
else:
progress_display("scons: " + closing_message)
if not options.no_exec:
+ if jobs.were_interrupted():
+ progress_display("scons: writing .sconsign file.")
SCons.SConsign.write()
+ progress_display("scons: " + opening_message)
+ jobs.run(postfunc = jobs_postfunc)
+
memory_stats.append('after building targets:')
count_stats.append(('post-', 'build'))
@@ -1210,10 +1214,9 @@ def main():
parts = ["SCons by Steven Knight et al.:\n"]
try:
+ import __main__
parts.append(version_string("script", __main__))
- except KeyboardInterrupt:
- raise
- except:
+ except (ImportError, AttributeError):
# On Windows there is no scons.py, so there is no
# __main__.__version__, hence there is no script version.
pass
@@ -1233,7 +1236,7 @@ def main():
if s:
exit_status = s
except KeyboardInterrupt:
- print "Build interrupted."
+ print("scons: Build interrupted.")
sys.exit(2)
except SyntaxError, e:
_scons_syntax_error(e)
diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py
index ee34a85..2148068 100644
--- a/src/engine/SCons/Script/SConsOptions.py
+++ b/src/engine/SCons/Script/SConsOptions.py
@@ -26,11 +26,19 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
import optparse
+import re
import string
import sys
import textwrap
try:
+ no_hyphen_re = re.compile(r'(\s+|(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))')
+except re.error:
+ # Pre-2.0 Python versions don't have the (?<= negative
+ # look-behind assertion.
+ no_hyphen_re = re.compile(r'(\s+|-*\w{2,}-(?=\w{2,}))')
+
+try:
from gettext import gettext
except ImportError:
def gettext(message):
@@ -382,8 +390,16 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter):
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...
+ method. This has been snarfed so we can modify text wrapping to
+ out liking:
+
+ -- add our own regular expression that doesn't break on hyphens
+ (so things like --no-print-directory don't get broken);
+
+ -- wrap the list of options themselves when it's too long
+ (the wrapper.fill(opts) call below);
+
+ -- set the subsequent_indent when wrapping the help_text.
"""
# The help for each option consists of two parts:
# * the opt strings and metavars
@@ -410,7 +426,11 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter):
opt_width = self.help_position - self.current_indent - 2
if len(opts) > opt_width:
- opts = "%*s%s\n" % (self.current_indent, "", opts)
+ wrapper = textwrap.TextWrapper(width=self.width,
+ initial_indent = ' ',
+ subsequent_indent = ' ')
+ wrapper.wordsep_re = no_hyphen_re
+ opts = wrapper.fill(opts) + '\n'
indent_first = self.help_position
else: # start help on same line as opts
opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts)
@@ -428,8 +448,10 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter):
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 = ' ')
+ wrapper = textwrap.TextWrapper(width=self.help_width,
+ subsequent_indent = ' ')
+ wrapper.wordsep_re = no_hyphen_re
+ help_lines = wrapper.wrap(help_text)
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))
@@ -503,8 +525,13 @@ def Parser(version):
# 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",
+ op.add_option("-b", "-d", "-e", "-m", "-S", "-t", "-w",
+ "--environment-overrides",
+ "--no-keep-going",
+ "--no-print-directory",
+ "--print-directory",
+ "--stop",
+ "--touch",
action="callback", callback=opt_ignore,
help="Ignored for compatibility.")
@@ -557,13 +584,6 @@ def Parser(version):
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,
@@ -836,11 +856,12 @@ def Parser(version):
# 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)
+ def opt_not_yet(option, opt, value, parser):
+ msg = "Warning: the %s option is not yet implemented\n" % opt
+ sys.stderr.write(msg)
+ sys.exit(0)
+
+
op.add_option('-l', '--load-average', '--max-load',
nargs=1, type="int",
dest="load_average", default=0,
@@ -887,16 +908,6 @@ def Parser(version):
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",
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index 36a147d..7e38ffd 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -39,7 +39,6 @@ import SCons.Errors
import SCons.Node
import SCons.Node.Alias
import SCons.Node.FS
-import SCons.Options
import SCons.Platform
import SCons.SConf
import SCons.Script.Main
@@ -141,7 +140,8 @@ call_stack = []
def Return(*vars, **kw):
retval = []
try:
- for var in vars:
+ fvars = SCons.Util.flatten(vars)
+ for var in fvars:
for v in string.split(var):
retval.append(call_stack[-1].globals[v])
except KeyError, x:
diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py
index ddeaf9e..72e31d1 100644
--- a/src/engine/SCons/Script/__init__.py
+++ b/src/engine/SCons/Script/__init__.py
@@ -84,6 +84,7 @@ import SCons.SConf
import SCons.Subst
import SCons.Tool
import SCons.Util
+import SCons.Variables
import SCons.Defaults
import Main
@@ -138,22 +139,31 @@ call_stack = _SConscript.call_stack
Action = SCons.Action.Action
AddMethod = SCons.Util.AddMethod
AllowSubstExceptions = SCons.Subst.SetAllowableExceptions
-BoolOption = SCons.Options.BoolOption
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
-PathOption = SCons.Options.PathOption
Platform = SCons.Platform.Platform
Return = _SConscript.Return
Scanner = SCons.Scanner.Base
Tool = SCons.Tool.Tool
WhereIs = SCons.Util.WhereIs
+#
+BoolVariable = SCons.Variables.BoolVariable
+EnumVariable = SCons.Variables.EnumVariable
+ListVariable = SCons.Variables.ListVariable
+PackageVariable = SCons.Variables.PackageVariable
+PathVariable = SCons.Variables.PathVariable
+
+# Deprecated names that will go away some day.
+BoolOption = SCons.Options.BoolOption
+EnumOption = SCons.Options.EnumOption
+ListOption = SCons.Options.ListOption
+PackageOption = SCons.Options.PackageOption
+PathOption = SCons.Options.PathOption
+
# Action factories.
Chmod = SCons.Defaults.Chmod
Copy = SCons.Defaults.Copy
@@ -262,6 +272,9 @@ def HelpFunction(text):
sconscript_reading = 0
#
+def Variables(files=[], args=ARGUMENTS):
+ return SCons.Variables.Variables(files, args)
+
def Options(files=[], args=ARGUMENTS):
return SCons.Options.Options(files, args)