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