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 os,re,sys |
---|
6 | from waflib import Utils,Logs,Errors |
---|
7 | NOT_RUN=0 |
---|
8 | MISSING=1 |
---|
9 | CRASHED=2 |
---|
10 | EXCEPTION=3 |
---|
11 | SKIPPED=8 |
---|
12 | SUCCESS=9 |
---|
13 | ASK_LATER=-1 |
---|
14 | SKIP_ME=-2 |
---|
15 | RUN_ME=-3 |
---|
16 | COMPILE_TEMPLATE_SHELL=''' |
---|
17 | def f(tsk): |
---|
18 | env = tsk.env |
---|
19 | gen = tsk.generator |
---|
20 | bld = gen.bld |
---|
21 | wd = getattr(tsk, 'cwd', None) |
---|
22 | p = env.get_flat |
---|
23 | tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s |
---|
24 | return tsk.exec_command(cmd, cwd=wd, env=env.env or None) |
---|
25 | ''' |
---|
26 | COMPILE_TEMPLATE_NOSHELL=''' |
---|
27 | def f(tsk): |
---|
28 | env = tsk.env |
---|
29 | gen = tsk.generator |
---|
30 | bld = gen.bld |
---|
31 | wd = getattr(tsk, 'cwd', None) |
---|
32 | def to_list(xx): |
---|
33 | if isinstance(xx, str): return [xx] |
---|
34 | return xx |
---|
35 | tsk.last_cmd = lst = [] |
---|
36 | %s |
---|
37 | lst = [x for x in lst if x] |
---|
38 | return tsk.exec_command(lst, cwd=wd, env=env.env or None) |
---|
39 | ''' |
---|
40 | classes={} |
---|
41 | class store_task_type(type): |
---|
42 | def __init__(cls,name,bases,dict): |
---|
43 | super(store_task_type,cls).__init__(name,bases,dict) |
---|
44 | name=cls.__name__ |
---|
45 | if name.endswith('_task'): |
---|
46 | name=name.replace('_task','') |
---|
47 | if name!='evil'and name!='TaskBase': |
---|
48 | global classes |
---|
49 | if getattr(cls,'run_str',None): |
---|
50 | (f,dvars)=compile_fun(cls.run_str,cls.shell) |
---|
51 | cls.hcode=cls.run_str |
---|
52 | cls.orig_run_str=cls.run_str |
---|
53 | cls.run_str=None |
---|
54 | cls.run=f |
---|
55 | cls.vars=list(set(cls.vars+dvars)) |
---|
56 | cls.vars.sort() |
---|
57 | elif getattr(cls,'run',None)and not'hcode'in cls.__dict__: |
---|
58 | cls.hcode=Utils.h_fun(cls.run) |
---|
59 | if sys.hexversion>0x3000000: |
---|
60 | cls.hcode=cls.hcode.encode('iso8859-1','xmlcharrefreplace') |
---|
61 | getattr(cls,'register',classes)[name]=cls |
---|
62 | evil=store_task_type('evil',(object,),{}) |
---|
63 | class TaskBase(evil): |
---|
64 | color='GREEN' |
---|
65 | ext_in=[] |
---|
66 | ext_out=[] |
---|
67 | before=[] |
---|
68 | after=[] |
---|
69 | hcode='' |
---|
70 | def __init__(self,*k,**kw): |
---|
71 | self.hasrun=NOT_RUN |
---|
72 | try: |
---|
73 | self.generator=kw['generator'] |
---|
74 | except KeyError: |
---|
75 | self.generator=self |
---|
76 | def __repr__(self): |
---|
77 | return'\n\t{task %r: %s %s}'%(self.__class__.__name__,id(self),str(getattr(self,'fun',''))) |
---|
78 | def __str__(self): |
---|
79 | if hasattr(self,'fun'): |
---|
80 | return self.fun.__name__ |
---|
81 | return self.__class__.__name__ |
---|
82 | def __hash__(self): |
---|
83 | return id(self) |
---|
84 | def keyword(self): |
---|
85 | if hasattr(self,'fun'): |
---|
86 | return'Function' |
---|
87 | return'Processing' |
---|
88 | def exec_command(self,cmd,**kw): |
---|
89 | bld=self.generator.bld |
---|
90 | try: |
---|
91 | if not kw.get('cwd',None): |
---|
92 | kw['cwd']=bld.cwd |
---|
93 | except AttributeError: |
---|
94 | bld.cwd=kw['cwd']=bld.variant_dir |
---|
95 | return bld.exec_command(cmd,**kw) |
---|
96 | def runnable_status(self): |
---|
97 | return RUN_ME |
---|
98 | def process(self): |
---|
99 | m=self.master |
---|
100 | if m.stop: |
---|
101 | m.out.put(self) |
---|
102 | return |
---|
103 | try: |
---|
104 | del self.generator.bld.task_sigs[self.uid()] |
---|
105 | except KeyError: |
---|
106 | pass |
---|
107 | try: |
---|
108 | self.generator.bld.returned_tasks.append(self) |
---|
109 | self.log_display(self.generator.bld) |
---|
110 | ret=self.run() |
---|
111 | except Exception: |
---|
112 | self.err_msg=Utils.ex_stack() |
---|
113 | self.hasrun=EXCEPTION |
---|
114 | m.error_handler(self) |
---|
115 | m.out.put(self) |
---|
116 | return |
---|
117 | if ret: |
---|
118 | self.err_code=ret |
---|
119 | self.hasrun=CRASHED |
---|
120 | else: |
---|
121 | try: |
---|
122 | self.post_run() |
---|
123 | except Errors.WafError: |
---|
124 | pass |
---|
125 | except Exception: |
---|
126 | self.err_msg=Utils.ex_stack() |
---|
127 | self.hasrun=EXCEPTION |
---|
128 | else: |
---|
129 | self.hasrun=SUCCESS |
---|
130 | if self.hasrun!=SUCCESS: |
---|
131 | m.error_handler(self) |
---|
132 | m.out.put(self) |
---|
133 | def run(self): |
---|
134 | if hasattr(self,'fun'): |
---|
135 | return self.fun(self) |
---|
136 | return 0 |
---|
137 | def post_run(self): |
---|
138 | pass |
---|
139 | def log_display(self,bld): |
---|
140 | if self.generator.bld.progress_bar==3: |
---|
141 | return |
---|
142 | s=self.display() |
---|
143 | if s: |
---|
144 | if bld.logger: |
---|
145 | logger=bld.logger |
---|
146 | else: |
---|
147 | logger=Logs |
---|
148 | if self.generator.bld.progress_bar==1: |
---|
149 | c1=Logs.colors.cursor_off |
---|
150 | c2=Logs.colors.cursor_on |
---|
151 | logger.info(s,extra={'stream':sys.stderr,'terminator':'','c1':c1,'c2':c2}) |
---|
152 | else: |
---|
153 | logger.info(s,extra={'terminator':'','c1':'','c2':''}) |
---|
154 | def display(self): |
---|
155 | col1=Logs.colors(self.color) |
---|
156 | col2=Logs.colors.NORMAL |
---|
157 | master=self.master |
---|
158 | def cur(): |
---|
159 | tmp=-1 |
---|
160 | if hasattr(master,'ready'): |
---|
161 | tmp-=master.ready.qsize() |
---|
162 | return master.processed+tmp |
---|
163 | if self.generator.bld.progress_bar==1: |
---|
164 | return self.generator.bld.progress_line(cur(),master.total,col1,col2) |
---|
165 | if self.generator.bld.progress_bar==2: |
---|
166 | ela=str(self.generator.bld.timer) |
---|
167 | try: |
---|
168 | ins=','.join([n.name for n in self.inputs]) |
---|
169 | except AttributeError: |
---|
170 | ins='' |
---|
171 | try: |
---|
172 | outs=','.join([n.name for n in self.outputs]) |
---|
173 | except AttributeError: |
---|
174 | outs='' |
---|
175 | return'|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n'%(master.total,cur(),ins,outs,ela) |
---|
176 | s=str(self) |
---|
177 | if not s: |
---|
178 | return None |
---|
179 | total=master.total |
---|
180 | n=len(str(total)) |
---|
181 | fs='[%%%dd/%%%dd] %%s%%s%%s%%s\n'%(n,n) |
---|
182 | kw=self.keyword() |
---|
183 | if kw: |
---|
184 | kw+=' ' |
---|
185 | return fs%(cur(),total,kw,col1,s,col2) |
---|
186 | def attr(self,att,default=None): |
---|
187 | ret=getattr(self,att,self) |
---|
188 | if ret is self:return getattr(self.__class__,att,default) |
---|
189 | return ret |
---|
190 | def hash_constraints(self): |
---|
191 | cls=self.__class__ |
---|
192 | tup=(str(cls.before),str(cls.after),str(cls.ext_in),str(cls.ext_out),cls.__name__,cls.hcode) |
---|
193 | h=hash(tup) |
---|
194 | return h |
---|
195 | def format_error(self): |
---|
196 | msg=getattr(self,'last_cmd','') |
---|
197 | name=getattr(self.generator,'name','') |
---|
198 | if getattr(self,"err_msg",None): |
---|
199 | return self.err_msg |
---|
200 | elif not self.hasrun: |
---|
201 | return'task in %r was not executed for some reason: %r'%(name,self) |
---|
202 | elif self.hasrun==CRASHED: |
---|
203 | try: |
---|
204 | return' -> task in %r failed (exit status %r): %r\n%r'%(name,self.err_code,self,msg) |
---|
205 | except AttributeError: |
---|
206 | return' -> task in %r failed: %r\n%r'%(name,self,msg) |
---|
207 | elif self.hasrun==MISSING: |
---|
208 | return' -> missing files in %r: %r\n%r'%(name,self,msg) |
---|
209 | else: |
---|
210 | return'invalid status for task in %r: %r'%(name,self.hasrun) |
---|
211 | def colon(self,var1,var2): |
---|
212 | tmp=self.env[var1] |
---|
213 | if not tmp: |
---|
214 | return[] |
---|
215 | if isinstance(var2,str): |
---|
216 | it=self.env[var2] |
---|
217 | else: |
---|
218 | it=var2 |
---|
219 | if isinstance(tmp,str): |
---|
220 | return[tmp%x for x in it] |
---|
221 | else: |
---|
222 | lst=[] |
---|
223 | for y in it: |
---|
224 | lst.extend(tmp) |
---|
225 | lst.append(y) |
---|
226 | return lst |
---|
227 | class Task(TaskBase): |
---|
228 | vars=[] |
---|
229 | shell=False |
---|
230 | def __init__(self,*k,**kw): |
---|
231 | TaskBase.__init__(self,*k,**kw) |
---|
232 | self.env=kw['env'] |
---|
233 | self.inputs=[] |
---|
234 | self.outputs=[] |
---|
235 | self.dep_nodes=[] |
---|
236 | self.run_after=set([]) |
---|
237 | def __str__(self): |
---|
238 | name=self.__class__.__name__ |
---|
239 | if self.outputs: |
---|
240 | if(name.endswith('lib')or name.endswith('program'))or not self.inputs: |
---|
241 | node=self.outputs[0] |
---|
242 | return node.path_from(node.ctx.launch_node()) |
---|
243 | if not(self.inputs or self.outputs): |
---|
244 | return self.__class__.__name__ |
---|
245 | if len(self.inputs)==1: |
---|
246 | node=self.inputs[0] |
---|
247 | return node.path_from(node.ctx.launch_node()) |
---|
248 | src_str=' '.join([a.path_from(a.ctx.launch_node())for a in self.inputs]) |
---|
249 | tgt_str=' '.join([a.path_from(a.ctx.launch_node())for a in self.outputs]) |
---|
250 | if self.outputs:sep=' -> ' |
---|
251 | else:sep='' |
---|
252 | return'%s: %s%s%s'%(self.__class__.__name__.replace('_task',''),src_str,sep,tgt_str) |
---|
253 | def keyword(self): |
---|
254 | name=self.__class__.__name__ |
---|
255 | if name.endswith('lib')or name.endswith('program'): |
---|
256 | return'Linking' |
---|
257 | if len(self.inputs)==1 and len(self.outputs)==1: |
---|
258 | return'Compiling' |
---|
259 | if not self.inputs: |
---|
260 | if self.outputs: |
---|
261 | return'Creating' |
---|
262 | else: |
---|
263 | return'Running' |
---|
264 | return'Processing' |
---|
265 | def __repr__(self): |
---|
266 | try: |
---|
267 | ins=",".join([x.name for x in self.inputs]) |
---|
268 | outs=",".join([x.name for x in self.outputs]) |
---|
269 | except AttributeError: |
---|
270 | ins=",".join([str(x)for x in self.inputs]) |
---|
271 | outs=",".join([str(x)for x in self.outputs]) |
---|
272 | return"".join(['\n\t{task %r: '%id(self),self.__class__.__name__," ",ins," -> ",outs,'}']) |
---|
273 | def uid(self): |
---|
274 | try: |
---|
275 | return self.uid_ |
---|
276 | except AttributeError: |
---|
277 | m=Utils.md5() |
---|
278 | up=m.update |
---|
279 | up(self.__class__.__name__) |
---|
280 | for x in self.inputs+self.outputs: |
---|
281 | up(x.abspath()) |
---|
282 | self.uid_=m.digest() |
---|
283 | return self.uid_ |
---|
284 | def set_inputs(self,inp): |
---|
285 | if isinstance(inp,list):self.inputs+=inp |
---|
286 | else:self.inputs.append(inp) |
---|
287 | def set_outputs(self,out): |
---|
288 | if isinstance(out,list):self.outputs+=out |
---|
289 | else:self.outputs.append(out) |
---|
290 | def set_run_after(self,task): |
---|
291 | assert isinstance(task,TaskBase) |
---|
292 | self.run_after.add(task) |
---|
293 | def signature(self): |
---|
294 | try:return self.cache_sig |
---|
295 | except AttributeError:pass |
---|
296 | self.m=Utils.md5() |
---|
297 | self.m.update(self.hcode) |
---|
298 | self.sig_explicit_deps() |
---|
299 | self.sig_vars() |
---|
300 | if self.scan: |
---|
301 | try: |
---|
302 | self.sig_implicit_deps() |
---|
303 | except Errors.TaskRescan: |
---|
304 | return self.signature() |
---|
305 | ret=self.cache_sig=self.m.digest() |
---|
306 | return ret |
---|
307 | def runnable_status(self): |
---|
308 | for t in self.run_after: |
---|
309 | if not t.hasrun: |
---|
310 | return ASK_LATER |
---|
311 | bld=self.generator.bld |
---|
312 | try: |
---|
313 | new_sig=self.signature() |
---|
314 | except Errors.TaskNotReady: |
---|
315 | return ASK_LATER |
---|
316 | key=self.uid() |
---|
317 | try: |
---|
318 | prev_sig=bld.task_sigs[key] |
---|
319 | except KeyError: |
---|
320 | Logs.debug("task: task %r must run as it was never run before or the task code changed"%self) |
---|
321 | return RUN_ME |
---|
322 | for node in self.outputs: |
---|
323 | try: |
---|
324 | if node.sig!=new_sig: |
---|
325 | return RUN_ME |
---|
326 | except AttributeError: |
---|
327 | Logs.debug("task: task %r must run as the output nodes do not exist"%self) |
---|
328 | return RUN_ME |
---|
329 | if new_sig!=prev_sig: |
---|
330 | return RUN_ME |
---|
331 | return SKIP_ME |
---|
332 | def post_run(self): |
---|
333 | bld=self.generator.bld |
---|
334 | sig=self.signature() |
---|
335 | for node in self.outputs: |
---|
336 | try: |
---|
337 | os.stat(node.abspath()) |
---|
338 | except OSError: |
---|
339 | self.hasrun=MISSING |
---|
340 | self.err_msg='-> missing file: %r'%node.abspath() |
---|
341 | raise Errors.WafError(self.err_msg) |
---|
342 | node.sig=sig |
---|
343 | bld.task_sigs[self.uid()]=self.cache_sig |
---|
344 | def sig_explicit_deps(self): |
---|
345 | bld=self.generator.bld |
---|
346 | upd=self.m.update |
---|
347 | for x in self.inputs+self.dep_nodes: |
---|
348 | try: |
---|
349 | upd(x.get_bld_sig()) |
---|
350 | except(AttributeError,TypeError): |
---|
351 | raise Errors.WafError('Missing node signature for %r (required by %r)'%(x,self)) |
---|
352 | if bld.deps_man: |
---|
353 | additional_deps=bld.deps_man |
---|
354 | for x in self.inputs+self.outputs: |
---|
355 | try: |
---|
356 | d=additional_deps[id(x)] |
---|
357 | except KeyError: |
---|
358 | continue |
---|
359 | for v in d: |
---|
360 | if isinstance(v,bld.root.__class__): |
---|
361 | try: |
---|
362 | v=v.get_bld_sig() |
---|
363 | except AttributeError: |
---|
364 | raise Errors.WafError('Missing node signature for %r (required by %r)'%(v,self)) |
---|
365 | elif hasattr(v,'__call__'): |
---|
366 | v=v() |
---|
367 | upd(v) |
---|
368 | return self.m.digest() |
---|
369 | def sig_vars(self): |
---|
370 | bld=self.generator.bld |
---|
371 | env=self.env |
---|
372 | upd=self.m.update |
---|
373 | act_sig=bld.hash_env_vars(env,self.__class__.vars) |
---|
374 | upd(act_sig) |
---|
375 | dep_vars=getattr(self,'dep_vars',None) |
---|
376 | if dep_vars: |
---|
377 | upd(bld.hash_env_vars(env,dep_vars)) |
---|
378 | return self.m.digest() |
---|
379 | scan=None |
---|
380 | def sig_implicit_deps(self): |
---|
381 | bld=self.generator.bld |
---|
382 | key=self.uid() |
---|
383 | prev=bld.task_sigs.get((key,'imp'),[]) |
---|
384 | if prev: |
---|
385 | try: |
---|
386 | if prev==self.compute_sig_implicit_deps(): |
---|
387 | return prev |
---|
388 | except Errors.TaskNotReady: |
---|
389 | raise |
---|
390 | except EnvironmentError: |
---|
391 | for x in bld.node_deps.get(self.uid(),[]): |
---|
392 | if not x.is_bld(): |
---|
393 | try: |
---|
394 | os.stat(x.abspath()) |
---|
395 | except OSError: |
---|
396 | try: |
---|
397 | del x.parent.children[x.name] |
---|
398 | except KeyError: |
---|
399 | pass |
---|
400 | del bld.task_sigs[(key,'imp')] |
---|
401 | raise Errors.TaskRescan('rescan') |
---|
402 | (nodes,names)=self.scan() |
---|
403 | if Logs.verbose: |
---|
404 | Logs.debug('deps: scanner for %s returned %s %s'%(str(self),str(nodes),str(names))) |
---|
405 | bld.node_deps[key]=nodes |
---|
406 | bld.raw_deps[key]=names |
---|
407 | self.are_implicit_nodes_ready() |
---|
408 | try: |
---|
409 | bld.task_sigs[(key,'imp')]=sig=self.compute_sig_implicit_deps() |
---|
410 | except Exception: |
---|
411 | if Logs.verbose: |
---|
412 | for k in bld.node_deps.get(self.uid(),[]): |
---|
413 | try: |
---|
414 | k.get_bld_sig() |
---|
415 | except Exception: |
---|
416 | Logs.warn('Missing signature for node %r (may cause rebuilds)'%k) |
---|
417 | else: |
---|
418 | return sig |
---|
419 | def compute_sig_implicit_deps(self): |
---|
420 | upd=self.m.update |
---|
421 | bld=self.generator.bld |
---|
422 | self.are_implicit_nodes_ready() |
---|
423 | for k in bld.node_deps.get(self.uid(),[]): |
---|
424 | upd(k.get_bld_sig()) |
---|
425 | return self.m.digest() |
---|
426 | def are_implicit_nodes_ready(self): |
---|
427 | bld=self.generator.bld |
---|
428 | try: |
---|
429 | cache=bld.dct_implicit_nodes |
---|
430 | except AttributeError: |
---|
431 | bld.dct_implicit_nodes=cache={} |
---|
432 | try: |
---|
433 | dct=cache[bld.cur] |
---|
434 | except KeyError: |
---|
435 | dct=cache[bld.cur]={} |
---|
436 | for tsk in bld.cur_tasks: |
---|
437 | for x in tsk.outputs: |
---|
438 | dct[x]=tsk |
---|
439 | modified=False |
---|
440 | for x in bld.node_deps.get(self.uid(),[]): |
---|
441 | if x in dct: |
---|
442 | self.run_after.add(dct[x]) |
---|
443 | modified=True |
---|
444 | if modified: |
---|
445 | for tsk in self.run_after: |
---|
446 | if not tsk.hasrun: |
---|
447 | raise Errors.TaskNotReady('not ready') |
---|
448 | if sys.hexversion>0x3000000: |
---|
449 | def uid(self): |
---|
450 | try: |
---|
451 | return self.uid_ |
---|
452 | except AttributeError: |
---|
453 | m=Utils.md5() |
---|
454 | up=m.update |
---|
455 | up(self.__class__.__name__.encode('iso8859-1','xmlcharrefreplace')) |
---|
456 | for x in self.inputs+self.outputs: |
---|
457 | up(x.abspath().encode('iso8859-1','xmlcharrefreplace')) |
---|
458 | self.uid_=m.digest() |
---|
459 | return self.uid_ |
---|
460 | uid.__doc__=Task.uid.__doc__ |
---|
461 | Task.uid=uid |
---|
462 | def is_before(t1,t2): |
---|
463 | to_list=Utils.to_list |
---|
464 | for k in to_list(t2.ext_in): |
---|
465 | if k in to_list(t1.ext_out): |
---|
466 | return 1 |
---|
467 | if t1.__class__.__name__ in to_list(t2.after): |
---|
468 | return 1 |
---|
469 | if t2.__class__.__name__ in to_list(t1.before): |
---|
470 | return 1 |
---|
471 | return 0 |
---|
472 | def set_file_constraints(tasks): |
---|
473 | ins=Utils.defaultdict(set) |
---|
474 | outs=Utils.defaultdict(set) |
---|
475 | for x in tasks: |
---|
476 | for a in getattr(x,'inputs',[])+getattr(x,'dep_nodes',[]): |
---|
477 | ins[id(a)].add(x) |
---|
478 | for a in getattr(x,'outputs',[]): |
---|
479 | outs[id(a)].add(x) |
---|
480 | links=set(ins.keys()).intersection(outs.keys()) |
---|
481 | for k in links: |
---|
482 | for a in ins[k]: |
---|
483 | a.run_after.update(outs[k]) |
---|
484 | def set_precedence_constraints(tasks): |
---|
485 | cstr_groups=Utils.defaultdict(list) |
---|
486 | for x in tasks: |
---|
487 | h=x.hash_constraints() |
---|
488 | cstr_groups[h].append(x) |
---|
489 | keys=list(cstr_groups.keys()) |
---|
490 | maxi=len(keys) |
---|
491 | for i in range(maxi): |
---|
492 | t1=cstr_groups[keys[i]][0] |
---|
493 | for j in range(i+1,maxi): |
---|
494 | t2=cstr_groups[keys[j]][0] |
---|
495 | if is_before(t1,t2): |
---|
496 | a=i |
---|
497 | b=j |
---|
498 | elif is_before(t2,t1): |
---|
499 | a=j |
---|
500 | b=i |
---|
501 | else: |
---|
502 | continue |
---|
503 | aval=set(cstr_groups[keys[a]]) |
---|
504 | for x in cstr_groups[keys[b]]: |
---|
505 | x.run_after.update(aval) |
---|
506 | def funex(c): |
---|
507 | dc={} |
---|
508 | exec(c,dc) |
---|
509 | return dc['f'] |
---|
510 | reg_act=re.compile(r"(?P<backslash>\\)|(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})",re.M) |
---|
511 | def compile_fun_shell(line): |
---|
512 | extr=[] |
---|
513 | def repl(match): |
---|
514 | g=match.group |
---|
515 | if g('dollar'):return"$" |
---|
516 | elif g('backslash'):return'\\\\' |
---|
517 | elif g('subst'):extr.append((g('var'),g('code')));return"%s" |
---|
518 | return None |
---|
519 | line=reg_act.sub(repl,line)or line |
---|
520 | parm=[] |
---|
521 | dvars=[] |
---|
522 | app=parm.append |
---|
523 | for(var,meth)in extr: |
---|
524 | if var=='SRC': |
---|
525 | if meth:app('tsk.inputs%s'%meth) |
---|
526 | else:app('" ".join([a.path_from(bld.bldnode) for a in tsk.inputs])') |
---|
527 | elif var=='TGT': |
---|
528 | if meth:app('tsk.outputs%s'%meth) |
---|
529 | else:app('" ".join([a.path_from(bld.bldnode) for a in tsk.outputs])') |
---|
530 | elif meth: |
---|
531 | if meth.startswith(':'): |
---|
532 | m=meth[1:] |
---|
533 | if m=='SRC': |
---|
534 | m='[a.path_from(bld.bldnode) for a in tsk.inputs]' |
---|
535 | elif m=='TGT': |
---|
536 | m='[a.path_from(bld.bldnode) for a in tsk.outputs]' |
---|
537 | elif m[:3]not in('tsk','gen','bld'): |
---|
538 | dvars.extend([var,meth[1:]]) |
---|
539 | m='%r'%m |
---|
540 | app('" ".join(tsk.colon(%r, %s))'%(var,m)) |
---|
541 | else: |
---|
542 | app('%s%s'%(var,meth)) |
---|
543 | else: |
---|
544 | if not var in dvars:dvars.append(var) |
---|
545 | app("p('%s')"%var) |
---|
546 | if parm:parm="%% (%s) "%(',\n\t\t'.join(parm)) |
---|
547 | else:parm='' |
---|
548 | c=COMPILE_TEMPLATE_SHELL%(line,parm) |
---|
549 | Logs.debug('action: %s'%c.strip().splitlines()) |
---|
550 | return(funex(c),dvars) |
---|
551 | def compile_fun_noshell(line): |
---|
552 | extr=[] |
---|
553 | def repl(match): |
---|
554 | g=match.group |
---|
555 | if g('dollar'):return"$" |
---|
556 | elif g('backslash'):return'\\' |
---|
557 | elif g('subst'):extr.append((g('var'),g('code')));return"<<|@|>>" |
---|
558 | return None |
---|
559 | line2=reg_act.sub(repl,line) |
---|
560 | params=line2.split('<<|@|>>') |
---|
561 | assert(extr) |
---|
562 | buf=[] |
---|
563 | dvars=[] |
---|
564 | app=buf.append |
---|
565 | for x in range(len(extr)): |
---|
566 | params[x]=params[x].strip() |
---|
567 | if params[x]: |
---|
568 | app("lst.extend(%r)"%params[x].split()) |
---|
569 | (var,meth)=extr[x] |
---|
570 | if var=='SRC': |
---|
571 | if meth:app('lst.append(tsk.inputs%s)'%meth) |
---|
572 | else:app("lst.extend([a.path_from(bld.bldnode) for a in tsk.inputs])") |
---|
573 | elif var=='TGT': |
---|
574 | if meth:app('lst.append(tsk.outputs%s)'%meth) |
---|
575 | else:app("lst.extend([a.path_from(bld.bldnode) for a in tsk.outputs])") |
---|
576 | elif meth: |
---|
577 | if meth.startswith(':'): |
---|
578 | m=meth[1:] |
---|
579 | if m=='SRC': |
---|
580 | m='[a.path_from(bld.bldnode) for a in tsk.inputs]' |
---|
581 | elif m=='TGT': |
---|
582 | m='[a.path_from(bld.bldnode) for a in tsk.outputs]' |
---|
583 | elif m[:3]not in('tsk','gen','bld'): |
---|
584 | dvars.extend([var,m]) |
---|
585 | m='%r'%m |
---|
586 | app('lst.extend(tsk.colon(%r, %s))'%(var,m)) |
---|
587 | else: |
---|
588 | app('lst.extend(gen.to_list(%s%s))'%(var,meth)) |
---|
589 | else: |
---|
590 | app('lst.extend(to_list(env[%r]))'%var) |
---|
591 | if not var in dvars:dvars.append(var) |
---|
592 | if extr: |
---|
593 | if params[-1]: |
---|
594 | app("lst.extend(%r)"%params[-1].split()) |
---|
595 | fun=COMPILE_TEMPLATE_NOSHELL%"\n\t".join(buf) |
---|
596 | Logs.debug('action: %s'%fun.strip().splitlines()) |
---|
597 | return(funex(fun),dvars) |
---|
598 | def compile_fun(line,shell=False): |
---|
599 | if line.find('<')>0 or line.find('>')>0 or line.find('&&')>0: |
---|
600 | shell=True |
---|
601 | if shell: |
---|
602 | return compile_fun_shell(line) |
---|
603 | else: |
---|
604 | return compile_fun_noshell(line) |
---|
605 | def task_factory(name,func=None,vars=None,color='GREEN',ext_in=[],ext_out=[],before=[],after=[],shell=False,scan=None): |
---|
606 | 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,} |
---|
607 | if isinstance(func,str): |
---|
608 | params['run_str']=func |
---|
609 | else: |
---|
610 | params['run']=func |
---|
611 | cls=type(Task)(name,(Task,),params) |
---|
612 | global classes |
---|
613 | classes[name]=cls |
---|
614 | return cls |
---|
615 | def always_run(cls): |
---|
616 | old=cls.runnable_status |
---|
617 | def always(self): |
---|
618 | ret=old(self) |
---|
619 | if ret==SKIP_ME: |
---|
620 | ret=RUN_ME |
---|
621 | return ret |
---|
622 | cls.runnable_status=always |
---|
623 | return cls |
---|
624 | def update_outputs(cls): |
---|
625 | old_post_run=cls.post_run |
---|
626 | def post_run(self): |
---|
627 | old_post_run(self) |
---|
628 | for node in self.outputs: |
---|
629 | node.sig=Utils.h_file(node.abspath()) |
---|
630 | self.generator.bld.task_sigs[node.abspath()]=self.uid() |
---|
631 | cls.post_run=post_run |
---|
632 | old_runnable_status=cls.runnable_status |
---|
633 | def runnable_status(self): |
---|
634 | status=old_runnable_status(self) |
---|
635 | if status!=RUN_ME: |
---|
636 | return status |
---|
637 | try: |
---|
638 | bld=self.generator.bld |
---|
639 | prev_sig=bld.task_sigs[self.uid()] |
---|
640 | if prev_sig==self.signature(): |
---|
641 | for x in self.outputs: |
---|
642 | if not x.is_child_of(bld.bldnode): |
---|
643 | x.sig=Utils.h_file(x.abspath()) |
---|
644 | if not x.sig or bld.task_sigs[x.abspath()]!=self.uid(): |
---|
645 | return RUN_ME |
---|
646 | return SKIP_ME |
---|
647 | except OSError: |
---|
648 | pass |
---|
649 | except IOError: |
---|
650 | pass |
---|
651 | except KeyError: |
---|
652 | pass |
---|
653 | except IndexError: |
---|
654 | pass |
---|
655 | except AttributeError: |
---|
656 | pass |
---|
657 | return RUN_ME |
---|
658 | cls.runnable_status=runnable_status |
---|
659 | return cls |
---|