[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