3
# WARNING! Do not edit! http://waf.googlecode.com/svn/docs/wafbook/single.html#_obtaining_the_waf_file
6
if sys.hexversion < 0x020400f0: from sets import Set as set
7
import os,shutil,re,tempfile
8
from waflib import Utils,Logs,Errors
18
COMPILE_TEMPLATE_SHELL='''
23
wd = getattr(tsk, 'cwd', None)
25
tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s
26
return tsk.exec_command(cmd, cwd=wd, env=env.env or None)
28
COMPILE_TEMPLATE_NOSHELL='''
33
wd = getattr(tsk, 'cwd', None)
35
if isinstance(xx, str): return [xx]
37
tsk.last_cmd = lst = []
39
lst = [x for x in lst if x]
40
return tsk.exec_command(lst, cwd=wd, env=env.env or None)
42
def cache_outputs(cls):
45
bld=self.generator.bld
46
if bld.cache_global and not bld.nocache:
47
if self.can_retrieve_cache():
53
bld=self.generator.bld
55
if bld.cache_global and not bld.nocache:
56
self.put_files_cache()
61
class store_task_type(type):
62
def __init__(cls,name,bases,dict):
63
super(store_task_type,cls).__init__(name,bases,dict)
65
if name.endswith('_task'):
66
name=name.replace('_task','')
67
if name!='evil'and name!='TaskBase':
69
if getattr(cls,'run_str',None):
70
(f,dvars)=compile_fun(cls.run_str,cls.shell)
74
cls.vars=list(set(cls.vars+dvars))
76
elif getattr(cls,'run',None)and not'hcode'in cls.__dict__:
77
cls.hcode=Utils.h_fun(cls.run)
78
if not getattr(cls,'nocache',None):
79
cls=cache_outputs(cls)
81
evil=store_task_type('evil',(object,),{})
89
def __init__(self,*k,**kw):
92
self.generator=kw['generator']
96
return'\n\t{task %r: %s %s}'%(self.__class__.__name__,id(self),str(getattr(self,'fun','')))
98
if hasattr(self,'fun'):
99
return'executing: %s\n'%self.fun.__name__
100
return self.__class__.__name__+'\n'
103
def exec_command(self,cmd,**kw):
104
bld=self.generator.bld
106
if not kw.get('cwd',None):
108
except AttributeError:
109
bld.cwd=kw['cwd']=bld.variant_dir
110
return bld.exec_command(cmd,**kw)
111
def runnable_status(self):
119
del self.generator.bld.task_sigs[self.uid()]
123
self.generator.bld.returned_tasks.append(self)
124
self.log_display(self.generator.bld)
127
self.err_msg=Utils.ex_stack()
128
self.hasrun=EXCEPTION
129
m.error_handler(self)
138
except Errors.WafError:
141
self.err_msg=Utils.ex_stack()
142
self.hasrun=EXCEPTION
145
if self.hasrun!=SUCCESS:
146
m.error_handler(self)
149
if hasattr(self,'fun'):
150
return self.fun(self)
154
def log_display(self,bld):
155
bld.to_log(self.display())
157
col1=Logs.colors(self.color)
158
col2=Logs.colors.NORMAL
162
if hasattr(master,'ready'):
163
tmp-=master.ready.qsize()
164
return master.processed+tmp
165
if self.generator.bld.progress_bar==1:
166
return self.generator.bld.progress_line(cur(),master.total,col1,col2)
167
if self.generator.bld.progress_bar==2:
168
ela=str(self.generator.bld.timer)
170
ins=','.join([n.name for n in self.inputs])
171
except AttributeError:
174
outs=','.join([n.name for n in self.outputs])
175
except AttributeError:
177
return'|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n'%(master.total,cur(),ins,outs,ela)
183
fs='[%%%dd/%%%dd] %%s%%s%%s'%(n,n)
184
return fs%(cur(),total,col1,s,col2)
185
def attr(self,att,default=None):
186
ret=getattr(self,att,self)
187
if ret is self:return getattr(self.__class__,att,default)
189
def hash_constraints(self):
191
tup=(str(cls.before),str(cls.after),str(cls.ext_in),str(cls.ext_out),cls.__name__,cls.hcode)
194
def format_error(self):
195
msg=getattr(self,'last_cmd','')
196
if getattr(self,"err_msg",None):
198
elif self.hasrun==CRASHED:
200
return' -> task failed (exit status %r): %r\n%r'%(self.err_code,self,msg)
201
except AttributeError:
202
return' -> task failed: %r\n%r'%(self,msg)
203
elif self.hasrun==MISSING:
204
return' -> missing files: %r\n%r'%(self,msg)
207
def colon(self,var1,var2):
209
if isinstance(var2,str):
213
if isinstance(tmp,str):
214
return[tmp%x for x in it]
216
if Logs.verbose and not tmp and it:
217
Logs.warn('Missing env variable %r for task %r (generator %r)'%(var1,self,self.generator))
223
class Task(TaskBase):
226
def __init__(self,*k,**kw):
227
TaskBase.__init__(self,*k,**kw)
232
self.run_after=set([])
235
src_str=' '.join([a.nice_path(env)for a in self.inputs])
236
tgt_str=' '.join([a.nice_path(env)for a in self.outputs])
237
if self.outputs:sep=' -> '
239
return'%s: %s%s%s\n'%(self.__class__.__name__.replace('_task',''),src_str,sep,tgt_str)
241
return"".join(['\n\t{task %r: '%id(self),self.__class__.__name__," ",",".join([x.name for x in self.inputs])," -> ",",".join([x.name for x in self.outputs]),'}'])
245
except AttributeError:
248
up(self.__class__.__name__)
249
for x in self.inputs+self.outputs:
253
def set_inputs(self,inp):
254
if isinstance(inp,list):self.inputs+=inp
255
else:self.inputs.append(inp)
256
def set_outputs(self,out):
257
if isinstance(out,list):self.outputs+=out
258
else:self.outputs.append(out)
259
def set_run_after(self,task):
260
assert isinstance(task,TaskBase)
261
self.run_after.add(task)
263
try:return self.cache_sig
264
except AttributeError:pass
266
self.m.update(self.hcode)
267
self.sig_explicit_deps()
271
self.sig_implicit_deps()
272
except Errors.TaskRescan:
273
return self.signature()
274
ret=self.cache_sig=self.m.digest()
276
def runnable_status(self):
277
for t in self.run_after:
280
bld=self.generator.bld
282
new_sig=self.signature()
283
except Errors.TaskNotReady:
287
prev_sig=bld.task_sigs[key]
289
Logs.debug("task: task %r must run as it was never run before or the task code changed"%self)
291
for node in self.outputs:
293
if node.sig!=new_sig:
295
except AttributeError:
296
Logs.debug("task: task %r must run as the output nodes do not exist"%self)
298
if new_sig!=prev_sig:
302
bld=self.generator.bld
304
for node in self.outputs:
306
os.stat(node.abspath())
309
self.err_msg='-> missing file: %r'%node.abspath()
310
raise Errors.WafError(self.err_msg)
312
bld.task_sigs[self.uid()]=self.cache_sig
313
def sig_explicit_deps(self):
314
bld=self.generator.bld
316
for x in self.inputs+self.dep_nodes:
319
except(AttributeError,TypeError):
320
raise Errors.WafError('Missing node signature for %r (required by %r)'%(x,self))
322
additional_deps=bld.deps_man
323
for x in self.inputs+self.outputs:
325
d=additional_deps[id(x)]
329
if isinstance(v,bld.root.__class__):
332
except AttributeError:
333
raise Errors.WafError('Missing node signature for %r (required by %r)'%(v,self))
334
elif hasattr(v,'__call__'):
337
return self.m.digest()
339
bld=self.generator.bld
342
act_sig=bld.hash_env_vars(env,self.__class__.vars)
344
dep_vars=getattr(self,'dep_vars',None)
346
upd(bld.hash_env_vars(env,dep_vars))
347
return self.m.digest()
349
def sig_implicit_deps(self):
350
bld=self.generator.bld
352
prev=bld.task_sigs.get((key,'imp'),[])
355
if prev==self.compute_sig_implicit_deps():
358
for x in bld.node_deps.get(self.uid(),[]):
359
if x.is_child_of(bld.srcnode):
364
del x.parent.children[x.name]
367
del bld.task_sigs[(key,'imp')]
368
raise Errors.TaskRescan('rescan')
369
(nodes,names)=self.scan()
371
Logs.debug('deps: scanner for %s returned %s %s'%(str(self),str(nodes),str(names)))
372
bld.node_deps[key]=nodes
373
bld.raw_deps[key]=names
374
self.are_implicit_nodes_ready()
376
bld.task_sigs[(key,'imp')]=sig=self.compute_sig_implicit_deps()
379
for k in bld.node_deps.get(self.uid(),[]):
383
Logs.warn('Missing signature for node %r (may cause rebuilds)'%k)
386
def compute_sig_implicit_deps(self):
388
bld=self.generator.bld
389
self.are_implicit_nodes_ready()
390
for k in bld.node_deps.get(self.uid(),[]):
392
return self.m.digest()
393
def are_implicit_nodes_ready(self):
394
bld=self.generator.bld
396
cache=bld.dct_implicit_nodes
398
bld.dct_implicit_nodes=cache={}
402
dct=cache[bld.cur]={}
403
for tsk in bld.cur_tasks:
404
for x in tsk.outputs:
407
for x in bld.node_deps.get(self.uid(),[]):
409
self.run_after.add(dct[x])
412
for tsk in self.run_after:
414
raise Errors.TaskNotReady('not ready')
415
def can_retrieve_cache(self):
416
if not getattr(self,'outputs',None):
419
ssig=Utils.to_hex(self.uid())+Utils.to_hex(sig)
420
dname=os.path.join(self.generator.bld.cache_global,ssig)
422
t1=os.stat(dname).st_mtime
425
for node in self.outputs:
426
orig=os.path.join(dname,node.name)
428
shutil.copy2(orig,node.abspath())
430
except(OSError,IOError):
431
Logs.debug('task: failed retrieving file')
434
t2=os.stat(dname).st_mtime
439
for node in self.outputs:
441
if self.generator.bld.progress_bar<1:
442
self.generator.bld.to_log('restoring from cache %r\n'%node.abspath())
445
def put_files_cache(self):
446
if getattr(self,'cached',None):
448
if not getattr(self,'outputs',None):
451
ssig=Utils.to_hex(self.uid())+Utils.to_hex(sig)
452
dname=os.path.join(self.generator.bld.cache_global,ssig)
453
tmpdir=tempfile.mkdtemp(prefix=self.generator.bld.cache_global+os.sep+'waf')
459
for node in self.outputs:
460
dest=os.path.join(tmpdir,node.name)
461
shutil.copy2(node.abspath(),dest)
462
except(OSError,IOError):
464
shutil.rmtree(tmpdir)
469
os.rename(tmpdir,dname)
472
shutil.rmtree(tmpdir)
477
os.chmod(dname,Utils.O755)
480
def is_before(t1,t2):
481
to_list=Utils.to_list
482
for k in to_list(t2.ext_in):
483
if k in to_list(t1.ext_out):
485
if t1.__class__.__name__ in to_list(t2.after):
487
if t2.__class__.__name__ in to_list(t1.before):
490
def set_file_constraints(tasks):
491
ins=Utils.defaultdict(set)
492
outs=Utils.defaultdict(set)
494
for a in getattr(x,'inputs',[])+getattr(x,'dep_nodes',[]):
496
for a in getattr(x,'outputs',[]):
498
links=set(ins.keys()).intersection(outs.keys())
501
a.run_after.update(outs[k])
502
def set_precedence_constraints(tasks):
503
cstr_groups=Utils.defaultdict(list)
505
h=x.hash_constraints()
506
cstr_groups[h].append(x)
507
keys=list(cstr_groups.keys())
509
for i in range(maxi):
510
t1=cstr_groups[keys[i]][0]
511
for j in range(i+1,maxi):
512
t2=cstr_groups[keys[j]][0]
516
elif is_before(t2,t1):
521
for x in cstr_groups[keys[b]]:
522
x.run_after.update(cstr_groups[keys[a]])
527
reg_act=re.compile(r"(?P<backslash>\\)|(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})",re.M)
528
def compile_fun_shell(line):
532
if g('dollar'):return"$"
533
elif g('backslash'):return'\\\\'
534
elif g('subst'):extr.append((g('var'),g('code')));return"%s"
536
line=reg_act.sub(repl,line)or line
540
for(var,meth)in extr:
542
if meth:app('tsk.inputs%s'%meth)
543
else:app('" ".join([a.path_from(bld.bldnode) for a in tsk.inputs])')
545
if meth:app('tsk.outputs%s'%meth)
546
else:app('" ".join([a.path_from(bld.bldnode) for a in tsk.outputs])')
548
if meth.startswith(':'):
551
m='[a.path_from(bld.bldnode) for a in tsk.inputs]'
553
m='[a.path_from(bld.bldnode) for a in tsk.outputs]'
554
elif m[:3]not in('tsk','gen','bld'):
555
dvars.extend([var,meth[1:]])
557
app('" ".join(tsk.colon(%r, %s))'%(var,m))
559
app('%s%s'%(var,meth))
561
if not var in dvars:dvars.append(var)
563
if parm:parm="%% (%s) "%(',\n\t\t'.join(parm))
565
c=COMPILE_TEMPLATE_SHELL%(line,parm)
566
Logs.debug('action: %s'%c)
567
return(funex(c),dvars)
568
def compile_fun_noshell(line):
572
if g('dollar'):return"$"
573
elif g('subst'):extr.append((g('var'),g('code')));return"<<|@|>>"
575
line2=reg_act.sub(repl,line)
576
params=line2.split('<<|@|>>')
581
for x in range(len(extr)):
582
params[x]=params[x].strip()
584
app("lst.extend(%r)"%params[x].split())
587
if meth:app('lst.append(tsk.inputs%s)'%meth)
588
else:app("lst.extend([a.path_from(bld.bldnode) for a in tsk.inputs])")
590
if meth:app('lst.append(tsk.outputs%s)'%meth)
591
else:app("lst.extend([a.path_from(bld.bldnode) for a in tsk.outputs])")
593
if meth.startswith(':'):
596
m='[a.path_from(bld.bldnode) for a in tsk.inputs]'
598
m='[a.path_from(bld.bldnode) for a in tsk.outputs]'
599
elif m[:3]not in('tsk','gen','bld'):
600
dvars.extend([var,m])
602
app('lst.extend(tsk.colon(%r, %s))'%(var,m))
604
app('lst.extend(gen.to_list(%s%s))'%(var,meth))
606
app('lst.extend(to_list(env[%r]))'%var)
607
if not var in dvars:dvars.append(var)
610
app("lst.extend(%r)"%params[-1].split())
611
fun=COMPILE_TEMPLATE_NOSHELL%"\n\t".join(buf)
612
Logs.debug('action: %s'%fun)
613
return(funex(fun),dvars)
614
def compile_fun(line,shell=False):
615
if line.find('<')>0 or line.find('>')>0 or line.find('&&')>0:
618
return compile_fun_shell(line)
620
return compile_fun_noshell(line)
621
def task_factory(name,func=None,vars=None,color='GREEN',ext_in=[],ext_out=[],before=[],after=[],shell=False,scan=None):
622
params={'vars':vars or[],'color':color,'name':name,'ext_in':Utils.to_list(ext_in),'ext_out':Utils.to_list(ext_out),'before':Utils.to_list(before),'after':Utils.to_list(after),'shell':shell,'scan':scan,}
623
if isinstance(func,str):
624
params['run_str']=func
627
cls=type(Task)(name,(Task,),params)
632
old=cls.runnable_status
638
cls.runnable_status=always
640
def update_outputs(cls):
641
old_post_run=cls.post_run
644
for node in self.outputs:
645
node.sig=Utils.h_file(node.abspath())
646
self.generator.bld.task_sigs[node.abspath()]=self.uid()
647
cls.post_run=post_run
648
old_runnable_status=cls.runnable_status
649
def runnable_status(self):
650
status=old_runnable_status(self)
654
bld=self.generator.bld
655
prev_sig=bld.task_sigs[self.uid()]
656
if prev_sig==self.signature():
657
for x in self.outputs:
658
if not x.sig or bld.task_sigs[x.abspath()]!=self.uid():
665
except AttributeError:
668
cls.runnable_status=runnable_status