summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Moody <dmoody256@gmail.com>2022-02-11 20:13:05 (GMT)
committerDaniel Moody <dmoody256@gmail.com>2022-02-11 20:13:05 (GMT)
commitd8932c2b87cfef617b2412afc6db024ba6e9560a (patch)
treec96bd3214e10d75050be5a9ffe6ef942f32f4729
parent3b8798ff671969a7211ccd7a5b579d6d84f22d6d (diff)
downloadSCons-d8932c2b87cfef617b2412afc6db024ba6e9560a.zip
SCons-d8932c2b87cfef617b2412afc6db024ba6e9560a.tar.gz
SCons-d8932c2b87cfef617b2412afc6db024ba6e9560a.tar.bz2
fix up interactive to support ninja scons daemon
-rw-r--r--SCons/Node/__init__.py1
-rw-r--r--SCons/Script/Interactive.py149
-rw-r--r--SCons/Script/Main.py5
-rw-r--r--SCons/Script/SConsOptions.py5
4 files changed, 88 insertions, 72 deletions
diff --git a/SCons/Node/__init__.py b/SCons/Node/__init__.py
index ec742a6..d0539b4 100644
--- a/SCons/Node/__init__.py
+++ b/SCons/Node/__init__.py
@@ -105,6 +105,7 @@ SConscriptNodes = set()
# currently used to release parts of a target's info during
# clean builds and update runs (see release_target_info).
interactive = False
+ninja_scons_daemon = False
def is_derived_none(node):
raise NotImplementedError
diff --git a/SCons/Script/Interactive.py b/SCons/Script/Interactive.py
index 26a8bcd..ad021fd 100644
--- a/SCons/Script/Interactive.py
+++ b/SCons/Script/Interactive.py
@@ -188,77 +188,86 @@ version Prints SCons version information.
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,
- # and clearing their state.
- #
- # We currently have to re-scan each node to find their
- # children, because built nodes have already been partially
- # cleared and don't remember their children. (In scons
- # 0.96.1 and earlier, this wasn't the case, and we didn't
- # have to re-scan the nodes.)
- #
- # Because we have to re-scan each node, we can't clear the
- # nodes as we walk over them, because we may end up rescanning
- # a cleared node as we scan a later node. Therefore, only
- # store the list of nodes that need to be cleared as we walk
- # the tree, and clear them in a separate pass.
- #
- # XXX: Someone more familiar with the inner workings of scons
- # may be able to point out a more efficient way to do this.
-
- SCons.Script.Main.progress_display("scons: Clearing cached node information ...")
-
- seen_nodes = {}
-
- def get_unseen_children(node, parent, seen_nodes=seen_nodes):
- def is_unseen(node, seen_nodes=seen_nodes):
- return node not in seen_nodes
- return [child for child in node.children(scan=1) if is_unseen(child)]
-
- def add_to_seen_nodes(node, parent, seen_nodes=seen_nodes):
- seen_nodes[node] = 1
-
- # If this file is in a VariantDir and has a
- # corresponding source file in the source tree, remember the
- # node in the source tree, too. This is needed in
- # particular to clear cached implicit dependencies on the
- # source file, since the scanner will scan it if the
- # VariantDir was created with duplicate=0.
- try:
- rfile_method = node.rfile
- except AttributeError:
- return
- else:
- rfile = rfile_method()
- if rfile != node:
- seen_nodes[rfile] = 1
-
- for node in nodes:
- walker = SCons.Node.Walker(node,
- kids_func=get_unseen_children,
- eval_func=add_to_seen_nodes)
- n = walker.get_next()
- while n:
+ if SCons.Node.ninja_scons_daemon:
+ for n in nodes:
+ print(f"Node: {n}, State: {SCons.Node.failed}")
+ if n.get_state() == SCons.Node.failed:
+ print(n)
+ n.clear()
+ n.set_state(SCons.Node.no_state)
+ n.implicit = None
+ else:
+ # Clean up so that we can perform the next build correctly.
+ #
+ # We do this by walking over all the children of the targets,
+ # and clearing their state.
+ #
+ # We currently have to re-scan each node to find their
+ # children, because built nodes have already been partially
+ # cleared and don't remember their children. (In scons
+ # 0.96.1 and earlier, this wasn't the case, and we didn't
+ # have to re-scan the nodes.)
+ #
+ # Because we have to re-scan each node, we can't clear the
+ # nodes as we walk over them, because we may end up rescanning
+ # a cleared node as we scan a later node. Therefore, only
+ # store the list of nodes that need to be cleared as we walk
+ # the tree, and clear them in a separate pass.
+ #
+ # XXX: Someone more familiar with the inner workings of scons
+ # may be able to point out a more efficient way to do this.
+
+ SCons.Script.Main.progress_display("scons: Clearing cached node information ...")
+
+ seen_nodes = {}
+
+ def get_unseen_children(node, parent, seen_nodes=seen_nodes):
+ def is_unseen(node, seen_nodes=seen_nodes):
+ return node not in seen_nodes
+ return [child for child in node.children(scan=1) if is_unseen(child)]
+
+ def add_to_seen_nodes(node, parent, seen_nodes=seen_nodes):
+ seen_nodes[node] = 1
+
+ # If this file is in a VariantDir and has a
+ # corresponding source file in the source tree, remember the
+ # node in the source tree, too. This is needed in
+ # particular to clear cached implicit dependencies on the
+ # source file, since the scanner will scan it if the
+ # VariantDir was created with duplicate=0.
+ try:
+ rfile_method = node.rfile
+ except AttributeError:
+ return
+ else:
+ rfile = rfile_method()
+ if rfile != node:
+ seen_nodes[rfile] = 1
+
+ for node in nodes:
+ walker = SCons.Node.Walker(node,
+ kids_func=get_unseen_children,
+ eval_func=add_to_seen_nodes)
n = walker.get_next()
-
- for node in seen_nodes.keys():
- # Call node.clear() to clear most of the state
- node.clear()
- # node.clear() doesn't reset node.state, so call
- # node.set_state() to reset it manually
- node.set_state(SCons.Node.no_state)
- node.implicit = None
-
- # Debug: Uncomment to verify that all Taskmaster reference
- # counts have been reset to zero.
- #if node.ref_count != 0:
- # from SCons.Debug import Trace
- # Trace('node %s, ref_count %s !!!\n' % (node, node.ref_count))
-
- SCons.SConsign.Reset()
- SCons.Script.Main.progress_display("scons: done clearing node information.")
+ while n:
+ n = walker.get_next()
+
+ for node in seen_nodes.keys():
+ # Call node.clear() to clear most of the state
+ node.clear()
+ # node.clear() doesn't reset node.state, so call
+ # node.set_state() to reset it manually
+ node.set_state(SCons.Node.no_state)
+ node.implicit = None
+
+ # Debug: Uncomment to verify that all Taskmaster reference
+ # counts have been reset to zero.
+ #if node.ref_count != 0:
+ # from SCons.Debug import Trace
+ # Trace('node %s, ref_count %s !!!\n' % (node, node.ref_count))
+
+ SCons.SConsign.Reset()
+ SCons.Script.Main.progress_display("scons: done clearing node information.")
def do_clean(self, argv):
"""\
diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py
index a340f5b..87d57bc 100644
--- a/SCons/Script/Main.py
+++ b/SCons/Script/Main.py
@@ -987,7 +987,8 @@ def _main(parser):
# This would then cause subtle bugs, as already happened in #2971.
if options.interactive:
SCons.Node.interactive = True
-
+ if options.ninja_scons_daemon:
+ SCons.Node.ninja_scons_daemon = 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.
@@ -1125,7 +1126,7 @@ def _main(parser):
platform = SCons.Platform.platform_module()
- if options.interactive:
+ if options.interactive or options.ninja_scons_daemon:
SCons.Script.Interactive.interact(fs, OptionsParser, options,
targets, target_top)
diff --git a/SCons/Script/SConsOptions.py b/SCons/Script/SConsOptions.py
index e2631fb..133d9ab 100644
--- a/SCons/Script/SConsOptions.py
+++ b/SCons/Script/SConsOptions.py
@@ -858,6 +858,11 @@ def Parser(version):
action="store_true",
help="Run in interactive mode")
+ op.add_option('--ninja-scons-daemon',
+ dest='ninja_scons_daemon', default=False,
+ action="store_true",
+ help="A special interactive mode to support a scons daemon for ninja builds. Intended for use only by the ninja tool.")
+
op.add_option('-j', '--jobs',
nargs=1, type="int",
dest="num_jobs", default=1,