summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Script/Main.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons/Script/Main.py')
-rw-r--r--src/engine/SCons/Script/Main.py104
1 files changed, 82 insertions, 22 deletions
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
index 97e0b19..bcbd0a1 100644
--- a/src/engine/SCons/Script/Main.py
+++ b/src/engine/SCons/Script/Main.py
@@ -68,6 +68,18 @@ import SCons.Taskmaster
import SCons.Util
import SCons.Warnings
+import SCons.Script.Interactive
+
+def fetch_win32_parallel_msg():
+ # A subsidiary function that exists solely to isolate this import
+ # 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
+ # versions (2.1) of Python.
+ import SCons.Platform.win32
+ SCons.Platform.win32.parallel_msg
+
#
class SConsPrintHelpException(Exception):
@@ -730,7 +742,6 @@ def version_string(label, module):
module.__buildsys__)
def _main(parser):
- import SCons
global exit_status
options = parser.values
@@ -750,7 +761,8 @@ def _main(parser):
SCons.Warnings.NoMetaclassSupportWarning,
SCons.Warnings.NoObjectCountWarning,
SCons.Warnings.NoParallelSupportWarning,
- SCons.Warnings.MisleadingKeywordsWarning, ]
+ SCons.Warnings.MisleadingKeywordsWarning,
+ SCons.Warnings.StackSizeWarning, ]
for warning in default_warnings:
SCons.Warnings.enableWarningClass(warning)
SCons.Warnings._warningOut = _scons_internal_warning
@@ -835,10 +847,10 @@ def _main(parser):
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.no_exec:
SCons.SConf.dryrun = 1
SCons.Action.execute_actions = None
- CleanTask.execute = CleanTask.show
if options.question:
SCons.SConf.dryrun = 1
if options.clean:
@@ -850,19 +862,6 @@ def _main(parser):
if options.no_progress or options.silent:
progress_display.set_mode(0)
- if options.silent:
- display.set_mode(0)
- if options.silent:
- SCons.Action.print_actions = None
-
- if options.cache_disable:
- SCons.CacheDir.CacheDir = SCons.Util.Null()
- if options.cache_debug:
- SCons.CacheDir.cache_debug = options.cache_debug
- if options.cache_force:
- SCons.CacheDir.cache_force = True
- if options.cache_show:
- SCons.CacheDir.cache_show = True
if options.site_dir:
_load_site_scons_dir(d, options.site_dir)
@@ -887,7 +886,18 @@ def _main(parser):
SCons.Script._Add_Targets(targets + parser.rargs)
SCons.Script._Add_Arguments(xmit_args)
- sys.stdout = SCons.Util.Unbuffered(sys.stdout)
+ # If stdout is not a tty, replace it with a wrapper object to call flush
+ # after every write.
+ #
+ # Tty devices automatically flush after every newline, so the replacement
+ # isn't necessary. Furthermore, if we replace sys.stdout, the readline
+ # module will no longer work. This affects the behavior during
+ # --interactive mode. --interactive should only be used when stdin and
+ # stdout refer to a tty.
+ if not sys.stdout.isatty():
+ sys.stdout = SCons.Util.Unbuffered(sys.stdout)
+ if not sys.stderr.isatty():
+ sys.stderr = SCons.Util.Unbuffered(sys.stderr)
memory_stats.append('before reading SConscript files:')
count_stats.append(('pre-', 'read'))
@@ -956,6 +966,47 @@ def _main(parser):
SCons.Node.implicit_cache = options.implicit_cache
SCons.Node.FS.set_duplicate(options.duplicate)
fs.set_max_drift(options.max_drift)
+ if not options.stack_size is None:
+ SCons.Job.stack_size = options.stack_size
+
+ platform = SCons.Platform.platform_module()
+
+ if options.interactive:
+ SCons.Script.Interactive.interact(fs, OptionsParser, options,
+ targets, target_top)
+
+ else:
+
+ # Build the targets
+ nodes = _build_targets(fs, options, targets, target_top)
+ if not nodes:
+ exit_status = 2
+
+def _build_targets(fs, options, targets, target_top):
+
+ progress_display.set_mode(not (options.no_progress or options.silent))
+ display.set_mode(not options.silent)
+ SCons.Action.print_actions = not options.silent
+ SCons.Action.execute_actions = not options.no_exec
+ SCons.SConf.dryrun = options.no_exec
+
+ 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
+ SCons.CacheDir.cache_show = options.cache_show
+
+ if options.no_exec:
+ CleanTask.execute = CleanTask.show
+ else:
+ CleanTask.execute = CleanTask.remove
lookup_top = None
if targets or SCons.Script.BUILD_TARGETS != SCons.Script._build_plus_default:
@@ -1003,7 +1054,7 @@ def _main(parser):
if not targets:
sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n")
- sys.exit(2)
+ return None
def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
if isinstance(x, SCons.Node.Node):
@@ -1046,7 +1097,7 @@ def _main(parser):
opening_message = "Cleaning targets ..."
closing_message = "done cleaning targets."
if options.keep_going:
- closing_message = "done cleaning targets (errors occurred during clean)."
+ failure_message = "done cleaning targets (errors occurred during clean)."
else:
failure_message = "cleaning terminated because of errors."
except AttributeError:
@@ -1091,8 +1142,7 @@ def _main(parser):
msg = "parallel builds are unsupported by this version of Python;\n" + \
"\tignoring -j or num_jobs option.\n"
elif sys.platform == 'win32':
- import SCons.Platform.win32
- msg = SCons.Platform.win32.parallel_msg
+ msg = fetch_win32_parallel_msg()
if msg:
SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
@@ -1101,7 +1151,15 @@ def _main(parser):
try:
progress_display("scons: " + opening_message)
- jobs.run()
+ 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()
if exit_status:
@@ -1114,6 +1172,8 @@ def _main(parser):
memory_stats.append('after building targets:')
count_stats.append(('post-', 'build'))
+ return nodes
+
def _exec_main(parser, values):
sconsflags = os.environ.get('SCONSFLAGS', '')
all_args = string.split(sconsflags) + sys.argv[1:]