waf, waflib: import unpacked waf 1.7.13
[pd-aubio.git] / waflib / Build.py
diff --git a/waflib/Build.py b/waflib/Build.py
new file mode 100644 (file)
index 0000000..f76933a
--- /dev/null
@@ -0,0 +1,758 @@
+#! /usr/bin/env python
+# encoding: utf-8
+# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file
+
+import os,sys,errno,re,shutil
+try:
+       import cPickle
+except ImportError:
+       import pickle as cPickle
+from waflib import Runner,TaskGen,Utils,ConfigSet,Task,Logs,Options,Context,Errors
+import waflib.Node
+CACHE_DIR='c4che'
+CACHE_SUFFIX='_cache.py'
+INSTALL=1337
+UNINSTALL=-1337
+SAVED_ATTRS='root node_deps raw_deps task_sigs'.split()
+CFG_FILES='cfg_files'
+POST_AT_ONCE=0
+POST_LAZY=1
+POST_BOTH=2
+class BuildContext(Context.Context):
+       '''executes the build'''
+       cmd='build'
+       variant=''
+       def __init__(self,**kw):
+               super(BuildContext,self).__init__(**kw)
+               self.is_install=0
+               self.top_dir=kw.get('top_dir',Context.top_dir)
+               self.run_dir=kw.get('run_dir',Context.run_dir)
+               self.post_mode=POST_AT_ONCE
+               self.out_dir=kw.get('out_dir',Context.out_dir)
+               self.cache_dir=kw.get('cache_dir',None)
+               if not self.cache_dir:
+                       self.cache_dir=self.out_dir+os.sep+CACHE_DIR
+               self.all_envs={}
+               self.task_sigs={}
+               self.node_deps={}
+               self.raw_deps={}
+               self.cache_dir_contents={}
+               self.task_gen_cache_names={}
+               self.launch_dir=Context.launch_dir
+               self.jobs=Options.options.jobs
+               self.targets=Options.options.targets
+               self.keep=Options.options.keep
+               self.cache_global=Options.cache_global
+               self.nocache=Options.options.nocache
+               self.progress_bar=Options.options.progress_bar
+               self.deps_man=Utils.defaultdict(list)
+               self.current_group=0
+               self.groups=[]
+               self.group_names={}
+       def get_variant_dir(self):
+               if not self.variant:
+                       return self.out_dir
+               return os.path.join(self.out_dir,self.variant)
+       variant_dir=property(get_variant_dir,None)
+       def __call__(self,*k,**kw):
+               kw['bld']=self
+               ret=TaskGen.task_gen(*k,**kw)
+               self.task_gen_cache_names={}
+               self.add_to_group(ret,group=kw.get('group',None))
+               return ret
+       def rule(self,*k,**kw):
+               def f(rule):
+                       ret=self(*k,**kw)
+                       ret.rule=rule
+                       return ret
+               return f
+       def __copy__(self):
+               raise Errors.WafError('build contexts are not supposed to be copied')
+       def install_files(self,*k,**kw):
+               pass
+       def install_as(self,*k,**kw):
+               pass
+       def symlink_as(self,*k,**kw):
+               pass
+       def load_envs(self):
+               node=self.root.find_node(self.cache_dir)
+               if not node:
+                       raise Errors.WafError('The project was not configured: run "waf configure" first!')
+               lst=node.ant_glob('**/*%s'%CACHE_SUFFIX,quiet=True)
+               if not lst:
+                       raise Errors.WafError('The cache directory is empty: reconfigure the project')
+               for x in lst:
+                       name=x.path_from(node).replace(CACHE_SUFFIX,'').replace('\\','/')
+                       env=ConfigSet.ConfigSet(x.abspath())
+                       self.all_envs[name]=env
+                       for f in env[CFG_FILES]:
+                               newnode=self.root.find_resource(f)
+                               try:
+                                       h=Utils.h_file(newnode.abspath())
+                               except(IOError,AttributeError):
+                                       Logs.error('cannot find %r'%f)
+                                       h=Utils.SIG_NIL
+                               newnode.sig=h
+       def init_dirs(self):
+               if not(os.path.isabs(self.top_dir)and os.path.isabs(self.out_dir)):
+                       raise Errors.WafError('The project was not configured: run "waf configure" first!')
+               self.path=self.srcnode=self.root.find_dir(self.top_dir)
+               self.bldnode=self.root.make_node(self.variant_dir)
+               self.bldnode.mkdir()
+       def execute(self):
+               self.restore()
+               if not self.all_envs:
+                       self.load_envs()
+               self.execute_build()
+       def execute_build(self):
+               Logs.info("Waf: Entering directory `%s'"%self.variant_dir)
+               self.recurse([self.run_dir])
+               self.pre_build()
+               self.timer=Utils.Timer()
+               if self.progress_bar:
+                       sys.stderr.write(Logs.colors.cursor_off)
+               try:
+                       self.compile()
+               finally:
+                       if self.progress_bar==1:
+                               c=len(self.returned_tasks)or 1
+                               self.to_log(self.progress_line(c,c,Logs.colors.BLUE,Logs.colors.NORMAL))
+                               print('')
+                               sys.stdout.flush()
+                               sys.stderr.write(Logs.colors.cursor_on)
+                       Logs.info("Waf: Leaving directory `%s'"%self.variant_dir)
+               self.post_build()
+       def restore(self):
+               try:
+                       env=ConfigSet.ConfigSet(os.path.join(self.cache_dir,'build.config.py'))
+               except(IOError,OSError):
+                       pass
+               else:
+                       if env['version']<Context.HEXVERSION:
+                               raise Errors.WafError('Version mismatch! reconfigure the project')
+                       for t in env['tools']:
+                               self.setup(**t)
+               dbfn=os.path.join(self.variant_dir,Context.DBFILE)
+               try:
+                       data=Utils.readf(dbfn,'rb')
+               except(IOError,EOFError):
+                       Logs.debug('build: Could not load the build cache %s (missing)'%dbfn)
+               else:
+                       try:
+                               waflib.Node.pickle_lock.acquire()
+                               waflib.Node.Nod3=self.node_class
+                               try:
+                                       data=cPickle.loads(data)
+                               except Exception ,e:
+                                       Logs.debug('build: Could not pickle the build cache %s: %r'%(dbfn,e))
+                               else:
+                                       for x in SAVED_ATTRS:
+                                               setattr(self,x,data[x])
+                       finally:
+                               waflib.Node.pickle_lock.release()
+               self.init_dirs()
+       def store(self):
+               data={}
+               for x in SAVED_ATTRS:
+                       data[x]=getattr(self,x)
+               db=os.path.join(self.variant_dir,Context.DBFILE)
+               try:
+                       waflib.Node.pickle_lock.acquire()
+                       waflib.Node.Nod3=self.node_class
+                       x=cPickle.dumps(data,-1)
+               finally:
+                       waflib.Node.pickle_lock.release()
+               Utils.writef(db+'.tmp',x,m='wb')
+               try:
+                       st=os.stat(db)
+                       os.remove(db)
+                       if not Utils.is_win32:
+                               os.chown(db+'.tmp',st.st_uid,st.st_gid)
+               except(AttributeError,OSError):
+                       pass
+               os.rename(db+'.tmp',db)
+       def compile(self):
+               Logs.debug('build: compile()')
+               self.producer=Runner.Parallel(self,self.jobs)
+               self.producer.biter=self.get_build_iterator()
+               self.returned_tasks=[]
+               try:
+                       self.producer.start()
+               except KeyboardInterrupt:
+                       self.store()
+                       raise
+               else:
+                       if self.producer.dirty:
+                               self.store()
+               if self.producer.error:
+                       raise Errors.BuildError(self.producer.error)
+       def setup(self,tool,tooldir=None,funs=None):
+               if isinstance(tool,list):
+                       for i in tool:self.setup(i,tooldir)
+                       return
+               module=Context.load_tool(tool,tooldir)
+               if hasattr(module,"setup"):module.setup(self)
+       def get_env(self):
+               try:
+                       return self.all_envs[self.variant]
+               except KeyError:
+                       return self.all_envs['']
+       def set_env(self,val):
+               self.all_envs[self.variant]=val
+       env=property(get_env,set_env)
+       def add_manual_dependency(self,path,value):
+               if path is None:
+                       raise ValueError('Invalid input')
+               if isinstance(path,waflib.Node.Node):
+                       node=path
+               elif os.path.isabs(path):
+                       node=self.root.find_resource(path)
+               else:
+                       node=self.path.find_resource(path)
+               if isinstance(value,list):
+                       self.deps_man[id(node)].extend(value)
+               else:
+                       self.deps_man[id(node)].append(value)
+       def launch_node(self):
+               try:
+                       return self.p_ln
+               except AttributeError:
+                       self.p_ln=self.root.find_dir(self.launch_dir)
+                       return self.p_ln
+       def hash_env_vars(self,env,vars_lst):
+               if not env.table:
+                       env=env.parent
+                       if not env:
+                               return Utils.SIG_NIL
+               idx=str(id(env))+str(vars_lst)
+               try:
+                       cache=self.cache_env
+               except AttributeError:
+                       cache=self.cache_env={}
+               else:
+                       try:
+                               return self.cache_env[idx]
+                       except KeyError:
+                               pass
+               lst=[env[a]for a in vars_lst]
+               ret=Utils.h_list(lst)
+               Logs.debug('envhash: %s %r',Utils.to_hex(ret),lst)
+               cache[idx]=ret
+               return ret
+       def get_tgen_by_name(self,name):
+               cache=self.task_gen_cache_names
+               if not cache:
+                       for g in self.groups:
+                               for tg in g:
+                                       try:
+                                               cache[tg.name]=tg
+                                       except AttributeError:
+                                               pass
+               try:
+                       return cache[name]
+               except KeyError:
+                       raise Errors.WafError('Could not find a task generator for the name %r'%name)
+       def progress_line(self,state,total,col1,col2):
+               n=len(str(total))
+               Utils.rot_idx+=1
+               ind=Utils.rot_chr[Utils.rot_idx%4]
+               pc=(100.*state)/total
+               eta=str(self.timer)
+               fs="[%%%dd/%%%dd][%%s%%2d%%%%%%s][%s]["%(n,n,ind)
+               left=fs%(state,total,col1,pc,col2)
+               right='][%s%s%s]'%(col1,eta,col2)
+               cols=Logs.get_term_cols()-len(left)-len(right)+2*len(col1)+2*len(col2)
+               if cols<7:cols=7
+               ratio=((cols*state)//total)-1
+               bar=('='*ratio+'>').ljust(cols)
+               msg=Utils.indicator%(left,bar,right)
+               return msg
+       def declare_chain(self,*k,**kw):
+               return TaskGen.declare_chain(*k,**kw)
+       def pre_build(self):
+               for m in getattr(self,'pre_funs',[]):
+                       m(self)
+       def post_build(self):
+               for m in getattr(self,'post_funs',[]):
+                       m(self)
+       def add_pre_fun(self,meth):
+               try:
+                       self.pre_funs.append(meth)
+               except AttributeError:
+                       self.pre_funs=[meth]
+       def add_post_fun(self,meth):
+               try:
+                       self.post_funs.append(meth)
+               except AttributeError:
+                       self.post_funs=[meth]
+       def get_group(self,x):
+               if not self.groups:
+                       self.add_group()
+               if x is None:
+                       return self.groups[self.current_group]
+               if x in self.group_names:
+                       return self.group_names[x]
+               return self.groups[x]
+       def add_to_group(self,tgen,group=None):
+               assert(isinstance(tgen,TaskGen.task_gen)or isinstance(tgen,Task.TaskBase))
+               tgen.bld=self
+               self.get_group(group).append(tgen)
+       def get_group_name(self,g):
+               if not isinstance(g,list):
+                       g=self.groups[g]
+               for x in self.group_names:
+                       if id(self.group_names[x])==id(g):
+                               return x
+               return''
+       def get_group_idx(self,tg):
+               se=id(tg)
+               for i in range(len(self.groups)):
+                       for t in self.groups[i]:
+                               if id(t)==se:
+                                       return i
+               return None
+       def add_group(self,name=None,move=True):
+               if name and name in self.group_names:
+                       Logs.error('add_group: name %s already present'%name)
+               g=[]
+               self.group_names[name]=g
+               self.groups.append(g)
+               if move:
+                       self.current_group=len(self.groups)-1
+       def set_group(self,idx):
+               if isinstance(idx,str):
+                       g=self.group_names[idx]
+                       for i in range(len(self.groups)):
+                               if id(g)==id(self.groups[i]):
+                                       self.current_group=i
+               else:
+                       self.current_group=idx
+       def total(self):
+               total=0
+               for group in self.groups:
+                       for tg in group:
+                               try:
+                                       total+=len(tg.tasks)
+                               except AttributeError:
+                                       total+=1
+               return total
+       def get_targets(self):
+               to_post=[]
+               min_grp=0
+               for name in self.targets.split(','):
+                       tg=self.get_tgen_by_name(name)
+                       if not tg:
+                               raise Errors.WafError('target %r does not exist'%name)
+                       m=self.get_group_idx(tg)
+                       if m>min_grp:
+                               min_grp=m
+                               to_post=[tg]
+                       elif m==min_grp:
+                               to_post.append(tg)
+               return(min_grp,to_post)
+       def get_all_task_gen(self):
+               lst=[]
+               for g in self.groups:
+                       lst.extend(g)
+               return lst
+       def post_group(self):
+               if self.targets=='*':
+                       for tg in self.groups[self.cur]:
+                               try:
+                                       f=tg.post
+                               except AttributeError:
+                                       pass
+                               else:
+                                       f()
+               elif self.targets:
+                       if self.cur<self._min_grp:
+                               for tg in self.groups[self.cur]:
+                                       try:
+                                               f=tg.post
+                                       except AttributeError:
+                                               pass
+                                       else:
+                                               f()
+                       else:
+                               for tg in self._exact_tg:
+                                       tg.post()
+               else:
+                       ln=self.launch_node()
+                       if ln.is_child_of(self.bldnode):
+                               Logs.warn('Building from the build directory, forcing --targets=*')
+                               ln=self.srcnode
+                       elif not ln.is_child_of(self.srcnode):
+                               Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)'%(ln.abspath(),self.srcnode.abspath()))
+                               ln=self.srcnode
+                       for tg in self.groups[self.cur]:
+                               try:
+                                       f=tg.post
+                               except AttributeError:
+                                       pass
+                               else:
+                                       if tg.path.is_child_of(ln):
+                                               f()
+       def get_tasks_group(self,idx):
+               tasks=[]
+               for tg in self.groups[idx]:
+                       try:
+                               tasks.extend(tg.tasks)
+                       except AttributeError:
+                               tasks.append(tg)
+               return tasks
+       def get_build_iterator(self):
+               self.cur=0
+               if self.targets and self.targets!='*':
+                       (self._min_grp,self._exact_tg)=self.get_targets()
+               global lazy_post
+               if self.post_mode!=POST_LAZY:
+                       while self.cur<len(self.groups):
+                               self.post_group()
+                               self.cur+=1
+                       self.cur=0
+               while self.cur<len(self.groups):
+                       if self.post_mode!=POST_AT_ONCE:
+                               self.post_group()
+                       tasks=self.get_tasks_group(self.cur)
+                       Task.set_file_constraints(tasks)
+                       Task.set_precedence_constraints(tasks)
+                       self.cur_tasks=tasks
+                       self.cur+=1
+                       if not tasks:
+                               continue
+                       yield tasks
+               while 1:
+                       yield[]
+class inst(Task.Task):
+       color='CYAN'
+       def uid(self):
+               lst=[self.dest,self.path]+self.source
+               return Utils.h_list(repr(lst))
+       def post(self):
+               buf=[]
+               for x in self.source:
+                       if isinstance(x,waflib.Node.Node):
+                               y=x
+                       else:
+                               y=self.path.find_resource(x)
+                               if not y:
+                                       if Logs.verbose:
+                                               Logs.warn('Could not find %s immediately (may cause broken builds)'%x)
+                                       idx=self.generator.bld.get_group_idx(self)
+                                       for tg in self.generator.bld.groups[idx]:
+                                               if not isinstance(tg,inst)and id(tg)!=id(self):
+                                                       tg.post()
+                                               y=self.path.find_resource(x)
+                                               if y:
+                                                       break
+                                       else:
+                                               raise Errors.WafError('Could not find %r in %r'%(x,self.path))
+                       buf.append(y)
+               self.inputs=buf
+       def runnable_status(self):
+               ret=super(inst,self).runnable_status()
+               if ret==Task.SKIP_ME:
+                       return Task.RUN_ME
+               return ret
+       def __str__(self):
+               return''
+       def run(self):
+               return self.generator.exec_task()
+       def get_install_path(self,destdir=True):
+               dest=Utils.subst_vars(self.dest,self.env)
+               dest=dest.replace('/',os.sep)
+               if destdir and Options.options.destdir:
+                       dest=os.path.join(Options.options.destdir,os.path.splitdrive(dest)[1].lstrip(os.sep))
+               return dest
+       def exec_install_files(self):
+               destpath=self.get_install_path()
+               if not destpath:
+                       raise Errors.WafError('unknown installation path %r'%self.generator)
+               for x,y in zip(self.source,self.inputs):
+                       if self.relative_trick:
+                               destfile=os.path.join(destpath,y.path_from(self.path))
+                       else:
+                               destfile=os.path.join(destpath,y.name)
+                       self.generator.bld.do_install(y.abspath(),destfile,self.chmod)
+       def exec_install_as(self):
+               destfile=self.get_install_path()
+               self.generator.bld.do_install(self.inputs[0].abspath(),destfile,self.chmod)
+       def exec_symlink_as(self):
+               destfile=self.get_install_path()
+               src=self.link
+               if self.relative_trick:
+                       src=os.path.relpath(src,os.path.dirname(destfile))
+               self.generator.bld.do_link(src,destfile)
+class InstallContext(BuildContext):
+       '''installs the targets on the system'''
+       cmd='install'
+       def __init__(self,**kw):
+               super(InstallContext,self).__init__(**kw)
+               self.uninstall=[]
+               self.is_install=INSTALL
+       def do_install(self,src,tgt,chmod=Utils.O644):
+               d,_=os.path.split(tgt)
+               if not d:
+                       raise Errors.WafError('Invalid installation given %r->%r'%(src,tgt))
+               Utils.check_dir(d)
+               srclbl=src.replace(self.srcnode.abspath()+os.sep,'')
+               if not Options.options.force:
+                       try:
+                               st1=os.stat(tgt)
+                               st2=os.stat(src)
+                       except OSError:
+                               pass
+                       else:
+                               if st1.st_mtime+2>=st2.st_mtime and st1.st_size==st2.st_size:
+                                       if not self.progress_bar:
+                                               Logs.info('- install %s (from %s)'%(tgt,srclbl))
+                                       return False
+               if not self.progress_bar:
+                       Logs.info('+ install %s (from %s)'%(tgt,srclbl))
+               try:
+                       os.remove(tgt)
+               except OSError:
+                       pass
+               try:
+                       shutil.copy2(src,tgt)
+                       os.chmod(tgt,chmod)
+               except IOError:
+                       try:
+                               os.stat(src)
+                       except(OSError,IOError):
+                               Logs.error('File %r does not exist'%src)
+                       raise Errors.WafError('Could not install the file %r'%tgt)
+       def do_link(self,src,tgt):
+               d,_=os.path.split(tgt)
+               Utils.check_dir(d)
+               link=False
+               if not os.path.islink(tgt):
+                       link=True
+               elif os.readlink(tgt)!=src:
+                       link=True
+               if link:
+                       try:os.remove(tgt)
+                       except OSError:pass
+                       if not self.progress_bar:
+                               Logs.info('+ symlink %s (to %s)'%(tgt,src))
+                       os.symlink(src,tgt)
+               else:
+                       if not self.progress_bar:
+                               Logs.info('- symlink %s (to %s)'%(tgt,src))
+       def run_task_now(self,tsk,postpone):
+               tsk.post()
+               if not postpone:
+                       if tsk.runnable_status()==Task.ASK_LATER:
+                               raise self.WafError('cannot post the task %r'%tsk)
+                       tsk.run()
+       def install_files(self,dest,files,env=None,chmod=Utils.O644,relative_trick=False,cwd=None,add=True,postpone=True):
+               tsk=inst(env=env or self.env)
+               tsk.bld=self
+               tsk.path=cwd or self.path
+               tsk.chmod=chmod
+               if isinstance(files,waflib.Node.Node):
+                       tsk.source=[files]
+               else:
+                       tsk.source=Utils.to_list(files)
+               tsk.dest=dest
+               tsk.exec_task=tsk.exec_install_files
+               tsk.relative_trick=relative_trick
+               if add:self.add_to_group(tsk)
+               self.run_task_now(tsk,postpone)
+               return tsk
+       def install_as(self,dest,srcfile,env=None,chmod=Utils.O644,cwd=None,add=True,postpone=True):
+               tsk=inst(env=env or self.env)
+               tsk.bld=self
+               tsk.path=cwd or self.path
+               tsk.chmod=chmod
+               tsk.source=[srcfile]
+               tsk.dest=dest
+               tsk.exec_task=tsk.exec_install_as
+               if add:self.add_to_group(tsk)
+               self.run_task_now(tsk,postpone)
+               return tsk
+       def symlink_as(self,dest,src,env=None,cwd=None,add=True,postpone=True,relative_trick=False):
+               if Utils.is_win32:
+                       return
+               tsk=inst(env=env or self.env)
+               tsk.bld=self
+               tsk.dest=dest
+               tsk.path=cwd or self.path
+               tsk.source=[]
+               tsk.link=src
+               tsk.relative_trick=relative_trick
+               tsk.exec_task=tsk.exec_symlink_as
+               if add:self.add_to_group(tsk)
+               self.run_task_now(tsk,postpone)
+               return tsk
+class UninstallContext(InstallContext):
+       '''removes the targets installed'''
+       cmd='uninstall'
+       def __init__(self,**kw):
+               super(UninstallContext,self).__init__(**kw)
+               self.is_install=UNINSTALL
+       def do_install(self,src,tgt,chmod=Utils.O644):
+               if not self.progress_bar:
+                       Logs.info('- remove %s'%tgt)
+               self.uninstall.append(tgt)
+               try:
+                       os.remove(tgt)
+               except OSError ,e:
+                       if e.errno!=errno.ENOENT:
+                               if not getattr(self,'uninstall_error',None):
+                                       self.uninstall_error=True
+                                       Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)')
+                               if Logs.verbose>1:
+                                       Logs.warn('Could not remove %s (error code %r)'%(e.filename,e.errno))
+               while tgt:
+                       tgt=os.path.dirname(tgt)
+                       try:
+                               os.rmdir(tgt)
+                       except OSError:
+                               break
+       def do_link(self,src,tgt):
+               try:
+                       if not self.progress_bar:
+                               Logs.info('- remove %s'%tgt)
+                       os.remove(tgt)
+               except OSError:
+                       pass
+               while tgt:
+                       tgt=os.path.dirname(tgt)
+                       try:
+                               os.rmdir(tgt)
+                       except OSError:
+                               break
+       def execute(self):
+               try:
+                       def runnable_status(self):
+                               return Task.SKIP_ME
+                       setattr(Task.Task,'runnable_status_back',Task.Task.runnable_status)
+                       setattr(Task.Task,'runnable_status',runnable_status)
+                       super(UninstallContext,self).execute()
+               finally:
+                       setattr(Task.Task,'runnable_status',Task.Task.runnable_status_back)
+class CleanContext(BuildContext):
+       '''cleans the project'''
+       cmd='clean'
+       def execute(self):
+               self.restore()
+               if not self.all_envs:
+                       self.load_envs()
+               self.recurse([self.run_dir])
+               try:
+                       self.clean()
+               finally:
+                       self.store()
+       def clean(self):
+               Logs.debug('build: clean called')
+               if self.bldnode!=self.srcnode:
+                       lst=[]
+                       for e in self.all_envs.values():
+                               lst.extend(self.root.find_or_declare(f)for f in e[CFG_FILES])
+                       for n in self.bldnode.ant_glob('**/*',excl='.lock* *conf_check_*/** config.log c4che/*',quiet=True):
+                               if n in lst:
+                                       continue
+                               n.delete()
+               self.root.children={}
+               for v in'node_deps task_sigs raw_deps'.split():
+                       setattr(self,v,{})
+class ListContext(BuildContext):
+       '''lists the targets to execute'''
+       cmd='list'
+       def execute(self):
+               self.restore()
+               if not self.all_envs:
+                       self.load_envs()
+               self.recurse([self.run_dir])
+               self.pre_build()
+               self.timer=Utils.Timer()
+               for g in self.groups:
+                       for tg in g:
+                               try:
+                                       f=tg.post
+                               except AttributeError:
+                                       pass
+                               else:
+                                       f()
+               try:
+                       self.get_tgen_by_name('')
+               except Exception:
+                       pass
+               lst=list(self.task_gen_cache_names.keys())
+               lst.sort()
+               for k in lst:
+                       Logs.pprint('GREEN',k)
+class StepContext(BuildContext):
+       '''executes tasks in a step-by-step fashion, for debugging'''
+       cmd='step'
+       def __init__(self,**kw):
+               super(StepContext,self).__init__(**kw)
+               self.files=Options.options.files
+       def compile(self):
+               if not self.files:
+                       Logs.warn('Add a pattern for the debug build, for example "waf step --files=main.c,app"')
+                       BuildContext.compile(self)
+                       return
+               targets=None
+               if self.targets and self.targets!='*':
+                       targets=self.targets.split(',')
+               for g in self.groups:
+                       for tg in g:
+                               if targets and tg.name not in targets:
+                                       continue
+                               try:
+                                       f=tg.post
+                               except AttributeError:
+                                       pass
+                               else:
+                                       f()
+                       for pat in self.files.split(','):
+                               matcher=self.get_matcher(pat)
+                               for tg in g:
+                                       if isinstance(tg,Task.TaskBase):
+                                               lst=[tg]
+                                       else:
+                                               lst=tg.tasks
+                                       for tsk in lst:
+                                               do_exec=False
+                                               for node in getattr(tsk,'inputs',[]):
+                                                       if matcher(node,output=False):
+                                                               do_exec=True
+                                                               break
+                                               for node in getattr(tsk,'outputs',[]):
+                                                       if matcher(node,output=True):
+                                                               do_exec=True
+                                                               break
+                                               if do_exec:
+                                                       ret=tsk.run()
+                                                       Logs.info('%s -> exit %r'%(str(tsk),ret))
+       def get_matcher(self,pat):
+               inn=True
+               out=True
+               if pat.startswith('in:'):
+                       out=False
+                       pat=pat.replace('in:','')
+               elif pat.startswith('out:'):
+                       inn=False
+                       pat=pat.replace('out:','')
+               anode=self.root.find_node(pat)
+               pattern=None
+               if not anode:
+                       if not pat.startswith('^'):
+                               pat='^.+?%s'%pat
+                       if not pat.endswith('$'):
+                               pat='%s$'%pat
+                       pattern=re.compile(pat)
+               def match(node,output):
+                       if output==True and not out:
+                               return False
+                       if output==False and not inn:
+                               return False
+                       if anode:
+                               return anode==node
+                       else:
+                               return pattern.match(node.abspath())
+               return match
+BuildContext.store=Utils.nogc(BuildContext.store)
+BuildContext.restore=Utils.nogc(BuildContext.restore)