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.
Vibe code with your voice
Stop fighting speech recognition.
Just talk → fix mistakes later
"... _brings_ hello world" ❌
↓
"... _prints_ hello world" ✅