fixing build signatures
I have a lot of functional tests for my build process. Recently I changed the program name on one of the intermediate steps. As result, SCons
* thinks the build signatures are updated, and
* wants to rebuild starting from that step instead of doing the expected rebuilds.
Therefore, I have to update the most part of the tests. But it's near to impossible to update manually.
I decided to update build signatures automatically.
To get the list of all the defined targets, I use the variable "env.ans" where env is an Environment object.
Then, for each the target, I traverse the tree of dependencies.
While traversing, the following nodes are ignored:
* those which have no build information (either source files, either defined, but not used),
* the default target (because executing the last step to get the default target is the essence of many tests).
To make a node up-to-date:
* code reads the data from .sconsign using get_stored_info(),
* new build signatures are calculated using calc_bsig(),
* .sconsign build information (bsig, bact and bactsig) is updated using set_entry().
The full code:
#
# Walk over the dependencies tree
#
def walk_dep_tree(node, func, tabs=''):
for ch in node.children():
walk_dep_tree(ch, func, tabs + ' ')
#
# Apply the function, ignoring:
# the nodes which were not built,
# default targets
#
if not node.is_derived():
return
old = node.get_stored_info()
if None == old:
return
if None == getattr(old, 'bactsig', None):
return
if str(node) in map(str, DEFAULT_TARGETS):
return
func(node, tabs)
def fix_build_signatures(target, source, env):
def print_node(node, tabs):
print tabs + str(node)
def update_bsig(node, tabs):
#print tabs + str(node)
#
# Check if the build information is changed
#
old = node.get_stored_info()
node.calc_bsig()
new = node.binfo
is_changed = (old.bactsig != new.bactsig) or (old.bact != new.bact) or (old.bsig != new.bsig)
if not is_changed:
return
#
# Update the build information
#
print 'Updating the build signature for ' + str(node)
old.bactsig = node.binfo.bactsig
old.bact = node.binfo.bact
old.bsig = node.binfo.bsig
node.dir.sconsign().set_entry(node.name, old)
#
# Update the signatures of all the targets
#
#for k in env.ans.keys():
# walk_dep_tree(env.ans[k], print_node)
for k in env.ans.keys():
walk_dep_tree(env.ans[k], update_bsig)
node = Local('fix-build-signatures')
env['BUILDERS']['fixbs'] = Builder(action = fix_build_signatures)
env.fixbs(node, None)
env.Alias('fixbs', node)
Usage:
scons fixbs
15 September 2006, update
Starting with SCons 0.96.92, the code doesn't work due to the signature refactoring of SCons.