summaryrefslogtreecommitdiff
path: root/waflib/TaskGen.py
diff options
context:
space:
mode:
Diffstat (limited to 'waflib/TaskGen.py')
-rw-r--r--waflib/TaskGen.py434
1 files changed, 434 insertions, 0 deletions
diff --git a/waflib/TaskGen.py b/waflib/TaskGen.py
new file mode 100644
index 0000000..046f1f9
--- /dev/null
+++ b/waflib/TaskGen.py
@@ -0,0 +1,434 @@
+#! /usr/bin/env python
+# encoding: utf-8
+# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file
+
+import copy,re,os
+from waflib import Task,Utils,Logs,Errors,ConfigSet,Node
+feats=Utils.defaultdict(set)
+HEADER_EXTS=['.h','.hpp','.hxx','.hh']
+class task_gen(object):
+ mappings=Utils.ordered_iter_dict()
+ prec=Utils.defaultdict(list)
+ def __init__(self,*k,**kw):
+ self.source=''
+ self.target=''
+ self.meths=[]
+ self.prec=Utils.defaultdict(list)
+ self.mappings={}
+ self.features=[]
+ self.tasks=[]
+ if not'bld'in kw:
+ self.env=ConfigSet.ConfigSet()
+ self.idx=0
+ self.path=None
+ else:
+ self.bld=kw['bld']
+ self.env=self.bld.env.derive()
+ self.path=self.bld.path
+ try:
+ self.idx=self.bld.idx[id(self.path)]=self.bld.idx.get(id(self.path),0)+1
+ except AttributeError:
+ self.bld.idx={}
+ self.idx=self.bld.idx[id(self.path)]=1
+ for key,val in kw.items():
+ setattr(self,key,val)
+ def __str__(self):
+ return"<task_gen %r declared in %s>"%(self.name,self.path.abspath())
+ def __repr__(self):
+ lst=[]
+ for x in self.__dict__.keys():
+ if x not in('env','bld','compiled_tasks','tasks'):
+ lst.append("%s=%s"%(x,repr(getattr(self,x))))
+ return"bld(%s) in %s"%(", ".join(lst),self.path.abspath())
+ def get_name(self):
+ try:
+ return self._name
+ except AttributeError:
+ if isinstance(self.target,list):
+ lst=[str(x)for x in self.target]
+ name=self._name=','.join(lst)
+ else:
+ name=self._name=str(self.target)
+ return name
+ def set_name(self,name):
+ self._name=name
+ name=property(get_name,set_name)
+ def to_list(self,val):
+ if isinstance(val,str):return val.split()
+ else:return val
+ def post(self):
+ if getattr(self,'posted',None):
+ return False
+ self.posted=True
+ keys=set(self.meths)
+ self.features=Utils.to_list(self.features)
+ for x in self.features+['*']:
+ st=feats[x]
+ if not st:
+ if not x in Task.classes:
+ Logs.warn('feature %r does not exist - bind at least one method to it'%x)
+ keys.update(list(st))
+ prec={}
+ prec_tbl=self.prec or task_gen.prec
+ for x in prec_tbl:
+ if x in keys:
+ prec[x]=prec_tbl[x]
+ tmp=[]
+ for a in keys:
+ for x in prec.values():
+ if a in x:break
+ else:
+ tmp.append(a)
+ tmp.sort()
+ out=[]
+ while tmp:
+ e=tmp.pop()
+ if e in keys:out.append(e)
+ try:
+ nlst=prec[e]
+ except KeyError:
+ pass
+ else:
+ del prec[e]
+ for x in nlst:
+ for y in prec:
+ if x in prec[y]:
+ break
+ else:
+ tmp.append(x)
+ if prec:
+ txt='\n'.join(['- %s after %s'%(k,repr(v))for k,v in prec.items()])
+ raise Errors.WafError('Cycle detected in the method execution\n%s'%txt)
+ out.reverse()
+ self.meths=out
+ Logs.debug('task_gen: posting %s %d'%(self,id(self)))
+ for x in out:
+ try:
+ v=getattr(self,x)
+ except AttributeError:
+ raise Errors.WafError('%r is not a valid task generator method'%x)
+ Logs.debug('task_gen: -> %s (%d)'%(x,id(self)))
+ v()
+ Logs.debug('task_gen: posted %s'%self.name)
+ return True
+ def get_hook(self,node):
+ name=node.name
+ if self.mappings:
+ for k in self.mappings:
+ if name.endswith(k):
+ return self.mappings[k]
+ for k in task_gen.mappings:
+ if name.endswith(k):
+ return task_gen.mappings[k]
+ raise Errors.WafError("File %r has no mapping in %r (have you forgotten to load a waf tool?)"%(node,task_gen.mappings.keys()))
+ def create_task(self,name,src=None,tgt=None,**kw):
+ task=Task.classes[name](env=self.env.derive(),generator=self)
+ if src:
+ task.set_inputs(src)
+ if tgt:
+ task.set_outputs(tgt)
+ task.__dict__.update(kw)
+ self.tasks.append(task)
+ return task
+ def clone(self,env):
+ newobj=self.bld()
+ for x in self.__dict__:
+ if x in('env','bld'):
+ continue
+ elif x in('path','features'):
+ setattr(newobj,x,getattr(self,x))
+ else:
+ setattr(newobj,x,copy.copy(getattr(self,x)))
+ newobj.posted=False
+ if isinstance(env,str):
+ newobj.env=self.bld.all_envs[env].derive()
+ else:
+ newobj.env=env.derive()
+ return newobj
+def declare_chain(name='',rule=None,reentrant=None,color='BLUE',ext_in=[],ext_out=[],before=[],after=[],decider=None,scan=None,install_path=None,shell=False):
+ ext_in=Utils.to_list(ext_in)
+ ext_out=Utils.to_list(ext_out)
+ if not name:
+ name=rule
+ cls=Task.task_factory(name,rule,color=color,ext_in=ext_in,ext_out=ext_out,before=before,after=after,scan=scan,shell=shell)
+ def x_file(self,node):
+ ext=decider and decider(self,node)or cls.ext_out
+ if ext_in:
+ _ext_in=ext_in[0]
+ tsk=self.create_task(name,node)
+ cnt=0
+ keys=set(self.mappings.keys())|set(self.__class__.mappings.keys())
+ for x in ext:
+ k=node.change_ext(x,ext_in=_ext_in)
+ tsk.outputs.append(k)
+ if reentrant!=None:
+ if cnt<int(reentrant):
+ self.source.append(k)
+ else:
+ for y in keys:
+ if k.name.endswith(y):
+ self.source.append(k)
+ break
+ cnt+=1
+ if install_path:
+ self.bld.install_files(install_path,tsk.outputs)
+ return tsk
+ for x in cls.ext_in:
+ task_gen.mappings[x]=x_file
+ return x_file
+def taskgen_method(func):
+ setattr(task_gen,func.__name__,func)
+ return func
+def feature(*k):
+ def deco(func):
+ setattr(task_gen,func.__name__,func)
+ for name in k:
+ feats[name].update([func.__name__])
+ return func
+ return deco
+def before_method(*k):
+ def deco(func):
+ setattr(task_gen,func.__name__,func)
+ for fun_name in k:
+ if not func.__name__ in task_gen.prec[fun_name]:
+ task_gen.prec[fun_name].append(func.__name__)
+ return func
+ return deco
+before=before_method
+def after_method(*k):
+ def deco(func):
+ setattr(task_gen,func.__name__,func)
+ for fun_name in k:
+ if not fun_name in task_gen.prec[func.__name__]:
+ task_gen.prec[func.__name__].append(fun_name)
+ return func
+ return deco
+after=after_method
+def extension(*k):
+ def deco(func):
+ setattr(task_gen,func.__name__,func)
+ for x in k:
+ task_gen.mappings[x]=func
+ return func
+ return deco
+@taskgen_method
+def to_nodes(self,lst,path=None):
+ tmp=[]
+ path=path or self.path
+ find=path.find_resource
+ if isinstance(lst,Node.Node):
+ lst=[lst]
+ for x in Utils.to_list(lst):
+ if isinstance(x,str):
+ node=find(x)
+ else:
+ node=x
+ if not node:
+ raise Errors.WafError("source not found: %r in %r"%(x,self))
+ tmp.append(node)
+ return tmp
+@feature('*')
+def process_source(self):
+ self.source=self.to_nodes(getattr(self,'source',[]))
+ for node in self.source:
+ self.get_hook(node)(self,node)
+@feature('*')
+@before_method('process_source')
+def process_rule(self):
+ if not getattr(self,'rule',None):
+ return
+ name=str(getattr(self,'name',None)or self.target or getattr(self.rule,'__name__',self.rule))
+ try:
+ cache=self.bld.cache_rule_attr
+ except AttributeError:
+ cache=self.bld.cache_rule_attr={}
+ cls=None
+ if getattr(self,'cache_rule','True'):
+ try:
+ cls=cache[(name,self.rule)]
+ except KeyError:
+ pass
+ if not cls:
+ rule=self.rule
+ if hasattr(self,'chmod'):
+ def chmod_fun(tsk):
+ for x in tsk.outputs:
+ os.chmod(x.abspath(),self.chmod)
+ rule=(self.rule,chmod_fun)
+ cls=Task.task_factory(name,rule,getattr(self,'vars',[]),shell=getattr(self,'shell',True),color=getattr(self,'color','BLUE'),scan=getattr(self,'scan',None))
+ if getattr(self,'scan',None):
+ cls.scan=self.scan
+ elif getattr(self,'deps',None):
+ def scan(self):
+ nodes=[]
+ for x in self.generator.to_list(getattr(self.generator,'deps',None)):
+ node=self.generator.path.find_resource(x)
+ if not node:
+ self.generator.bld.fatal('Could not find %r (was it declared?)'%x)
+ nodes.append(node)
+ return[nodes,[]]
+ cls.scan=scan
+ if getattr(self,'update_outputs',None):
+ Task.update_outputs(cls)
+ if getattr(self,'always',None):
+ Task.always_run(cls)
+ for x in('after','before','ext_in','ext_out'):
+ setattr(cls,x,getattr(self,x,[]))
+ if getattr(self,'cache_rule','True'):
+ cache[(name,self.rule)]=cls
+ if getattr(self,'cls_str',None):
+ setattr(cls,'__str__',self.cls_str)
+ if getattr(self,'cls_keyword',None):
+ setattr(cls,'keyword',self.cls_keyword)
+ tsk=self.create_task(name)
+ if getattr(self,'target',None):
+ if isinstance(self.target,str):
+ self.target=self.target.split()
+ if not isinstance(self.target,list):
+ self.target=[self.target]
+ for x in self.target:
+ if isinstance(x,str):
+ tsk.outputs.append(self.path.find_or_declare(x))
+ else:
+ x.parent.mkdir()
+ tsk.outputs.append(x)
+ if getattr(self,'install_path',None):
+ self.bld.install_files(self.install_path,tsk.outputs,chmod=getattr(self,'chmod',Utils.O644))
+ if getattr(self,'source',None):
+ tsk.inputs=self.to_nodes(self.source)
+ self.source=[]
+ if getattr(self,'cwd',None):
+ tsk.cwd=self.cwd
+@feature('seq')
+def sequence_order(self):
+ if self.meths and self.meths[-1]!='sequence_order':
+ self.meths.append('sequence_order')
+ return
+ if getattr(self,'seq_start',None):
+ return
+ if getattr(self.bld,'prev',None):
+ self.bld.prev.post()
+ for x in self.bld.prev.tasks:
+ for y in self.tasks:
+ y.set_run_after(x)
+ self.bld.prev=self
+re_m4=re.compile('@(\w+)@',re.M)
+class subst_pc(Task.Task):
+ def force_permissions(self):
+ if getattr(self.generator,'chmod',None):
+ for x in self.outputs:
+ os.chmod(x.abspath(),self.generator.chmod)
+ def run(self):
+ if getattr(self.generator,'is_copy',None):
+ for i,x in enumerate(self.outputs):
+ x.write(self.inputs[i].read('rb'),'wb')
+ self.force_permissions()
+ return None
+ if getattr(self.generator,'fun',None):
+ ret=self.generator.fun(self)
+ if not ret:
+ self.force_permissions()
+ return ret
+ code=self.inputs[0].read(encoding=getattr(self.generator,'encoding','ISO8859-1'))
+ if getattr(self.generator,'subst_fun',None):
+ code=self.generator.subst_fun(self,code)
+ if code is not None:
+ self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','ISO8859-1'))
+ self.force_permissions()
+ return None
+ code=code.replace('%','%%')
+ lst=[]
+ def repl(match):
+ g=match.group
+ if g(1):
+ lst.append(g(1))
+ return"%%(%s)s"%g(1)
+ return''
+ global re_m4
+ code=getattr(self.generator,'re_m4',re_m4).sub(repl,code)
+ try:
+ d=self.generator.dct
+ except AttributeError:
+ d={}
+ for x in lst:
+ tmp=getattr(self.generator,x,'')or self.env[x]or self.env[x.upper()]
+ try:
+ tmp=''.join(tmp)
+ except TypeError:
+ tmp=str(tmp)
+ d[x]=tmp
+ code=code%d
+ self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','ISO8859-1'))
+ self.generator.bld.raw_deps[self.uid()]=self.dep_vars=lst
+ try:delattr(self,'cache_sig')
+ except AttributeError:pass
+ self.force_permissions()
+ def sig_vars(self):
+ bld=self.generator.bld
+ env=self.env
+ upd=self.m.update
+ if getattr(self.generator,'fun',None):
+ upd(Utils.h_fun(self.generator.fun))
+ if getattr(self.generator,'subst_fun',None):
+ upd(Utils.h_fun(self.generator.subst_fun))
+ vars=self.generator.bld.raw_deps.get(self.uid(),[])
+ act_sig=bld.hash_env_vars(env,vars)
+ upd(act_sig)
+ lst=[getattr(self.generator,x,'')for x in vars]
+ upd(Utils.h_list(lst))
+ return self.m.digest()
+@extension('.pc.in')
+def add_pcfile(self,node):
+ tsk=self.create_task('subst_pc',node,node.change_ext('.pc','.pc.in'))
+ self.bld.install_files(getattr(self,'install_path','${LIBDIR}/pkgconfig/'),tsk.outputs)
+class subst(subst_pc):
+ pass
+@feature('subst')
+@before_method('process_source','process_rule')
+def process_subst(self):
+ src=Utils.to_list(getattr(self,'source',[]))
+ if isinstance(src,Node.Node):
+ src=[src]
+ tgt=Utils.to_list(getattr(self,'target',[]))
+ if isinstance(tgt,Node.Node):
+ tgt=[tgt]
+ if len(src)!=len(tgt):
+ raise Errors.WafError('invalid number of source/target for %r'%self)
+ for x,y in zip(src,tgt):
+ if not x or not y:
+ raise Errors.WafError('null source or target for %r'%self)
+ a,b=None,None
+ if isinstance(x,str)and isinstance(y,str)and x==y:
+ a=self.path.find_node(x)
+ b=self.path.get_bld().make_node(y)
+ if not os.path.isfile(b.abspath()):
+ b.sig=None
+ b.parent.mkdir()
+ else:
+ if isinstance(x,str):
+ a=self.path.find_resource(x)
+ elif isinstance(x,Node.Node):
+ a=x
+ if isinstance(y,str):
+ b=self.path.find_or_declare(y)
+ elif isinstance(y,Node.Node):
+ b=y
+ if not a:
+ raise Errors.WafError('could not find %r for %r'%(x,self))
+ has_constraints=False
+ tsk=self.create_task('subst',a,b)
+ for k in('after','before','ext_in','ext_out'):
+ val=getattr(self,k,None)
+ if val:
+ has_constraints=True
+ setattr(tsk,k,val)
+ if not has_constraints:
+ global HEADER_EXTS
+ for xt in HEADER_EXTS:
+ if b.name.endswith(xt):
+ tsk.before=[k for k in('c','cxx')if k in Task.classes]
+ break
+ inst_to=getattr(self,'install_path',None)
+ if inst_to:
+ self.bld.install_files(inst_to,b,chmod=getattr(self,'chmod',Utils.O644))
+ self.source=[]