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