1#! /usr/bin/env python 2# encoding: utf-8 3# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file 4 5from __future__ import with_statement 6import atexit,os,sys,errno,inspect,re,datetime,platform,base64,signal,functools,time 7try: 8 import cPickle 9except ImportError: 10 import pickle as cPickle 11if os.name=='posix'and sys.version_info[0]<3: 12 try: 13 import subprocess32 as subprocess 14 except ImportError: 15 import subprocess 16else: 17 import subprocess 18try: 19 TimeoutExpired=subprocess.TimeoutExpired 20except AttributeError: 21 class TimeoutExpired(Exception): 22 pass 23from collections import deque,defaultdict 24try: 25 import _winreg as winreg 26except ImportError: 27 try: 28 import winreg 29 except ImportError: 30 winreg=None 31from waflib import Errors 32try: 33 from hashlib import md5 34except ImportError: 35 try: 36 from hashlib import sha1 as md5 37 except ImportError: 38 pass 39else: 40 try: 41 md5().digest() 42 except ValueError: 43 from hashlib import sha1 as md5 44try: 45 import threading 46except ImportError: 47 if not'JOBS'in os.environ: 48 os.environ['JOBS']='1' 49 class threading(object): 50 pass 51 class Lock(object): 52 def acquire(self): 53 pass 54 def release(self): 55 pass 56 threading.Lock=threading.Thread=Lock 57SIG_NIL='SIG_NIL_SIG_NIL_'.encode() 58O644=420 59O755=493 60rot_chr=['\\','|','/','-'] 61rot_idx=0 62class ordered_iter_dict(dict): 63 def __init__(self,*k,**kw): 64 self.lst=deque() 65 dict.__init__(self,*k,**kw) 66 def clear(self): 67 dict.clear(self) 68 self.lst=deque() 69 def __setitem__(self,key,value): 70 if key in dict.keys(self): 71 self.lst.remove(key) 72 dict.__setitem__(self,key,value) 73 self.lst.append(key) 74 def __delitem__(self,key): 75 dict.__delitem__(self,key) 76 try: 77 self.lst.remove(key) 78 except ValueError: 79 pass 80 def __iter__(self): 81 return reversed(self.lst) 82 def keys(self): 83 return reversed(self.lst) 84class lru_node(object): 85 __slots__=('next','prev','key','val') 86 def __init__(self): 87 self.next=self 88 self.prev=self 89 self.key=None 90 self.val=None 91class lru_cache(object): 92 __slots__=('maxlen','table','head') 93 def __init__(self,maxlen=100): 94 self.maxlen=maxlen 95 self.table={} 96 self.head=lru_node() 97 self.head.next=self.head 98 self.head.prev=self.head 99 def __getitem__(self,key): 100 node=self.table[key] 101 if node is self.head: 102 return node.val 103 node.prev.next=node.next 104 node.next.prev=node.prev 105 node.next=self.head.next 106 node.prev=self.head 107 self.head=node.next.prev=node.prev.next=node 108 return node.val 109 def __setitem__(self,key,val): 110 if key in self.table: 111 node=self.table[key] 112 node.val=val 113 self.__getitem__(key) 114 else: 115 if len(self.table)<self.maxlen: 116 node=lru_node() 117 node.prev=self.head 118 node.next=self.head.next 119 node.prev.next=node.next.prev=node 120 else: 121 node=self.head=self.head.next 122 try: 123 del self.table[node.key] 124 except KeyError: 125 pass 126 node.key=key 127 node.val=val 128 self.table[key]=node 129class lazy_generator(object): 130 def __init__(self,fun,params): 131 self.fun=fun 132 self.params=params 133 def __iter__(self): 134 return self 135 def __next__(self): 136 try: 137 it=self.it 138 except AttributeError: 139 it=self.it=self.fun(*self.params) 140 return next(it) 141 next=__next__ 142is_win32=os.sep=='\\'or sys.platform=='win32'or os.name=='nt' 143def readf(fname,m='r',encoding='latin-1'): 144 if sys.hexversion>0x3000000 and not'b'in m: 145 m+='b' 146 with open(fname,m)as f: 147 txt=f.read() 148 if encoding: 149 txt=txt.decode(encoding) 150 else: 151 txt=txt.decode() 152 else: 153 with open(fname,m)as f: 154 txt=f.read() 155 return txt 156def writef(fname,data,m='w',encoding='latin-1'): 157 if sys.hexversion>0x3000000 and not'b'in m: 158 data=data.encode(encoding) 159 m+='b' 160 with open(fname,m)as f: 161 f.write(data) 162def h_file(fname): 163 m=md5() 164 with open(fname,'rb')as f: 165 while fname: 166 fname=f.read(200000) 167 m.update(fname) 168 return m.digest() 169def readf_win32(f,m='r',encoding='latin-1'): 170 flags=os.O_NOINHERIT|os.O_RDONLY 171 if'b'in m: 172 flags|=os.O_BINARY 173 if'+'in m: 174 flags|=os.O_RDWR 175 try: 176 fd=os.open(f,flags) 177 except OSError: 178 raise IOError('Cannot read from %r'%f) 179 if sys.hexversion>0x3000000 and not'b'in m: 180 m+='b' 181 with os.fdopen(fd,m)as f: 182 txt=f.read() 183 if encoding: 184 txt=txt.decode(encoding) 185 else: 186 txt=txt.decode() 187 else: 188 with os.fdopen(fd,m)as f: 189 txt=f.read() 190 return txt 191def writef_win32(f,data,m='w',encoding='latin-1'): 192 if sys.hexversion>0x3000000 and not'b'in m: 193 data=data.encode(encoding) 194 m+='b' 195 flags=os.O_CREAT|os.O_TRUNC|os.O_WRONLY|os.O_NOINHERIT 196 if'b'in m: 197 flags|=os.O_BINARY 198 if'+'in m: 199 flags|=os.O_RDWR 200 try: 201 fd=os.open(f,flags) 202 except OSError: 203 raise OSError('Cannot write to %r'%f) 204 with os.fdopen(fd,m)as f: 205 f.write(data) 206def h_file_win32(fname): 207 try: 208 fd=os.open(fname,os.O_BINARY|os.O_RDONLY|os.O_NOINHERIT) 209 except OSError: 210 raise OSError('Cannot read from %r'%fname) 211 m=md5() 212 with os.fdopen(fd,'rb')as f: 213 while fname: 214 fname=f.read(200000) 215 m.update(fname) 216 return m.digest() 217readf_unix=readf 218writef_unix=writef 219h_file_unix=h_file 220if hasattr(os,'O_NOINHERIT')and sys.hexversion<0x3040000: 221 readf=readf_win32 222 writef=writef_win32 223 h_file=h_file_win32 224try: 225 x=''.encode('hex') 226except LookupError: 227 import binascii 228 def to_hex(s): 229 ret=binascii.hexlify(s) 230 if not isinstance(ret,str): 231 ret=ret.decode('utf-8') 232 return ret 233else: 234 def to_hex(s): 235 return s.encode('hex') 236to_hex.__doc__=""" 237Return the hexadecimal representation of a string 238 239:param s: string to convert 240:type s: string 241""" 242def listdir_win32(s): 243 if not s: 244 try: 245 import ctypes 246 except ImportError: 247 return[x+':\\'for x in'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] 248 else: 249 dlen=4 250 maxdrives=26 251 buf=ctypes.create_string_buffer(maxdrives*dlen) 252 ndrives=ctypes.windll.kernel32.GetLogicalDriveStringsA(maxdrives*dlen,ctypes.byref(buf)) 253 return[str(buf.raw[4*i:4*i+2].decode('ascii'))for i in range(int(ndrives/dlen))] 254 if len(s)==2 and s[1]==":": 255 s+=os.sep 256 if not os.path.isdir(s): 257 e=OSError('%s is not a directory'%s) 258 e.errno=errno.ENOENT 259 raise e 260 return os.listdir(s) 261listdir=os.listdir 262if is_win32: 263 listdir=listdir_win32 264def num2ver(ver): 265 if isinstance(ver,str): 266 ver=tuple(ver.split('.')) 267 if isinstance(ver,tuple): 268 ret=0 269 for i in range(4): 270 if i<len(ver): 271 ret+=256**(3-i)*int(ver[i]) 272 return ret 273 return ver 274def to_list(val): 275 if isinstance(val,str): 276 return val.split() 277 else: 278 return val 279def console_encoding(): 280 try: 281 import ctypes 282 except ImportError: 283 pass 284 else: 285 try: 286 codepage=ctypes.windll.kernel32.GetConsoleCP() 287 except AttributeError: 288 pass 289 else: 290 if codepage: 291 return'cp%d'%codepage 292 return sys.stdout.encoding or('cp1252'if is_win32 else'latin-1') 293def split_path_unix(path): 294 return path.split('/') 295def split_path_cygwin(path): 296 if path.startswith('//'): 297 ret=path.split('/')[2:] 298 ret[0]='/'+ret[0] 299 return ret 300 return path.split('/') 301re_sp=re.compile('[/\\\\]+') 302def split_path_win32(path): 303 if path.startswith('\\\\'): 304 ret=re_sp.split(path)[1:] 305 ret[0]='\\\\'+ret[0] 306 if ret[0]=='\\\\?': 307 return ret[1:] 308 return ret 309 return re_sp.split(path) 310msysroot=None 311def split_path_msys(path): 312 if path.startswith(('/','\\'))and not path.startswith(('//','\\\\')): 313 global msysroot 314 if not msysroot: 315 msysroot=subprocess.check_output(['cygpath','-w','/']).decode(sys.stdout.encoding or'latin-1') 316 msysroot=msysroot.strip() 317 path=os.path.normpath(msysroot+os.sep+path) 318 return split_path_win32(path) 319if sys.platform=='cygwin': 320 split_path=split_path_cygwin 321elif is_win32: 322 if os.environ.get('MSYSTEM'): 323 split_path=split_path_msys 324 else: 325 split_path=split_path_win32 326else: 327 split_path=split_path_unix 328split_path.__doc__=""" 329Splits a path by / or \\; do not confuse this function with with ``os.path.split`` 330 331:type path: string 332:param path: path to split 333:return: list of string 334""" 335def check_dir(path): 336 if not os.path.isdir(path): 337 try: 338 os.makedirs(path) 339 except OSError as e: 340 if not os.path.isdir(path): 341 raise Errors.WafError('Cannot create the folder %r'%path,ex=e) 342def check_exe(name,env=None): 343 if not name: 344 raise ValueError('Cannot execute an empty string!') 345 def is_exe(fpath): 346 return os.path.isfile(fpath)and os.access(fpath,os.X_OK) 347 fpath,fname=os.path.split(name) 348 if fpath and is_exe(name): 349 return os.path.abspath(name) 350 else: 351 env=env or os.environ 352 for path in env['PATH'].split(os.pathsep): 353 path=path.strip('"') 354 exe_file=os.path.join(path,name) 355 if is_exe(exe_file): 356 return os.path.abspath(exe_file) 357 return None 358def def_attrs(cls,**kw): 359 for k,v in kw.items(): 360 if not hasattr(cls,k): 361 setattr(cls,k,v) 362def quote_define_name(s): 363 fu=re.sub('[^a-zA-Z0-9]','_',s) 364 fu=re.sub('_+','_',fu) 365 fu=fu.upper() 366 return fu 367re_sh=re.compile('\\s|\'|"') 368def shell_escape(cmd): 369 if isinstance(cmd,str): 370 return cmd 371 return' '.join(repr(x)if re_sh.search(x)else x for x in cmd) 372def h_list(lst): 373 return md5(repr(lst).encode()).digest() 374def h_fun(fun): 375 try: 376 return fun.code 377 except AttributeError: 378 if isinstance(fun,functools.partial): 379 code=list(fun.args) 380 code.extend(sorted(fun.keywords.items())) 381 code.append(h_fun(fun.func)) 382 fun.code=h_list(code) 383 return fun.code 384 try: 385 h=inspect.getsource(fun) 386 except EnvironmentError: 387 h='nocode' 388 try: 389 fun.code=h 390 except AttributeError: 391 pass 392 return h 393def h_cmd(ins): 394 if isinstance(ins,str): 395 ret=ins 396 elif isinstance(ins,list)or isinstance(ins,tuple): 397 ret=str([h_cmd(x)for x in ins]) 398 else: 399 ret=str(h_fun(ins)) 400 if sys.hexversion>0x3000000: 401 ret=ret.encode('latin-1','xmlcharrefreplace') 402 return ret 403reg_subst=re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}") 404def subst_vars(expr,params): 405 def repl_var(m): 406 if m.group(1): 407 return'\\' 408 if m.group(2): 409 return'$' 410 try: 411 return params.get_flat(m.group(3)) 412 except AttributeError: 413 return params[m.group(3)] 414 return reg_subst.sub(repl_var,expr) 415def destos_to_binfmt(key): 416 if key=='darwin': 417 return'mac-o' 418 elif key in('win32','cygwin','uwin','msys'): 419 return'pe' 420 return'elf' 421def unversioned_sys_platform(): 422 s=sys.platform 423 if s.startswith('java'): 424 from java.lang import System 425 s=System.getProperty('os.name') 426 if s=='Mac OS X': 427 return'darwin' 428 elif s.startswith('Windows '): 429 return'win32' 430 elif s=='OS/2': 431 return'os2' 432 elif s=='HP-UX': 433 return'hp-ux' 434 elif s in('SunOS','Solaris'): 435 return'sunos' 436 else:s=s.lower() 437 if s=='powerpc': 438 return'darwin' 439 if s=='win32'or s=='os2': 440 return s 441 if s=='cli'and os.name=='nt': 442 return'win32' 443 return re.split('\d+$',s)[0] 444def nada(*k,**kw): 445 pass 446class Timer(object): 447 def __init__(self): 448 self.start_time=self.now() 449 def __str__(self): 450 delta=self.now()-self.start_time 451 if not isinstance(delta,datetime.timedelta): 452 delta=datetime.timedelta(seconds=delta) 453 days=delta.days 454 hours,rem=divmod(delta.seconds,3600) 455 minutes,seconds=divmod(rem,60) 456 seconds+=delta.microseconds*1e-6 457 result='' 458 if days: 459 result+='%dd'%days 460 if days or hours: 461 result+='%dh'%hours 462 if days or hours or minutes: 463 result+='%dm'%minutes 464 return'%s%.3fs'%(result,seconds) 465 def now(self): 466 return datetime.datetime.utcnow() 467 if hasattr(time,'perf_counter'): 468 def now(self): 469 return time.perf_counter() 470def read_la_file(path): 471 sp=re.compile(r'^([^=]+)=\'(.*)\'$') 472 dc={} 473 for line in readf(path).splitlines(): 474 try: 475 _,left,right,_=sp.split(line.strip()) 476 dc[left]=right 477 except ValueError: 478 pass 479 return dc 480def run_once(fun): 481 cache={} 482 def wrap(*k): 483 try: 484 return cache[k] 485 except KeyError: 486 ret=fun(*k) 487 cache[k]=ret 488 return ret 489 wrap.__cache__=cache 490 wrap.__name__=fun.__name__ 491 return wrap 492def get_registry_app_path(key,filename): 493 if not winreg: 494 return None 495 try: 496 result=winreg.QueryValue(key,"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s.exe"%filename[0]) 497 except OSError: 498 pass 499 else: 500 if os.path.isfile(result): 501 return result 502def lib64(): 503 if os.sep=='/': 504 if platform.architecture()[0]=='64bit': 505 if os.path.exists('/usr/lib64')and not os.path.exists('/usr/lib32'): 506 return'64' 507 return'' 508def sane_path(p): 509 return os.path.abspath(os.path.expanduser(p)) 510process_pool=[] 511def get_process(): 512 try: 513 return process_pool.pop() 514 except IndexError: 515 filepath=os.path.dirname(os.path.abspath(__file__))+os.sep+'processor.py' 516 cmd=[sys.executable,'-c',readf(filepath)] 517 return subprocess.Popen(cmd,stdout=subprocess.PIPE,stdin=subprocess.PIPE,bufsize=0) 518def run_prefork_process(cmd,kwargs,cargs): 519 if not'env'in kwargs: 520 kwargs['env']=dict(os.environ) 521 try: 522 obj=base64.b64encode(cPickle.dumps([cmd,kwargs,cargs])) 523 except(TypeError,AttributeError): 524 return run_regular_process(cmd,kwargs,cargs) 525 proc=get_process() 526 if not proc: 527 return run_regular_process(cmd,kwargs,cargs) 528 proc.stdin.write(obj) 529 proc.stdin.write('\n'.encode()) 530 proc.stdin.flush() 531 obj=proc.stdout.readline() 532 if not obj: 533 raise OSError('Preforked sub-process %r died'%proc.pid) 534 process_pool.append(proc) 535 lst=cPickle.loads(base64.b64decode(obj)) 536 assert len(lst)==5 537 ret,out,err,ex,trace=lst 538 if ex: 539 if ex=='OSError': 540 raise OSError(trace) 541 elif ex=='ValueError': 542 raise ValueError(trace) 543 elif ex=='TimeoutExpired': 544 exc=TimeoutExpired(cmd,timeout=cargs['timeout'],output=out) 545 exc.stderr=err 546 raise exc 547 else: 548 raise Exception(trace) 549 return ret,out,err 550def lchown(path,user=-1,group=-1): 551 if isinstance(user,str): 552 import pwd 553 entry=pwd.getpwnam(user) 554 if not entry: 555 raise OSError('Unknown user %r'%user) 556 user=entry[2] 557 if isinstance(group,str): 558 import grp 559 entry=grp.getgrnam(group) 560 if not entry: 561 raise OSError('Unknown group %r'%group) 562 group=entry[2] 563 return os.lchown(path,user,group) 564def run_regular_process(cmd,kwargs,cargs={}): 565 proc=subprocess.Popen(cmd,**kwargs) 566 if kwargs.get('stdout')or kwargs.get('stderr'): 567 try: 568 out,err=proc.communicate(**cargs) 569 except TimeoutExpired: 570 if kwargs.get('start_new_session')and hasattr(os,'killpg'): 571 os.killpg(proc.pid,signal.SIGKILL) 572 else: 573 proc.kill() 574 out,err=proc.communicate() 575 exc=TimeoutExpired(proc.args,timeout=cargs['timeout'],output=out) 576 exc.stderr=err 577 raise exc 578 status=proc.returncode 579 else: 580 out,err=(None,None) 581 try: 582 status=proc.wait(**cargs) 583 except TimeoutExpired as e: 584 if kwargs.get('start_new_session')and hasattr(os,'killpg'): 585 os.killpg(proc.pid,signal.SIGKILL) 586 else: 587 proc.kill() 588 proc.wait() 589 raise e 590 return status,out,err 591def run_process(cmd,kwargs,cargs={}): 592 if kwargs.get('stdout')and kwargs.get('stderr'): 593 return run_prefork_process(cmd,kwargs,cargs) 594 else: 595 return run_regular_process(cmd,kwargs,cargs) 596def alloc_process_pool(n,force=False): 597 global run_process,get_process,alloc_process_pool 598 if not force: 599 n=max(n-len(process_pool),0) 600 try: 601 lst=[get_process()for x in range(n)] 602 except OSError: 603 run_process=run_regular_process 604 get_process=alloc_process_pool=nada 605 else: 606 for x in lst: 607 process_pool.append(x) 608def atexit_pool(): 609 for k in process_pool: 610 try: 611 os.kill(k.pid,9) 612 except OSError: 613 pass 614 else: 615 k.wait() 616if(sys.hexversion<0x207000f and not is_win32)or sys.hexversion>=0x306000f: 617 atexit.register(atexit_pool) 618if os.environ.get('WAF_NO_PREFORK')or sys.platform=='cli'or not sys.executable: 619 run_process=run_regular_process 620 get_process=alloc_process_pool=nada 621