689 lines
18 KiB
Python
689 lines
18 KiB
Python
#! /usr/bin/env python
|
|
# encoding: utf-8
|
|
# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file
|
|
|
|
import os,re,sys,tempfile
|
|
from waflib import Utils,Logs,Errors
|
|
NOT_RUN=0
|
|
MISSING=1
|
|
CRASHED=2
|
|
EXCEPTION=3
|
|
SKIPPED=8
|
|
SUCCESS=9
|
|
ASK_LATER=-1
|
|
SKIP_ME=-2
|
|
RUN_ME=-3
|
|
COMPILE_TEMPLATE_SHELL='''
|
|
def f(tsk):
|
|
env = tsk.env
|
|
gen = tsk.generator
|
|
bld = gen.bld
|
|
cwdx = tsk.get_cwd()
|
|
p = env.get_flat
|
|
tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s
|
|
return tsk.exec_command(cmd, cwd=cwdx, env=env.env or None)
|
|
'''
|
|
COMPILE_TEMPLATE_NOSHELL='''
|
|
def f(tsk):
|
|
env = tsk.env
|
|
gen = tsk.generator
|
|
bld = gen.bld
|
|
cwdx = tsk.get_cwd()
|
|
def to_list(xx):
|
|
if isinstance(xx, str): return [xx]
|
|
return xx
|
|
def merge(lst1, lst2):
|
|
if lst1 and lst2:
|
|
return lst1[:-1] + [lst1[-1] + lst2[0]] + lst2[1:]
|
|
return lst1 + lst2
|
|
lst = []
|
|
%s
|
|
if '' in lst:
|
|
lst = [x for x in lst if x]
|
|
tsk.last_cmd = lst
|
|
return tsk.exec_command(lst, cwd=cwdx, env=env.env or None)
|
|
'''
|
|
classes={}
|
|
class store_task_type(type):
|
|
def __init__(cls,name,bases,dict):
|
|
super(store_task_type,cls).__init__(name,bases,dict)
|
|
name=cls.__name__
|
|
if name!='evil'and name!='TaskBase':
|
|
global classes
|
|
if getattr(cls,'run_str',None):
|
|
(f,dvars)=compile_fun(cls.run_str,cls.shell)
|
|
cls.hcode=Utils.h_cmd(cls.run_str)
|
|
cls.orig_run_str=cls.run_str
|
|
cls.run_str=None
|
|
cls.run=f
|
|
cls.vars=list(set(cls.vars+dvars))
|
|
cls.vars.sort()
|
|
elif getattr(cls,'run',None)and not'hcode'in cls.__dict__:
|
|
cls.hcode=Utils.h_cmd(cls.run)
|
|
getattr(cls,'register',classes)[name]=cls
|
|
evil=store_task_type('evil',(object,),{})
|
|
class TaskBase(evil):
|
|
color='GREEN'
|
|
ext_in=[]
|
|
ext_out=[]
|
|
before=[]
|
|
after=[]
|
|
hcode=''
|
|
__slots__=('hasrun','generator')
|
|
def __init__(self,*k,**kw):
|
|
self.hasrun=NOT_RUN
|
|
try:
|
|
self.generator=kw['generator']
|
|
except KeyError:
|
|
self.generator=self
|
|
def __repr__(self):
|
|
return'\n\t{task %r: %s %s}'%(self.__class__.__name__,id(self),str(getattr(self,'fun','')))
|
|
def __str__(self):
|
|
if hasattr(self,'fun'):
|
|
return self.fun.__name__
|
|
return self.__class__.__name__
|
|
def keyword(self):
|
|
if hasattr(self,'fun'):
|
|
return'Function'
|
|
return'Processing'
|
|
def get_cwd(self):
|
|
bld=self.generator.bld
|
|
ret=getattr(self,'cwd',None)or getattr(self.generator.bld,'cwd',bld.bldnode)
|
|
if isinstance(ret,str):
|
|
self.generator.bld.fatal('Working folders given to tasks must be Node objects')
|
|
return ret
|
|
def quote_flag(self,x):
|
|
old=x
|
|
if'\\'in x:
|
|
x=x.replace('\\','\\\\')
|
|
if'"'in x:
|
|
x=x.replace('"','\\"')
|
|
if old!=x or' 'in x or'\t'in x or"'"in x:
|
|
x='"%s"'%x
|
|
return x
|
|
def split_argfile(self,cmd):
|
|
return([cmd[0]],[self.quote_flag(x)for x in cmd[1:]])
|
|
def exec_command(self,cmd,**kw):
|
|
if not'cwd'in kw:
|
|
kw['cwd']=self.get_cwd()
|
|
if self.env.PATH:
|
|
env=kw['env']=dict(kw.get('env')or self.env.env or os.environ)
|
|
env['PATH']=self.env.PATH if isinstance(self.env.PATH,str)else os.pathsep.join(self.env.PATH)
|
|
if not isinstance(cmd,str)and(len(repr(cmd))>=8192 if Utils.is_win32 else len(cmd)>200000):
|
|
cmd,args=self.split_argfile(cmd)
|
|
try:
|
|
(fd,tmp)=tempfile.mkstemp()
|
|
os.write(fd,'\r\n'.join(args))
|
|
os.close(fd)
|
|
return self.generator.bld.exec_command(cmd+['@'+tmp],**kw)
|
|
finally:
|
|
try:
|
|
os.remove(tmp)
|
|
except OSError:
|
|
pass
|
|
else:
|
|
return self.generator.bld.exec_command(cmd,**kw)
|
|
def runnable_status(self):
|
|
return RUN_ME
|
|
def uid(self):
|
|
return Utils.SIG_NIL
|
|
def process(self):
|
|
m=self.generator.bld.producer
|
|
try:
|
|
del self.generator.bld.task_sigs[self.uid()]
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
ret=self.run()
|
|
except Exception:
|
|
self.err_msg=Utils.ex_stack()
|
|
self.hasrun=EXCEPTION
|
|
m.error_handler(self)
|
|
return
|
|
if ret:
|
|
self.err_code=ret
|
|
self.hasrun=CRASHED
|
|
else:
|
|
try:
|
|
self.post_run()
|
|
except Errors.WafError:
|
|
pass
|
|
except Exception:
|
|
self.err_msg=Utils.ex_stack()
|
|
self.hasrun=EXCEPTION
|
|
else:
|
|
self.hasrun=SUCCESS
|
|
if self.hasrun!=SUCCESS:
|
|
m.error_handler(self)
|
|
def run(self):
|
|
if hasattr(self,'fun'):
|
|
return self.fun(self)
|
|
return 0
|
|
def post_run(self):
|
|
pass
|
|
def log_display(self,bld):
|
|
if self.generator.bld.progress_bar==3:
|
|
return
|
|
s=self.display()
|
|
if s:
|
|
if bld.logger:
|
|
logger=bld.logger
|
|
else:
|
|
logger=Logs
|
|
if self.generator.bld.progress_bar==1:
|
|
c1=Logs.colors.cursor_off
|
|
c2=Logs.colors.cursor_on
|
|
logger.info(s,extra={'stream':sys.stderr,'terminator':'','c1':c1,'c2':c2})
|
|
else:
|
|
logger.info(s,extra={'terminator':'','c1':'','c2':''})
|
|
def display(self):
|
|
col1=Logs.colors(self.color)
|
|
col2=Logs.colors.NORMAL
|
|
master=self.generator.bld.producer
|
|
def cur():
|
|
tmp=-1
|
|
if hasattr(master,'ready'):
|
|
tmp-=master.ready.qsize()
|
|
return master.processed+tmp
|
|
if self.generator.bld.progress_bar==1:
|
|
return self.generator.bld.progress_line(cur(),master.total,col1,col2)
|
|
if self.generator.bld.progress_bar==2:
|
|
ela=str(self.generator.bld.timer)
|
|
try:
|
|
ins=','.join([n.name for n in self.inputs])
|
|
except AttributeError:
|
|
ins=''
|
|
try:
|
|
outs=','.join([n.name for n in self.outputs])
|
|
except AttributeError:
|
|
outs=''
|
|
return'|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n'%(master.total,cur(),ins,outs,ela)
|
|
s=str(self)
|
|
if not s:
|
|
return None
|
|
total=master.total
|
|
n=len(str(total))
|
|
fs='[%%%dd/%%%dd] %%s%%s%%s%%s\n'%(n,n)
|
|
kw=self.keyword()
|
|
if kw:
|
|
kw+=' '
|
|
return fs%(cur(),total,kw,col1,s,col2)
|
|
def hash_constraints(self):
|
|
cls=self.__class__
|
|
tup=(str(cls.before),str(cls.after),str(cls.ext_in),str(cls.ext_out),cls.__name__,cls.hcode)
|
|
return hash(tup)
|
|
def format_error(self):
|
|
msg=getattr(self,'last_cmd','')
|
|
name=getattr(self.generator,'name','')
|
|
if getattr(self,"err_msg",None):
|
|
return self.err_msg
|
|
elif not self.hasrun:
|
|
return'task in %r was not executed for some reason: %r'%(name,self)
|
|
elif self.hasrun==CRASHED:
|
|
try:
|
|
return' -> task in %r failed (exit status %r): %r\n%r'%(name,self.err_code,self,msg)
|
|
except AttributeError:
|
|
return' -> task in %r failed: %r\n%r'%(name,self,msg)
|
|
elif self.hasrun==MISSING:
|
|
return' -> missing files in %r: %r\n%r'%(name,self,msg)
|
|
else:
|
|
return'invalid status for task in %r: %r'%(name,self.hasrun)
|
|
def colon(self,var1,var2):
|
|
tmp=self.env[var1]
|
|
if not tmp:
|
|
return[]
|
|
if isinstance(var2,str):
|
|
it=self.env[var2]
|
|
else:
|
|
it=var2
|
|
if isinstance(tmp,str):
|
|
return[tmp%x for x in it]
|
|
else:
|
|
lst=[]
|
|
for y in it:
|
|
lst.extend(tmp)
|
|
lst.append(y)
|
|
return lst
|
|
class Task(TaskBase):
|
|
vars=[]
|
|
always_run=False
|
|
shell=False
|
|
def __init__(self,*k,**kw):
|
|
TaskBase.__init__(self,*k,**kw)
|
|
self.env=kw['env']
|
|
self.inputs=[]
|
|
self.outputs=[]
|
|
self.dep_nodes=[]
|
|
self.run_after=set([])
|
|
def __str__(self):
|
|
name=self.__class__.__name__
|
|
if self.outputs:
|
|
if name.endswith(('lib','program'))or not self.inputs:
|
|
node=self.outputs[0]
|
|
return node.path_from(node.ctx.launch_node())
|
|
if not(self.inputs or self.outputs):
|
|
return self.__class__.__name__
|
|
if len(self.inputs)==1:
|
|
node=self.inputs[0]
|
|
return node.path_from(node.ctx.launch_node())
|
|
src_str=' '.join([a.path_from(a.ctx.launch_node())for a in self.inputs])
|
|
tgt_str=' '.join([a.path_from(a.ctx.launch_node())for a in self.outputs])
|
|
if self.outputs:sep=' -> '
|
|
else:sep=''
|
|
return'%s: %s%s%s'%(self.__class__.__name__,src_str,sep,tgt_str)
|
|
def keyword(self):
|
|
name=self.__class__.__name__
|
|
if name.endswith(('lib','program')):
|
|
return'Linking'
|
|
if len(self.inputs)==1 and len(self.outputs)==1:
|
|
return'Compiling'
|
|
if not self.inputs:
|
|
if self.outputs:
|
|
return'Creating'
|
|
else:
|
|
return'Running'
|
|
return'Processing'
|
|
def __repr__(self):
|
|
try:
|
|
ins=",".join([x.name for x in self.inputs])
|
|
outs=",".join([x.name for x in self.outputs])
|
|
except AttributeError:
|
|
ins=",".join([str(x)for x in self.inputs])
|
|
outs=",".join([str(x)for x in self.outputs])
|
|
return"".join(['\n\t{task %r: '%id(self),self.__class__.__name__," ",ins," -> ",outs,'}'])
|
|
def uid(self):
|
|
try:
|
|
return self.uid_
|
|
except AttributeError:
|
|
m=Utils.md5(self.__class__.__name__)
|
|
up=m.update
|
|
for x in self.inputs+self.outputs:
|
|
up(x.abspath())
|
|
self.uid_=m.digest()
|
|
return self.uid_
|
|
def set_inputs(self,inp):
|
|
if isinstance(inp,list):self.inputs+=inp
|
|
else:self.inputs.append(inp)
|
|
def set_outputs(self,out):
|
|
if isinstance(out,list):self.outputs+=out
|
|
else:self.outputs.append(out)
|
|
def set_run_after(self,task):
|
|
assert isinstance(task,TaskBase)
|
|
self.run_after.add(task)
|
|
def signature(self):
|
|
try:
|
|
return self.cache_sig
|
|
except AttributeError:
|
|
pass
|
|
self.m=Utils.md5(self.hcode)
|
|
self.sig_explicit_deps()
|
|
self.sig_vars()
|
|
if self.scan:
|
|
try:
|
|
self.sig_implicit_deps()
|
|
except Errors.TaskRescan:
|
|
return self.signature()
|
|
ret=self.cache_sig=self.m.digest()
|
|
return ret
|
|
def runnable_status(self):
|
|
for t in self.run_after:
|
|
if not t.hasrun:
|
|
return ASK_LATER
|
|
try:
|
|
new_sig=self.signature()
|
|
except Errors.TaskNotReady:
|
|
return ASK_LATER
|
|
bld=self.generator.bld
|
|
key=self.uid()
|
|
try:
|
|
prev_sig=bld.task_sigs[key]
|
|
except KeyError:
|
|
Logs.debug('task: task %r must run: it was never run before or the task code changed',self)
|
|
return RUN_ME
|
|
if new_sig!=prev_sig:
|
|
Logs.debug('task: task %r must run: the task signature changed',self)
|
|
return RUN_ME
|
|
for node in self.outputs:
|
|
sig=bld.node_sigs.get(node)
|
|
if not sig:
|
|
Logs.debug('task: task %r must run: an output node has no signature',self)
|
|
return RUN_ME
|
|
if sig!=key:
|
|
Logs.debug('task: task %r must run: an output node was produced by another task',self)
|
|
return RUN_ME
|
|
if not node.exists():
|
|
Logs.debug('task: task %r must run: an output node does not exist',self)
|
|
return RUN_ME
|
|
return(self.always_run and RUN_ME)or SKIP_ME
|
|
def post_run(self):
|
|
bld=self.generator.bld
|
|
for node in self.outputs:
|
|
if not node.exists():
|
|
self.hasrun=MISSING
|
|
self.err_msg='-> missing file: %r'%node.abspath()
|
|
raise Errors.WafError(self.err_msg)
|
|
bld.node_sigs[node]=self.uid()
|
|
bld.task_sigs[self.uid()]=self.signature()
|
|
try:
|
|
del self.last_cmd
|
|
except AttributeError:
|
|
pass
|
|
def sig_explicit_deps(self):
|
|
bld=self.generator.bld
|
|
upd=self.m.update
|
|
for x in self.inputs+self.dep_nodes:
|
|
upd(x.get_bld_sig())
|
|
if bld.deps_man:
|
|
additional_deps=bld.deps_man
|
|
for x in self.inputs+self.outputs:
|
|
try:
|
|
d=additional_deps[x]
|
|
except KeyError:
|
|
continue
|
|
for v in d:
|
|
if isinstance(v,bld.root.__class__):
|
|
v=v.get_bld_sig()
|
|
elif hasattr(v,'__call__'):
|
|
v=v()
|
|
upd(v)
|
|
def sig_vars(self):
|
|
sig=self.generator.bld.hash_env_vars(self.env,self.__class__.vars)
|
|
self.m.update(sig)
|
|
scan=None
|
|
def sig_implicit_deps(self):
|
|
bld=self.generator.bld
|
|
key=self.uid()
|
|
prev=bld.imp_sigs.get(key,[])
|
|
if prev:
|
|
try:
|
|
if prev==self.compute_sig_implicit_deps():
|
|
return prev
|
|
except Errors.TaskNotReady:
|
|
raise
|
|
except EnvironmentError:
|
|
for x in bld.node_deps.get(self.uid(),[]):
|
|
if not x.is_bld()and not x.exists():
|
|
try:
|
|
del x.parent.children[x.name]
|
|
except KeyError:
|
|
pass
|
|
del bld.imp_sigs[key]
|
|
raise Errors.TaskRescan('rescan')
|
|
(bld.node_deps[key],bld.raw_deps[key])=self.scan()
|
|
if Logs.verbose:
|
|
Logs.debug('deps: scanner for %s: %r; unresolved: %r',self,bld.node_deps[key],bld.raw_deps[key])
|
|
try:
|
|
bld.imp_sigs[key]=self.compute_sig_implicit_deps()
|
|
except EnvironmentError:
|
|
for k in bld.node_deps.get(self.uid(),[]):
|
|
if not k.exists():
|
|
Logs.warn('Dependency %r for %r is missing: check the task declaration and the build order!',k,self)
|
|
raise
|
|
def compute_sig_implicit_deps(self):
|
|
upd=self.m.update
|
|
self.are_implicit_nodes_ready()
|
|
for k in self.generator.bld.node_deps.get(self.uid(),[]):
|
|
upd(k.get_bld_sig())
|
|
return self.m.digest()
|
|
def are_implicit_nodes_ready(self):
|
|
bld=self.generator.bld
|
|
try:
|
|
cache=bld.dct_implicit_nodes
|
|
except AttributeError:
|
|
bld.dct_implicit_nodes=cache={}
|
|
try:
|
|
dct=cache[bld.cur]
|
|
except KeyError:
|
|
dct=cache[bld.cur]={}
|
|
for tsk in bld.cur_tasks:
|
|
for x in tsk.outputs:
|
|
dct[x]=tsk
|
|
modified=False
|
|
for x in bld.node_deps.get(self.uid(),[]):
|
|
if x in dct:
|
|
self.run_after.add(dct[x])
|
|
modified=True
|
|
if modified:
|
|
for tsk in self.run_after:
|
|
if not tsk.hasrun:
|
|
raise Errors.TaskNotReady('not ready')
|
|
if sys.hexversion>0x3000000:
|
|
def uid(self):
|
|
try:
|
|
return self.uid_
|
|
except AttributeError:
|
|
m=Utils.md5(self.__class__.__name__.encode('iso8859-1','xmlcharrefreplace'))
|
|
up=m.update
|
|
for x in self.inputs+self.outputs:
|
|
up(x.abspath().encode('iso8859-1','xmlcharrefreplace'))
|
|
self.uid_=m.digest()
|
|
return self.uid_
|
|
uid.__doc__=Task.uid.__doc__
|
|
Task.uid=uid
|
|
def is_before(t1,t2):
|
|
to_list=Utils.to_list
|
|
for k in to_list(t2.ext_in):
|
|
if k in to_list(t1.ext_out):
|
|
return 1
|
|
if t1.__class__.__name__ in to_list(t2.after):
|
|
return 1
|
|
if t2.__class__.__name__ in to_list(t1.before):
|
|
return 1
|
|
return 0
|
|
def set_file_constraints(tasks):
|
|
ins=Utils.defaultdict(set)
|
|
outs=Utils.defaultdict(set)
|
|
for x in tasks:
|
|
for a in getattr(x,'inputs',[])+getattr(x,'dep_nodes',[]):
|
|
ins[id(a)].add(x)
|
|
for a in getattr(x,'outputs',[]):
|
|
outs[id(a)].add(x)
|
|
links=set(ins.keys()).intersection(outs.keys())
|
|
for k in links:
|
|
for a in ins[k]:
|
|
a.run_after.update(outs[k])
|
|
def set_precedence_constraints(tasks):
|
|
cstr_groups=Utils.defaultdict(list)
|
|
for x in tasks:
|
|
h=x.hash_constraints()
|
|
cstr_groups[h].append(x)
|
|
keys=list(cstr_groups.keys())
|
|
maxi=len(keys)
|
|
for i in range(maxi):
|
|
t1=cstr_groups[keys[i]][0]
|
|
for j in range(i+1,maxi):
|
|
t2=cstr_groups[keys[j]][0]
|
|
if is_before(t1,t2):
|
|
a=i
|
|
b=j
|
|
elif is_before(t2,t1):
|
|
a=j
|
|
b=i
|
|
else:
|
|
continue
|
|
aval=set(cstr_groups[keys[a]])
|
|
for x in cstr_groups[keys[b]]:
|
|
x.run_after.update(aval)
|
|
def funex(c):
|
|
dc={}
|
|
exec(c,dc)
|
|
return dc['f']
|
|
re_cond=re.compile('(?P<var>\w+)|(?P<or>\|)|(?P<and>&)')
|
|
re_novar=re.compile(r'^(SRC|TGT)\W+.*?$')
|
|
reg_act=re.compile(r'(?P<backslash>\\)|(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})',re.M)
|
|
def compile_fun_shell(line):
|
|
extr=[]
|
|
def repl(match):
|
|
g=match.group
|
|
if g('dollar'):
|
|
return"$"
|
|
elif g('backslash'):
|
|
return'\\\\'
|
|
elif g('subst'):
|
|
extr.append((g('var'),g('code')))
|
|
return"%s"
|
|
return None
|
|
line=reg_act.sub(repl,line)or line
|
|
def replc(m):
|
|
if m.group('and'):
|
|
return' and '
|
|
elif m.group('or'):
|
|
return' or '
|
|
else:
|
|
x=m.group('var')
|
|
if x not in dvars:
|
|
dvars.append(x)
|
|
return'env[%r]'%x
|
|
parm=[]
|
|
dvars=[]
|
|
app=parm.append
|
|
for(var,meth)in extr:
|
|
if var=='SRC':
|
|
if meth:app('tsk.inputs%s'%meth)
|
|
else:app('" ".join([a.path_from(cwdx) for a in tsk.inputs])')
|
|
elif var=='TGT':
|
|
if meth:app('tsk.outputs%s'%meth)
|
|
else:app('" ".join([a.path_from(cwdx) for a in tsk.outputs])')
|
|
elif meth:
|
|
if meth.startswith(':'):
|
|
if var not in dvars:
|
|
dvars.append(var)
|
|
m=meth[1:]
|
|
if m=='SRC':
|
|
m='[a.path_from(cwdx) for a in tsk.inputs]'
|
|
elif m=='TGT':
|
|
m='[a.path_from(cwdx) for a in tsk.outputs]'
|
|
elif re_novar.match(m):
|
|
m='[tsk.inputs%s]'%m[3:]
|
|
elif re_novar.match(m):
|
|
m='[tsk.outputs%s]'%m[3:]
|
|
elif m[:3]not in('tsk','gen','bld'):
|
|
dvars.append(meth[1:])
|
|
m='%r'%m
|
|
app('" ".join(tsk.colon(%r, %s))'%(var,m))
|
|
elif meth.startswith('?'):
|
|
expr=re_cond.sub(replc,meth[1:])
|
|
app('p(%r) if (%s) else ""'%(var,expr))
|
|
else:
|
|
app('%s%s'%(var,meth))
|
|
else:
|
|
if var not in dvars:
|
|
dvars.append(var)
|
|
app("p('%s')"%var)
|
|
if parm:parm="%% (%s) "%(',\n\t\t'.join(parm))
|
|
else:parm=''
|
|
c=COMPILE_TEMPLATE_SHELL%(line,parm)
|
|
Logs.debug('action: %s',c.strip().splitlines())
|
|
return(funex(c),dvars)
|
|
reg_act_noshell=re.compile(r"(?P<space>\s+)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})|(?P<text>\S+)",re.M)
|
|
def compile_fun_noshell(line):
|
|
buf=[]
|
|
dvars=[]
|
|
merge=False
|
|
app=buf.append
|
|
def replc(m):
|
|
if m.group('and'):
|
|
return' and '
|
|
elif m.group('or'):
|
|
return' or '
|
|
else:
|
|
x=m.group('var')
|
|
if x not in dvars:
|
|
dvars.append(x)
|
|
return'env[%r]'%x
|
|
for m in reg_act_noshell.finditer(line):
|
|
if m.group('space'):
|
|
merge=False
|
|
continue
|
|
elif m.group('text'):
|
|
app('[%r]'%m.group('text'))
|
|
elif m.group('subst'):
|
|
var=m.group('var')
|
|
code=m.group('code')
|
|
if var=='SRC':
|
|
if code:
|
|
app('[tsk.inputs%s]'%code)
|
|
else:
|
|
app('[a.path_from(cwdx) for a in tsk.inputs]')
|
|
elif var=='TGT':
|
|
if code:
|
|
app('[tsk.outputs%s]'%code)
|
|
else:
|
|
app('[a.path_from(cwdx) for a in tsk.outputs]')
|
|
elif code:
|
|
if code.startswith(':'):
|
|
if not var in dvars:
|
|
dvars.append(var)
|
|
m=code[1:]
|
|
if m=='SRC':
|
|
m='[a.path_from(cwdx) for a in tsk.inputs]'
|
|
elif m=='TGT':
|
|
m='[a.path_from(cwdx) for a in tsk.outputs]'
|
|
elif re_novar.match(m):
|
|
m='[tsk.inputs%s]'%m[3:]
|
|
elif re_novar.match(m):
|
|
m='[tsk.outputs%s]'%m[3:]
|
|
elif m[:3]not in('tsk','gen','bld'):
|
|
dvars.append(m)
|
|
m='%r'%m
|
|
app('tsk.colon(%r, %s)'%(var,m))
|
|
elif code.startswith('?'):
|
|
expr=re_cond.sub(replc,code[1:])
|
|
app('to_list(env[%r] if (%s) else [])'%(var,expr))
|
|
else:
|
|
app('gen.to_list(%s%s)'%(var,code))
|
|
else:
|
|
app('to_list(env[%r])'%var)
|
|
if not var in dvars:
|
|
dvars.append(var)
|
|
if merge:
|
|
tmp='merge(%s, %s)'%(buf[-2],buf[-1])
|
|
del buf[-1]
|
|
buf[-1]=tmp
|
|
merge=True
|
|
buf=['lst.extend(%s)'%x for x in buf]
|
|
fun=COMPILE_TEMPLATE_NOSHELL%"\n\t".join(buf)
|
|
Logs.debug('action: %s',fun.strip().splitlines())
|
|
return(funex(fun),dvars)
|
|
def compile_fun(line,shell=False):
|
|
if isinstance(line,str):
|
|
if line.find('<')>0 or line.find('>')>0 or line.find('&&')>0:
|
|
shell=True
|
|
else:
|
|
dvars_lst=[]
|
|
funs_lst=[]
|
|
for x in line:
|
|
if isinstance(x,str):
|
|
fun,dvars=compile_fun(x,shell)
|
|
dvars_lst+=dvars
|
|
funs_lst.append(fun)
|
|
else:
|
|
funs_lst.append(x)
|
|
def composed_fun(task):
|
|
for x in funs_lst:
|
|
ret=x(task)
|
|
if ret:
|
|
return ret
|
|
return None
|
|
return composed_fun,dvars
|
|
if shell:
|
|
return compile_fun_shell(line)
|
|
else:
|
|
return compile_fun_noshell(line)
|
|
def task_factory(name,func=None,vars=None,color='GREEN',ext_in=[],ext_out=[],before=[],after=[],shell=False,scan=None):
|
|
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,}
|
|
if isinstance(func,str)or isinstance(func,tuple):
|
|
params['run_str']=func
|
|
else:
|
|
params['run']=func
|
|
cls=type(Task)(name,(Task,),params)
|
|
global classes
|
|
classes[name]=cls
|
|
return cls
|
|
def always_run(cls):
|
|
Logs.warn('This decorator is deprecated, set always_run on the task class instead!')
|
|
cls.always_run=True
|
|
return cls
|
|
def update_outputs(cls):
|
|
return cls
|