[Scons-users] Value nodes and --debug=explain

Tom Tanner (BLOOMBERG/ LONDON) ttanner2 at bloomberg.net
Fri Oct 30 08:23:07 EDT 2015


There was a discussion about this earlier. There's a fix sculling around for it somewhere. This patch should apply to Node/__init__.py


@@ -1198,59 +1198,51 @@ class Node(object):
             old_bkids    = old.bsources    + old.bdepends    + old.bimplicit
             old_bkidsigs = old.bsourcesigs + old.bdependsigs + old.bimplicitsigs
         except AttributeError:
             return "Cannot explain why `%s' is being rebuilt: No previous build information found\n" % self
 
         new = self.get_binfo()
 
         new_bkids    = new.bsources    + new.bdepends    + new.bimplicit
         new_bkidsigs = new.bsourcesigs + new.bdependsigs + new.bimplicitsigs
 
+        osig = dict(zip(old_bkids, old_bkidsigs))
+
         # The sources and dependencies we'll want to report are all stored
         # as relative paths to this target's directory, but we want to
         # report them relative to the top-level SConstruct directory,
         # so we only print them after running them through this lambda
         # to turn them into the right relative Node and then return
         # its string.
         def stringify( s, E=self.dir.Entry ) :
             if hasattr( s, 'dir' ) :
                 return str(E(s))
             return str(s)
 
-        # We stringify everything because we seem to get different instances of
-        # each Value object even if they have the same value. As this
-        # stringifies everything on output, I don't think we really care -
-        # though if you happen to have a Value object whose value matches a
-        # filename, the resultant output wil be confusing, whichever way you
-        # deal with it.
-        old_kids = list(map(stringify, old_bkids))
-        new_kids = list(map(stringify, new_bkids))
-        osig = dict(zip(old_kids, old_bkidsigs))
-
         lines = []
 
-        removed = [x for x in old_kids if not x in new_kids]
+        removed = [x for x in old_bkids if not x in new_bkids]
         if removed:
+            removed = list(map(stringify, removed))
             fmt = "`%s' is no longer a dependency\n"
             lines.extend([fmt % s for s in removed])
 
         for k in new_bkids:
-            ks = stringify(k)
-            if not ks in old_kids:
-                lines.append("`%s' is a new dependency\n" % ks)
-            elif k.changed_since_last_build(self, osig[ks]):
-                lines.append("`%s' changed\n" % ks)
+            if not k in old_bkids:
+                lines.append("`%s' is a new dependency\n" % stringify(k))
+            elif k in osig and k.changed_since_last_build(self, osig[k]):
+                lines.append("`%s' changed\n" % stringify(k))
 
-        if len(lines) == 0 and old_kids != new_kids:
+        if len(lines) == 0 and old_bkids != new_bkids:
             lines.append("the dependency order changed:\n" +
-                         "%sold: %s\n" % (' ' * 15, old_kids) +
-                         "%snew: %s\n" % (' ' * 15, new_kids))
+                         "%sold: %s\n" % (' ' * 15, list(map(stringify, old_bkids))) +
+                         "%snew: %s\n" % (' ' * 15, list(map(stringify, new_bkids))))
 
         if old.bactsig != new.bactsig:
             def fmt_with_title(title, strlines):
                 lines = strlines.split('\n')
                 sep = '\n' + ' ' * (15 + len(title))
                 return ' ' * 15 + title + sep.join(lines) + '\n'
 
             if old.bact == new.bact:
                 lines.append("the contents of the build action changed\n" +
                              fmt_with_title('action: ', new.bact))

From: scons-users at scons.org At: Oct 29 2015 20:41:02
To: scons-users at scons.org
Subject: Re:[Scons-users] Value nodes and --debug=explain

I've noticed that, if I use Value nodes as sources, if one changes, then the
explain output claims that ALL the Value node sources are completely
different.  That is, for a Value that did not change, it claims it is both no
longer a dependency, and also a new dependency.  I would think it should
only emit messages about Values that actually changed.

For the following SConstruct:
    env = Environment()

    sources = [
        env.Value('a'),
        env.Value('b'),
    ]
    env.Command('tgt', sources, [
        'touch $TARGET'
    ])

If, after building once, I change the 'b' Value to 'c', then I see:
    $ scons --debug=explain
    scons: Reading SConscript files ...
    scons: done reading SConscript files.
    scons: Building targets ...
    scons: rebuilding `tgt' because:
               `a' is no longer a dependency
               `b' is no longer a dependency
               `a' is a new dependency
               `c' is a new dependency
    touch tgt
    scons: done building targets.


The cause here seems to that, in SCons.Node.explain(), when it checks
whether a given node from the old_bkids is in new_kids, and vice-versa, the
check always fails, because env.Value('a') != env.Value('a'), and because
there's no __hash__ override, the object id is used when doing lookups of
nodes as keys in osig (a dictionary).

So, if I add the following to SCons.Node.Python.Value:
    def __eq__(self, other):
        if isinstance(other, Value):
            return self.value == other.value
        return False

    def __hash__(self):
        return hash(self.value)

Then I get output more inline with what I'd expect:
    $ scons --debug=explain
    scons: Reading SConscript files ...
    scons: done reading SConscript files.
    scons: Building targets ...
    scons: rebuilding `tgt' because:
               `c' is no longer a dependency
               `d' is a new dependency
    touch tgt
    scons: done building targets.

However, I wonder if perhaps I'm missing something obvious that doesn't
require a code change to SCons?

I've tested both 2.3.2 and 2.4; both have the same behavior.

 - Matt
_______________________________________________
Scons-users mailing list
Scons-users at scons.org
https://pairlist4.pair.net/mailman/listinfo/scons-users


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://pairlist4.pair.net/pipermail/scons-users/attachments/20151030/365eb37a/attachment-0001.html>


More information about the Scons-users mailing list