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)
15 September 2006, update
Starting with SCons 0.96.92, the code doesn't work due to the signature refactoring of SCons.