1#! /usr/bin/env python 2# encoding: UTF-8 3# Thomas Nagy, 2006-2015 (ita) 4 5""" 6Add a pre-build hook to remove build files (declared in the system) 7that do not have a corresponding target 8 9This can be used for example to remove the targets 10that have changed name without performing 11a full 'waf clean' 12 13Of course, it will only work if there are no dynamically generated 14nodes/tasks, in which case the method will have to be modified 15to exclude some folders for example. 16 17Make sure to set bld.post_mode = waflib.Build.POST_AT_ONCE 18""" 19 20from waflib import Logs, Build 21from waflib.Runner import Parallel 22 23DYNAMIC_EXT = [] # add your non-cleanable files/extensions here 24MOC_H_EXTS = '.cpp .cxx .hpp .hxx .h'.split() 25 26def can_delete(node): 27 """Imperfect moc cleanup which does not look for a Q_OBJECT macro in the files""" 28 if not node.name.endswith('.moc'): 29 return True 30 base = node.name[:-4] 31 p1 = node.parent.get_src() 32 p2 = node.parent.get_bld() 33 for k in MOC_H_EXTS: 34 h_name = base + k 35 n = p1.search_node(h_name) 36 if n: 37 return False 38 n = p2.search_node(h_name) 39 if n: 40 return False 41 42 # foo.cpp.moc, foo.h.moc, etc. 43 if base.endswith(k): 44 return False 45 46 return True 47 48# recursion over the nodes to find the stale files 49def stale_rec(node, nodes): 50 if node.abspath() in node.ctx.env[Build.CFG_FILES]: 51 return 52 53 if getattr(node, 'children', []): 54 for x in node.children.values(): 55 if x.name != "c4che": 56 stale_rec(x, nodes) 57 else: 58 for ext in DYNAMIC_EXT: 59 if node.name.endswith(ext): 60 break 61 else: 62 if not node in nodes: 63 if can_delete(node): 64 Logs.warn('Removing stale file -> %r', node) 65 node.delete() 66 67old = Parallel.refill_task_list 68def refill_task_list(self): 69 iit = old(self) 70 bld = self.bld 71 72 # execute this operation only once 73 if getattr(self, 'stale_done', False): 74 return iit 75 self.stale_done = True 76 77 # this does not work in partial builds 78 if bld.targets != '*': 79 return iit 80 81 # this does not work in dynamic builds 82 if getattr(bld, 'post_mode') == Build.POST_AT_ONCE: 83 return iit 84 85 # obtain the nodes to use during the build 86 nodes = [] 87 for tasks in bld.groups: 88 for x in tasks: 89 try: 90 nodes.extend(x.outputs) 91 except AttributeError: 92 pass 93 94 stale_rec(bld.bldnode, nodes) 95 return iit 96 97Parallel.refill_task_list = refill_task_list 98 99