[0fa325b] | 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: |
---|
[1a31baf] | 666 | if not x.is_child_of(bld.bldnode): |
---|
| 667 | x.sig=Utils.h_file(x.abspath()) |
---|
[0fa325b] | 668 | if not x.sig or bld.task_sigs[x.abspath()]!=self.uid(): |
---|
| 669 | return RUN_ME |
---|
| 670 | return SKIP_ME |
---|
[1a31baf] | 671 | except OSError: |
---|
| 672 | pass |
---|
| 673 | except IOError: |
---|
| 674 | pass |
---|
[0fa325b] | 675 | except KeyError: |
---|
| 676 | pass |
---|
| 677 | except IndexError: |
---|
| 678 | pass |
---|
| 679 | except AttributeError: |
---|
| 680 | pass |
---|
| 681 | return RUN_ME |
---|
| 682 | cls.runnable_status=runnable_status |
---|
| 683 | return cls |
---|