akmhoque | fa8ee9b | 2014-03-14 09:06:24 -0500 | [diff] [blame^] | 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 |