README.md: improve markdown formatting, update homepage, use https
[pd-aubio.git] / waflib / TaskGen.py
1 #! /usr/bin/env python
2 # encoding: utf-8
3 # WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file
4
5 import copy,re,os
6 from waflib import Task,Utils,Logs,Errors,ConfigSet,Node
7 feats=Utils.defaultdict(set)
8 class task_gen(object):
9         mappings={}
10         prec=Utils.defaultdict(list)
11         def __init__(self,*k,**kw):
12                 self.source=''
13                 self.target=''
14                 self.meths=[]
15                 self.prec=Utils.defaultdict(list)
16                 self.mappings={}
17                 self.features=[]
18                 self.tasks=[]
19                 if not'bld'in kw:
20                         self.env=ConfigSet.ConfigSet()
21                         self.idx=0
22                         self.path=None
23                 else:
24                         self.bld=kw['bld']
25                         self.env=self.bld.env.derive()
26                         self.path=self.bld.path
27                         try:
28                                 self.idx=self.bld.idx[id(self.path)]=self.bld.idx.get(id(self.path),0)+1
29                         except AttributeError:
30                                 self.bld.idx={}
31                                 self.idx=self.bld.idx[id(self.path)]=1
32                 for key,val in kw.items():
33                         setattr(self,key,val)
34         def __str__(self):
35                 return"<task_gen %r declared in %s>"%(self.name,self.path.abspath())
36         def __repr__(self):
37                 lst=[]
38                 for x in self.__dict__.keys():
39                         if x not in['env','bld','compiled_tasks','tasks']:
40                                 lst.append("%s=%s"%(x,repr(getattr(self,x))))
41                 return"bld(%s) in %s"%(", ".join(lst),self.path.abspath())
42         def get_name(self):
43                 try:
44                         return self._name
45                 except AttributeError:
46                         if isinstance(self.target,list):
47                                 lst=[str(x)for x in self.target]
48                                 name=self._name=','.join(lst)
49                         else:
50                                 name=self._name=str(self.target)
51                         return name
52         def set_name(self,name):
53                 self._name=name
54         name=property(get_name,set_name)
55         def to_list(self,val):
56                 if isinstance(val,str):return val.split()
57                 else:return val
58         def post(self):
59                 if getattr(self,'posted',None):
60                         return False
61                 self.posted=True
62                 keys=set(self.meths)
63                 self.features=Utils.to_list(self.features)
64                 for x in self.features+['*']:
65                         st=feats[x]
66                         if not st:
67                                 if not x in Task.classes:
68                                         Logs.warn('feature %r does not exist - bind at least one method to it'%x)
69                         keys.update(list(st))
70                 prec={}
71                 prec_tbl=self.prec or task_gen.prec
72                 for x in prec_tbl:
73                         if x in keys:
74                                 prec[x]=prec_tbl[x]
75                 tmp=[]
76                 for a in keys:
77                         for x in prec.values():
78                                 if a in x:break
79                         else:
80                                 tmp.append(a)
81                 tmp.sort()
82                 out=[]
83                 while tmp:
84                         e=tmp.pop()
85                         if e in keys:out.append(e)
86                         try:
87                                 nlst=prec[e]
88                         except KeyError:
89                                 pass
90                         else:
91                                 del prec[e]
92                                 for x in nlst:
93                                         for y in prec:
94                                                 if x in prec[y]:
95                                                         break
96                                         else:
97                                                 tmp.append(x)
98                 if prec:
99                         raise Errors.WafError('Cycle detected in the method execution %r'%prec)
100                 out.reverse()
101                 self.meths=out
102                 Logs.debug('task_gen: posting %s %d'%(self,id(self)))
103                 for x in out:
104                         try:
105                                 v=getattr(self,x)
106                         except AttributeError:
107                                 raise Errors.WafError('%r is not a valid task generator method'%x)
108                         Logs.debug('task_gen: -> %s (%d)'%(x,id(self)))
109                         v()
110                 Logs.debug('task_gen: posted %s'%self.name)
111                 return True
112         def get_hook(self,node):
113                 name=node.name
114                 for k in self.mappings:
115                         if name.endswith(k):
116                                 return self.mappings[k]
117                 for k in task_gen.mappings:
118                         if name.endswith(k):
119                                 return task_gen.mappings[k]
120                 raise Errors.WafError("File %r has no mapping in %r (did you forget to load a waf tool?)"%(node,task_gen.mappings.keys()))
121         def create_task(self,name,src=None,tgt=None):
122                 task=Task.classes[name](env=self.env.derive(),generator=self)
123                 if src:
124                         task.set_inputs(src)
125                 if tgt:
126                         task.set_outputs(tgt)
127                 self.tasks.append(task)
128                 return task
129         def clone(self,env):
130                 newobj=self.bld()
131                 for x in self.__dict__:
132                         if x in['env','bld']:
133                                 continue
134                         elif x in['path','features']:
135                                 setattr(newobj,x,getattr(self,x))
136                         else:
137                                 setattr(newobj,x,copy.copy(getattr(self,x)))
138                 newobj.posted=False
139                 if isinstance(env,str):
140                         newobj.env=self.bld.all_envs[env].derive()
141                 else:
142                         newobj.env=env.derive()
143                 return newobj
144 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):
145         ext_in=Utils.to_list(ext_in)
146         ext_out=Utils.to_list(ext_out)
147         if not name:
148                 name=rule
149         cls=Task.task_factory(name,rule,color=color,ext_in=ext_in,ext_out=ext_out,before=before,after=after,scan=scan,shell=shell)
150         def x_file(self,node):
151                 ext=decider and decider(self,node)or cls.ext_out
152                 if ext_in:
153                         _ext_in=ext_in[0]
154                 tsk=self.create_task(name,node)
155                 cnt=0
156                 keys=list(self.mappings.keys())+list(self.__class__.mappings.keys())
157                 for x in ext:
158                         k=node.change_ext(x,ext_in=_ext_in)
159                         tsk.outputs.append(k)
160                         if reentrant!=None:
161                                 if cnt<int(reentrant):
162                                         self.source.append(k)
163                         else:
164                                 for y in keys:
165                                         if k.name.endswith(y):
166                                                 self.source.append(k)
167                                                 break
168                         cnt+=1
169                 if install_path:
170                         self.bld.install_files(install_path,tsk.outputs)
171                 return tsk
172         for x in cls.ext_in:
173                 task_gen.mappings[x]=x_file
174         return x_file
175 def taskgen_method(func):
176         setattr(task_gen,func.__name__,func)
177         return func
178 def feature(*k):
179         def deco(func):
180                 setattr(task_gen,func.__name__,func)
181                 for name in k:
182                         feats[name].update([func.__name__])
183                 return func
184         return deco
185 def before_method(*k):
186         def deco(func):
187                 setattr(task_gen,func.__name__,func)
188                 for fun_name in k:
189                         if not func.__name__ in task_gen.prec[fun_name]:
190                                 task_gen.prec[fun_name].append(func.__name__)
191                 return func
192         return deco
193 before=before_method
194 def after_method(*k):
195         def deco(func):
196                 setattr(task_gen,func.__name__,func)
197                 for fun_name in k:
198                         if not fun_name in task_gen.prec[func.__name__]:
199                                 task_gen.prec[func.__name__].append(fun_name)
200                 return func
201         return deco
202 after=after_method
203 def extension(*k):
204         def deco(func):
205                 setattr(task_gen,func.__name__,func)
206                 for x in k:
207                         task_gen.mappings[x]=func
208                 return func
209         return deco
210 @taskgen_method
211 def to_nodes(self,lst,path=None):
212         tmp=[]
213         path=path or self.path
214         find=path.find_resource
215         if isinstance(lst,self.path.__class__):
216                 lst=[lst]
217         for x in Utils.to_list(lst):
218                 if isinstance(x,str):
219                         node=find(x)
220                 else:
221                         node=x
222                 if not node:
223                         raise Errors.WafError("source not found: %r in %r"%(x,self))
224                 tmp.append(node)
225         return tmp
226 @feature('*')
227 def process_source(self):
228         self.source=self.to_nodes(getattr(self,'source',[]))
229         for node in self.source:
230                 self.get_hook(node)(self,node)
231 @feature('*')
232 @before_method('process_source')
233 def process_rule(self):
234         if not getattr(self,'rule',None):
235                 return
236         name=str(getattr(self,'name',None)or self.target or getattr(self.rule,'__name__',self.rule))
237         try:
238                 cache=self.bld.cache_rule_attr
239         except AttributeError:
240                 cache=self.bld.cache_rule_attr={}
241         cls=None
242         if getattr(self,'cache_rule','True'):
243                 try:
244                         cls=cache[(name,self.rule)]
245                 except KeyError:
246                         pass
247         if not cls:
248                 cls=Task.task_factory(name,self.rule,getattr(self,'vars',[]),shell=getattr(self,'shell',True),color=getattr(self,'color','BLUE'),scan=getattr(self,'scan',None))
249                 if getattr(self,'scan',None):
250                         cls.scan=self.scan
251                 elif getattr(self,'deps',None):
252                         def scan(self):
253                                 nodes=[]
254                                 for x in self.generator.to_list(getattr(self.generator,'deps',None)):
255                                         node=self.generator.path.find_resource(x)
256                                         if not node:
257                                                 self.generator.bld.fatal('Could not find %r (was it declared?)'%x)
258                                         nodes.append(node)
259                                 return[nodes,[]]
260                         cls.scan=scan
261                 if getattr(self,'update_outputs',None):
262                         Task.update_outputs(cls)
263                 if getattr(self,'always',None):
264                         Task.always_run(cls)
265                 for x in['after','before','ext_in','ext_out']:
266                         setattr(cls,x,getattr(self,x,[]))
267                 if getattr(self,'cache_rule','True'):
268                         cache[(name,self.rule)]=cls
269         tsk=self.create_task(name)
270         if getattr(self,'target',None):
271                 if isinstance(self.target,str):
272                         self.target=self.target.split()
273                 if not isinstance(self.target,list):
274                         self.target=[self.target]
275                 for x in self.target:
276                         if isinstance(x,str):
277                                 tsk.outputs.append(self.path.find_or_declare(x))
278                         else:
279                                 x.parent.mkdir()
280                                 tsk.outputs.append(x)
281                 if getattr(self,'install_path',None):
282                         self.bld.install_files(self.install_path,tsk.outputs)
283         if getattr(self,'source',None):
284                 tsk.inputs=self.to_nodes(self.source)
285                 self.source=[]
286         if getattr(self,'cwd',None):
287                 tsk.cwd=self.cwd
288 @feature('seq')
289 def sequence_order(self):
290         if self.meths and self.meths[-1]!='sequence_order':
291                 self.meths.append('sequence_order')
292                 return
293         if getattr(self,'seq_start',None):
294                 return
295         if getattr(self.bld,'prev',None):
296                 self.bld.prev.post()
297                 for x in self.bld.prev.tasks:
298                         for y in self.tasks:
299                                 y.set_run_after(x)
300         self.bld.prev=self
301 re_m4=re.compile('@(\w+)@',re.M)
302 class subst_pc(Task.Task):
303         def run(self):
304                 if getattr(self.generator,'is_copy',None):
305                         self.outputs[0].write(self.inputs[0].read('rb'),'wb')
306                         if getattr(self.generator,'chmod',None):
307                                 os.chmod(self.outputs[0].abspath(),self.generator.chmod)
308                         return None
309                 if getattr(self.generator,'fun',None):
310                         self.generator.fun(self)
311                 code=self.inputs[0].read(encoding=getattr(self.generator,'encoding','ISO8859-1'))
312                 if getattr(self.generator,'subst_fun',None):
313                         code=self.generator.subst_fun(self,code)
314                         if code:
315                                 self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','ISO8859-1'))
316                         return
317                 code=code.replace('%','%%')
318                 lst=[]
319                 def repl(match):
320                         g=match.group
321                         if g(1):
322                                 lst.append(g(1))
323                                 return"%%(%s)s"%g(1)
324                         return''
325                 code=re_m4.sub(repl,code)
326                 try:
327                         d=self.generator.dct
328                 except AttributeError:
329                         d={}
330                         for x in lst:
331                                 tmp=getattr(self.generator,x,'')or self.env.get_flat(x)or self.env.get_flat(x.upper())
332                                 d[x]=str(tmp)
333                 code=code%d
334                 self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','ISO8859-1'))
335                 self.generator.bld.raw_deps[self.uid()]=self.dep_vars=lst
336                 try:delattr(self,'cache_sig')
337                 except AttributeError:pass
338                 if getattr(self.generator,'chmod',None):
339                         os.chmod(self.outputs[0].abspath(),self.generator.chmod)
340         def sig_vars(self):
341                 bld=self.generator.bld
342                 env=self.env
343                 upd=self.m.update
344                 if getattr(self.generator,'fun',None):
345                         upd(Utils.h_fun(self.generator.fun))
346                 if getattr(self.generator,'subst_fun',None):
347                         upd(Utils.h_fun(self.generator.subst_fun))
348                 vars=self.generator.bld.raw_deps.get(self.uid(),[])
349                 act_sig=bld.hash_env_vars(env,vars)
350                 upd(act_sig)
351                 lst=[getattr(self.generator,x,'')for x in vars]
352                 upd(Utils.h_list(lst))
353                 return self.m.digest()
354 @extension('.pc.in')
355 def add_pcfile(self,node):
356         tsk=self.create_task('subst_pc',node,node.change_ext('.pc','.pc.in'))
357         self.bld.install_files(getattr(self,'install_path','${LIBDIR}/pkgconfig/'),tsk.outputs)
358 class subst(subst_pc):
359         pass
360 @feature('subst')
361 @before_method('process_source','process_rule')
362 def process_subst(self):
363         src=Utils.to_list(getattr(self,'source',[]))
364         if isinstance(src,Node.Node):
365                 src=[src]
366         tgt=Utils.to_list(getattr(self,'target',[]))
367         if isinstance(tgt,Node.Node):
368                 tgt=[tgt]
369         if len(src)!=len(tgt):
370                 raise Errors.WafError('invalid number of source/target for %r'%self)
371         for x,y in zip(src,tgt):
372                 if not x or not y:
373                         raise Errors.WafError('null source or target for %r'%self)
374                 a,b=None,None
375                 if isinstance(x,str)and isinstance(y,str)and x==y:
376                         a=self.path.find_node(x)
377                         b=self.path.get_bld().make_node(y)
378                         if not os.path.isfile(b.abspath()):
379                                 b.sig=None
380                                 b.parent.mkdir()
381                 else:
382                         if isinstance(x,str):
383                                 a=self.path.find_resource(x)
384                         elif isinstance(x,Node.Node):
385                                 a=x
386                         if isinstance(y,str):
387                                 b=self.path.find_or_declare(y)
388                         elif isinstance(y,Node.Node):
389                                 b=y
390                 if not a:
391                         raise Errors.WafError('cound not find %r for %r'%(x,self))
392                 has_constraints=False
393                 tsk=self.create_task('subst',a,b)
394                 for k in('after','before','ext_in','ext_out'):
395                         val=getattr(self,k,None)
396                         if val:
397                                 has_constraints=True
398                                 setattr(tsk,k,val)
399                 if not has_constraints and b.name.endswith('.h'):
400                         tsk.before=[k for k in('c','cxx')if k in Task.classes]
401                 inst_to=getattr(self,'install_path',None)
402                 if inst_to:
403                         self.bld.install_files(inst_to,b,chmod=getattr(self,'chmod',Utils.O644))
404         self.source=[]