diff options
author | Daniel Moody <dmoody256@gmail.com> | 2022-02-11 20:13:05 (GMT) |
---|---|---|
committer | Daniel Moody <dmoody256@gmail.com> | 2022-02-11 20:13:05 (GMT) |
commit | d8932c2b87cfef617b2412afc6db024ba6e9560a (patch) | |
tree | c96bd3214e10d75050be5a9ffe6ef942f32f4729 | |
parent | 3b8798ff671969a7211ccd7a5b579d6d84f22d6d (diff) | |
download | SCons-d8932c2b87cfef617b2412afc6db024ba6e9560a.zip SCons-d8932c2b87cfef617b2412afc6db024ba6e9560a.tar.gz SCons-d8932c2b87cfef617b2412afc6db024ba6e9560a.tar.bz2 |
fix up interactive to support ninja scons daemon
-rw-r--r-- | SCons/Node/__init__.py | 1 | ||||
-rw-r--r-- | SCons/Script/Interactive.py | 149 | ||||
-rw-r--r-- | SCons/Script/Main.py | 5 | ||||
-rw-r--r-- | SCons/Script/SConsOptions.py | 5 |
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, |