1# encoding: utf-8 2# Thomas Nagy, 2006-2010 (ita) 3 4""" 5Add a pre-build hook to remove all build files 6which do not have a corresponding target 7 8This can be used for example to remove the targets 9that have changed name without performing 10a full 'waf clean' 11 12Of course, it will only work if there are no dynamically generated 13nodes/tasks, in which case the method will have to be modified 14to exclude some folders for example. 15""" 16 17from waflib import Logs, Build, Options, Utils, Errors 18import os 19from wafsamba import samba_utils 20from Runner import Parallel 21 22old_refill_task_list = Parallel.refill_task_list 23def replace_refill_task_list(self): 24 '''replacement for refill_task_list() that deletes stale files''' 25 26 iit = old_refill_task_list(self) 27 bld = self.bld 28 29 if not getattr(bld, 'new_rules', False): 30 # we only need to check for stale files if the build rules changed 31 return iit 32 33 if Options.options.compile_targets: 34 # not safe when --target is used 35 return iit 36 37 # execute only once 38 if getattr(self, 'cleanup_done', False): 39 return iit 40 self.cleanup_done = True 41 42 def group_name(g): 43 tm = self.bld.task_manager 44 return [x for x in tm.groups_names if id(tm.groups_names[x]) == id(g)][0] 45 46 bin_base = bld.bldnode.abspath() 47 bin_base_len = len(bin_base) 48 49 # paranoia 50 if bin_base[-4:] != '/bin': 51 raise Errors.WafError("Invalid bin base: %s" % bin_base) 52 53 # obtain the expected list of files 54 expected = [] 55 for i in range(len(bld.task_manager.groups)): 56 g = bld.task_manager.groups[i] 57 tasks = g.tasks_gen 58 for x in tasks: 59 try: 60 if getattr(x, 'target'): 61 tlist = samba_utils.TO_LIST(getattr(x, 'target')) 62 ttype = getattr(x, 'samba_type', None) 63 task_list = getattr(x, 'compiled_tasks', []) 64 if task_list: 65 # this gets all of the .o files, including the task 66 # ids, so foo.c maps to foo_3.o for idx=3 67 for tsk in task_list: 68 for output in tsk.outputs: 69 objpath = os.path.normpath(output.abspath(bld.env)) 70 expected.append(objpath) 71 for t in tlist: 72 if ttype in ['LIBRARY','MODULE']: 73 t = samba_utils.apply_pattern(t, bld.env.shlib_PATTERN) 74 if ttype == 'PYTHON': 75 t = samba_utils.apply_pattern(t, bld.env.pyext_PATTERN) 76 p = os.path.join(x.path.abspath(bld.env), t) 77 p = os.path.normpath(p) 78 expected.append(p) 79 for n in x.allnodes: 80 p = n.abspath(bld.env) 81 if p[0:bin_base_len] == bin_base: 82 expected.append(p) 83 except: 84 pass 85 86 for root, dirs, files in os.walk(bin_base): 87 for f in files: 88 p = root + '/' + f 89 if os.path.islink(p): 90 link = os.readlink(p) 91 if link[0:bin_base_len] == bin_base: 92 p = link 93 if f in ['config.h']: 94 continue 95 (froot, fext) = os.path.splitext(f) 96 if fext not in [ '.c', '.h', '.so', '.o' ]: 97 continue 98 if f[-7:] == '.inst.h': 99 continue 100 if p.find("/.conf") != -1: 101 continue 102 if not p in expected and os.path.exists(p): 103 Logs.warn("Removing stale file: %s" % p) 104 os.unlink(p) 105 return iit 106 107 108def AUTOCLEANUP_STALE_FILES(bld): 109 """automatically clean up any files in bin that shouldn't be there""" 110 old_refill_task_list = Parallel.refill_task_list 111 Parallel.refill_task_list = replace_refill_task_list 112 Parallel.bld = bld 113Build.BuildContext.AUTOCLEANUP_STALE_FILES = AUTOCLEANUP_STALE_FILES 114