#! /usr/bin/env python
# encoding: utf-8
# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file

import os,sys,errno,re,shutil
try:
	import cPickle
except ImportError:
	import pickle as cPickle
from waflib import Runner,TaskGen,Utils,ConfigSet,Task,Logs,Options,Context,Errors
import waflib.Node
CACHE_DIR='c4che'
CACHE_SUFFIX='_cache.py'
INSTALL=1337
UNINSTALL=-1337
SAVED_ATTRS='root node_deps raw_deps task_sigs'.split()
CFG_FILES='cfg_files'
POST_AT_ONCE=0
POST_LAZY=1
POST_BOTH=2
class BuildContext(Context.Context):
	'''executes the build'''
	cmd='build'
	variant=''
	def __init__(self,**kw):
		super(BuildContext,self).__init__(**kw)
		self.is_install=0
		self.top_dir=kw.get('top_dir',Context.top_dir)
		self.run_dir=kw.get('run_dir',Context.run_dir)
		self.post_mode=POST_AT_ONCE
		self.out_dir=kw.get('out_dir',Context.out_dir)
		self.cache_dir=kw.get('cache_dir',None)
		if not self.cache_dir:
			self.cache_dir=self.out_dir+os.sep+CACHE_DIR
		self.all_envs={}
		self.task_sigs={}
		self.node_deps={}
		self.raw_deps={}
		self.cache_dir_contents={}
		self.task_gen_cache_names={}
		self.launch_dir=Context.launch_dir
		self.jobs=Options.options.jobs
		self.targets=Options.options.targets
		self.keep=Options.options.keep
		self.cache_global=Options.cache_global
		self.nocache=Options.options.nocache
		self.progress_bar=Options.options.progress_bar
		self.deps_man=Utils.defaultdict(list)
		self.current_group=0
		self.groups=[]
		self.group_names={}
	def get_variant_dir(self):
		if not self.variant:
			return self.out_dir
		return os.path.join(self.out_dir,self.variant)
	variant_dir=property(get_variant_dir,None)
	def __call__(self,*k,**kw):
		kw['bld']=self
		ret=TaskGen.task_gen(*k,**kw)
		self.task_gen_cache_names={}
		self.add_to_group(ret,group=kw.get('group',None))
		return ret
	def rule(self,*k,**kw):
		def f(rule):
			ret=self(*k,**kw)
			ret.rule=rule
			return ret
		return f
	def __copy__(self):
		raise Errors.WafError('build contexts are not supposed to be copied')
	def install_files(self,*k,**kw):
		pass
	def install_as(self,*k,**kw):
		pass
	def symlink_as(self,*k,**kw):
		pass
	def load_envs(self):
		node=self.root.find_node(self.cache_dir)
		if not node:
			raise Errors.WafError('The project was not configured: run "waf configure" first!')
		lst=node.ant_glob('**/*%s'%CACHE_SUFFIX,quiet=True)
		if not lst:
			raise Errors.WafError('The cache directory is empty: reconfigure the project')
		for x in lst:
			name=x.path_from(node).replace(CACHE_SUFFIX,'').replace('\\','/')
			env=ConfigSet.ConfigSet(x.abspath())
			self.all_envs[name]=env
			for f in env[CFG_FILES]:
				newnode=self.root.find_resource(f)
				try:
					h=Utils.h_file(newnode.abspath())
				except(IOError,AttributeError):
					Logs.error('cannot find %r'%f)
					h=Utils.SIG_NIL
				newnode.sig=h
	def init_dirs(self):
		if not(os.path.isabs(self.top_dir)and os.path.isabs(self.out_dir)):
			raise Errors.WafError('The project was not configured: run "waf configure" first!')
		self.path=self.srcnode=self.root.find_dir(self.top_dir)
		self.bldnode=self.root.make_node(self.variant_dir)
		self.bldnode.mkdir()
	def execute(self):
		self.restore()
		if not self.all_envs:
			self.load_envs()
		self.execute_build()
	def execute_build(self):
		Logs.info("Waf: Entering directory `%s'"%self.variant_dir)
		self.recurse([self.run_dir])
		self.pre_build()
		self.timer=Utils.Timer()
		if self.progress_bar:
			sys.stderr.write(Logs.colors.cursor_off)
		try:
			self.compile()
		finally:
			if self.progress_bar==1:
				c=len(self.returned_tasks)or 1
				self.to_log(self.progress_line(c,c,Logs.colors.BLUE,Logs.colors.NORMAL))
				print('')
				sys.stdout.flush()
				sys.stderr.write(Logs.colors.cursor_on)
			Logs.info("Waf: Leaving directory `%s'"%self.variant_dir)
		self.post_build()
	def restore(self):
		try:
			env=ConfigSet.ConfigSet(os.path.join(self.cache_dir,'build.config.py'))
		except(IOError,OSError):
			pass
		else:
			if env['version']<Context.HEXVERSION:
				raise Errors.WafError('Version mismatch! reconfigure the project')
			for t in env['tools']:
				self.setup(**t)
		dbfn=os.path.join(self.variant_dir,Context.DBFILE)
		try:
			data=Utils.readf(dbfn,'rb')
		except(IOError,EOFError):
			Logs.debug('build: Could not load the build cache %s (missing)'%dbfn)
		else:
			try:
				waflib.Node.pickle_lock.acquire()
				waflib.Node.Nod3=self.node_class
				try:
					data=cPickle.loads(data)
				except Exception ,e:
					Logs.debug('build: Could not pickle the build cache %s: %r'%(dbfn,e))
				else:
					for x in SAVED_ATTRS:
						setattr(self,x,data[x])
			finally:
				waflib.Node.pickle_lock.release()
		self.init_dirs()
	def store(self):
		data={}
		for x in SAVED_ATTRS:
			data[x]=getattr(self,x)
		db=os.path.join(self.variant_dir,Context.DBFILE)
		try:
			waflib.Node.pickle_lock.acquire()
			waflib.Node.Nod3=self.node_class
			x=cPickle.dumps(data,-1)
		finally:
			waflib.Node.pickle_lock.release()
		Utils.writef(db+'.tmp',x,m='wb')
		try:
			st=os.stat(db)
			os.remove(db)
			if not Utils.is_win32:
				os.chown(db+'.tmp',st.st_uid,st.st_gid)
		except(AttributeError,OSError):
			pass
		os.rename(db+'.tmp',db)
	def compile(self):
		Logs.debug('build: compile()')
		self.producer=Runner.Parallel(self,self.jobs)
		self.producer.biter=self.get_build_iterator()
		self.returned_tasks=[]
		try:
			self.producer.start()
		except KeyboardInterrupt:
			self.store()
			raise
		else:
			if self.producer.dirty:
				self.store()
		if self.producer.error:
			raise Errors.BuildError(self.producer.error)
	def setup(self,tool,tooldir=None,funs=None):
		if isinstance(tool,list):
			for i in tool:self.setup(i,tooldir)
			return
		module=Context.load_tool(tool,tooldir)
		if hasattr(module,"setup"):module.setup(self)
	def get_env(self):
		try:
			return self.all_envs[self.variant]
		except KeyError:
			return self.all_envs['']
	def set_env(self,val):
		self.all_envs[self.variant]=val
	env=property(get_env,set_env)
	def add_manual_dependency(self,path,value):
		if path is None:
			raise ValueError('Invalid input')
		if isinstance(path,waflib.Node.Node):
			node=path
		elif os.path.isabs(path):
			node=self.root.find_resource(path)
		else:
			node=self.path.find_resource(path)
		if isinstance(value,list):
			self.deps_man[id(node)].extend(value)
		else:
			self.deps_man[id(node)].append(value)
	def launch_node(self):
		try:
			return self.p_ln
		except AttributeError:
			self.p_ln=self.root.find_dir(self.launch_dir)
			return self.p_ln
	def hash_env_vars(self,env,vars_lst):
		if not env.table:
			env=env.parent
			if not env:
				return Utils.SIG_NIL
		idx=str(id(env))+str(vars_lst)
		try:
			cache=self.cache_env
		except AttributeError:
			cache=self.cache_env={}
		else:
			try:
				return self.cache_env[idx]
			except KeyError:
				pass
		lst=[env[a]for a in vars_lst]
		ret=Utils.h_list(lst)
		Logs.debug('envhash: %s %r',Utils.to_hex(ret),lst)
		cache[idx]=ret
		return ret
	def get_tgen_by_name(self,name):
		cache=self.task_gen_cache_names
		if not cache:
			for g in self.groups:
				for tg in g:
					try:
						cache[tg.name]=tg
					except AttributeError:
						pass
		try:
			return cache[name]
		except KeyError:
			raise Errors.WafError('Could not find a task generator for the name %r'%name)
	def progress_line(self,state,total,col1,col2):
		n=len(str(total))
		Utils.rot_idx+=1
		ind=Utils.rot_chr[Utils.rot_idx%4]
		pc=(100.*state)/total
		eta=str(self.timer)
		fs="[%%%dd/%%%dd][%%s%%2d%%%%%%s][%s]["%(n,n,ind)
		left=fs%(state,total,col1,pc,col2)
		right='][%s%s%s]'%(col1,eta,col2)
		cols=Logs.get_term_cols()-len(left)-len(right)+2*len(col1)+2*len(col2)
		if cols<7:cols=7
		ratio=((cols*state)//total)-1
		bar=('='*ratio+'>').ljust(cols)
		msg=Utils.indicator%(left,bar,right)
		return msg
	def declare_chain(self,*k,**kw):
		return TaskGen.declare_chain(*k,**kw)
	def pre_build(self):
		for m in getattr(self,'pre_funs',[]):
			m(self)
	def post_build(self):
		for m in getattr(self,'post_funs',[]):
			m(self)
	def add_pre_fun(self,meth):
		try:
			self.pre_funs.append(meth)
		except AttributeError:
			self.pre_funs=[meth]
	def add_post_fun(self,meth):
		try:
			self.post_funs.append(meth)
		except AttributeError:
			self.post_funs=[meth]
	def get_group(self,x):
		if not self.groups:
			self.add_group()
		if x is None:
			return self.groups[self.current_group]
		if x in self.group_names:
			return self.group_names[x]
		return self.groups[x]
	def add_to_group(self,tgen,group=None):
		assert(isinstance(tgen,TaskGen.task_gen)or isinstance(tgen,Task.TaskBase))
		tgen.bld=self
		self.get_group(group).append(tgen)
	def get_group_name(self,g):
		if not isinstance(g,list):
			g=self.groups[g]
		for x in self.group_names:
			if id(self.group_names[x])==id(g):
				return x
		return''
	def get_group_idx(self,tg):
		se=id(tg)
		for i in range(len(self.groups)):
			for t in self.groups[i]:
				if id(t)==se:
					return i
		return None
	def add_group(self,name=None,move=True):
		if name and name in self.group_names:
			Logs.error('add_group: name %s already present'%name)
		g=[]
		self.group_names[name]=g
		self.groups.append(g)
		if move:
			self.current_group=len(self.groups)-1
	def set_group(self,idx):
		if isinstance(idx,str):
			g=self.group_names[idx]
			for i in range(len(self.groups)):
				if id(g)==id(self.groups[i]):
					self.current_group=i
		else:
			self.current_group=idx
	def total(self):
		total=0
		for group in self.groups:
			for tg in group:
				try:
					total+=len(tg.tasks)
				except AttributeError:
					total+=1
		return total
	def get_targets(self):
		to_post=[]
		min_grp=0
		for name in self.targets.split(','):
			tg=self.get_tgen_by_name(name)
			if not tg:
				raise Errors.WafError('target %r does not exist'%name)
			m=self.get_group_idx(tg)
			if m>min_grp:
				min_grp=m
				to_post=[tg]
			elif m==min_grp:
				to_post.append(tg)
		return(min_grp,to_post)
	def get_all_task_gen(self):
		lst=[]
		for g in self.groups:
			lst.extend(g)
		return lst
	def post_group(self):
		if self.targets=='*':
			for tg in self.groups[self.cur]:
				try:
					f=tg.post
				except AttributeError:
					pass
				else:
					f()
		elif self.targets:
			if self.cur<self._min_grp:
				for tg in self.groups[self.cur]:
					try:
						f=tg.post
					except AttributeError:
						pass
					else:
						f()
			else:
				for tg in self._exact_tg:
					tg.post()
		else:
			ln=self.launch_node()
			if ln.is_child_of(self.bldnode):
				Logs.warn('Building from the build directory, forcing --targets=*')
				ln=self.srcnode
			elif not ln.is_child_of(self.srcnode):
				Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)'%(ln.abspath(),self.srcnode.abspath()))
				ln=self.srcnode
			for tg in self.groups[self.cur]:
				try:
					f=tg.post
				except AttributeError:
					pass
				else:
					if tg.path.is_child_of(ln):
						f()
	def get_tasks_group(self,idx):
		tasks=[]
		for tg in self.groups[idx]:
			try:
				tasks.extend(tg.tasks)
			except AttributeError:
				tasks.append(tg)
		return tasks
	def get_build_iterator(self):
		self.cur=0
		if self.targets and self.targets!='*':
			(self._min_grp,self._exact_tg)=self.get_targets()
		global lazy_post
		if self.post_mode!=POST_LAZY:
			while self.cur<len(self.groups):
				self.post_group()
				self.cur+=1
			self.cur=0
		while self.cur<len(self.groups):
			if self.post_mode!=POST_AT_ONCE:
				self.post_group()
			tasks=self.get_tasks_group(self.cur)
			Task.set_file_constraints(tasks)
			Task.set_precedence_constraints(tasks)
			self.cur_tasks=tasks
			self.cur+=1
			if not tasks:
				continue
			yield tasks
		while 1:
			yield[]
class inst(Task.Task):
	color='CYAN'
	def uid(self):
		lst=[self.dest,self.path]+self.source
		return Utils.h_list(repr(lst))
	def post(self):
		buf=[]
		for x in self.source:
			if isinstance(x,waflib.Node.Node):
				y=x
			else:
				y=self.path.find_resource(x)
				if not y:
					if Logs.verbose:
						Logs.warn('Could not find %s immediately (may cause broken builds)'%x)
					idx=self.generator.bld.get_group_idx(self)
					for tg in self.generator.bld.groups[idx]:
						if not isinstance(tg,inst)and id(tg)!=id(self):
							tg.post()
						y=self.path.find_resource(x)
						if y:
							break
					else:
						raise Errors.WafError('Could not find %r in %r'%(x,self.path))
			buf.append(y)
		self.inputs=buf
	def runnable_status(self):
		ret=super(inst,self).runnable_status()
		if ret==Task.SKIP_ME:
			return Task.RUN_ME
		return ret
	def __str__(self):
		return''
	def run(self):
		return self.generator.exec_task()
	def get_install_path(self,destdir=True):
		dest=Utils.subst_vars(self.dest,self.env)
		dest=dest.replace('/',os.sep)
		if destdir and Options.options.destdir:
			dest=os.path.join(Options.options.destdir,os.path.splitdrive(dest)[1].lstrip(os.sep))
		return dest
	def exec_install_files(self):
		destpath=self.get_install_path()
		if not destpath:
			raise Errors.WafError('unknown installation path %r'%self.generator)
		for x,y in zip(self.source,self.inputs):
			if self.relative_trick:
				destfile=os.path.join(destpath,y.path_from(self.path))
			else:
				destfile=os.path.join(destpath,y.name)
			self.generator.bld.do_install(y.abspath(),destfile,self.chmod)
	def exec_install_as(self):
		destfile=self.get_install_path()
		self.generator.bld.do_install(self.inputs[0].abspath(),destfile,self.chmod)
	def exec_symlink_as(self):
		destfile=self.get_install_path()
		src=self.link
		if self.relative_trick:
			src=os.path.relpath(src,os.path.dirname(destfile))
		self.generator.bld.do_link(src,destfile)
class InstallContext(BuildContext):
	'''installs the targets on the system'''
	cmd='install'
	def __init__(self,**kw):
		super(InstallContext,self).__init__(**kw)
		self.uninstall=[]
		self.is_install=INSTALL
	def do_install(self,src,tgt,chmod=Utils.O644):
		d,_=os.path.split(tgt)
		if not d:
			raise Errors.WafError('Invalid installation given %r->%r'%(src,tgt))
		Utils.check_dir(d)
		srclbl=src.replace(self.srcnode.abspath()+os.sep,'')
		if not Options.options.force:
			try:
				st1=os.stat(tgt)
				st2=os.stat(src)
			except OSError:
				pass
			else:
				if st1.st_mtime+2>=st2.st_mtime and st1.st_size==st2.st_size:
					if not self.progress_bar:
						Logs.info('- install %s (from %s)'%(tgt,srclbl))
					return False
		if not self.progress_bar:
			Logs.info('+ install %s (from %s)'%(tgt,srclbl))
		try:
			os.remove(tgt)
		except OSError:
			pass
		try:
			shutil.copy2(src,tgt)
			os.chmod(tgt,chmod)
		except IOError:
			try:
				os.stat(src)
			except(OSError,IOError):
				Logs.error('File %r does not exist'%src)
			raise Errors.WafError('Could not install the file %r'%tgt)
	def do_link(self,src,tgt):
		d,_=os.path.split(tgt)
		Utils.check_dir(d)
		link=False
		if not os.path.islink(tgt):
			link=True
		elif os.readlink(tgt)!=src:
			link=True
		if link:
			try:os.remove(tgt)
			except OSError:pass
			if not self.progress_bar:
				Logs.info('+ symlink %s (to %s)'%(tgt,src))
			os.symlink(src,tgt)
		else:
			if not self.progress_bar:
				Logs.info('- symlink %s (to %s)'%(tgt,src))
	def run_task_now(self,tsk,postpone):
		tsk.post()
		if not postpone:
			if tsk.runnable_status()==Task.ASK_LATER:
				raise self.WafError('cannot post the task %r'%tsk)
			tsk.run()
	def install_files(self,dest,files,env=None,chmod=Utils.O644,relative_trick=False,cwd=None,add=True,postpone=True):
		tsk=inst(env=env or self.env)
		tsk.bld=self
		tsk.path=cwd or self.path
		tsk.chmod=chmod
		if isinstance(files,waflib.Node.Node):
			tsk.source=[files]
		else:
			tsk.source=Utils.to_list(files)
		tsk.dest=dest
		tsk.exec_task=tsk.exec_install_files
		tsk.relative_trick=relative_trick
		if add:self.add_to_group(tsk)
		self.run_task_now(tsk,postpone)
		return tsk
	def install_as(self,dest,srcfile,env=None,chmod=Utils.O644,cwd=None,add=True,postpone=True):
		tsk=inst(env=env or self.env)
		tsk.bld=self
		tsk.path=cwd or self.path
		tsk.chmod=chmod
		tsk.source=[srcfile]
		tsk.dest=dest
		tsk.exec_task=tsk.exec_install_as
		if add:self.add_to_group(tsk)
		self.run_task_now(tsk,postpone)
		return tsk
	def symlink_as(self,dest,src,env=None,cwd=None,add=True,postpone=True,relative_trick=False):
		if Utils.is_win32:
			return
		tsk=inst(env=env or self.env)
		tsk.bld=self
		tsk.dest=dest
		tsk.path=cwd or self.path
		tsk.source=[]
		tsk.link=src
		tsk.relative_trick=relative_trick
		tsk.exec_task=tsk.exec_symlink_as
		if add:self.add_to_group(tsk)
		self.run_task_now(tsk,postpone)
		return tsk
class UninstallContext(InstallContext):
	'''removes the targets installed'''
	cmd='uninstall'
	def __init__(self,**kw):
		super(UninstallContext,self).__init__(**kw)
		self.is_install=UNINSTALL
	def do_install(self,src,tgt,chmod=Utils.O644):
		if not self.progress_bar:
			Logs.info('- remove %s'%tgt)
		self.uninstall.append(tgt)
		try:
			os.remove(tgt)
		except OSError ,e:
			if e.errno!=errno.ENOENT:
				if not getattr(self,'uninstall_error',None):
					self.uninstall_error=True
					Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)')
				if Logs.verbose>1:
					Logs.warn('Could not remove %s (error code %r)'%(e.filename,e.errno))
		while tgt:
			tgt=os.path.dirname(tgt)
			try:
				os.rmdir(tgt)
			except OSError:
				break
	def do_link(self,src,tgt):
		try:
			if not self.progress_bar:
				Logs.info('- remove %s'%tgt)
			os.remove(tgt)
		except OSError:
			pass
		while tgt:
			tgt=os.path.dirname(tgt)
			try:
				os.rmdir(tgt)
			except OSError:
				break
	def execute(self):
		try:
			def runnable_status(self):
				return Task.SKIP_ME
			setattr(Task.Task,'runnable_status_back',Task.Task.runnable_status)
			setattr(Task.Task,'runnable_status',runnable_status)
			super(UninstallContext,self).execute()
		finally:
			setattr(Task.Task,'runnable_status',Task.Task.runnable_status_back)
class CleanContext(BuildContext):
	'''cleans the project'''
	cmd='clean'
	def execute(self):
		self.restore()
		if not self.all_envs:
			self.load_envs()
		self.recurse([self.run_dir])
		try:
			self.clean()
		finally:
			self.store()
	def clean(self):
		Logs.debug('build: clean called')
		if self.bldnode!=self.srcnode:
			lst=[]
			for e in self.all_envs.values():
				lst.extend(self.root.find_or_declare(f)for f in e[CFG_FILES])
			for n in self.bldnode.ant_glob('**/*',excl='.lock* *conf_check_*/** config.log c4che/*',quiet=True):
				if n in lst:
					continue
				n.delete()
		self.root.children={}
		for v in'node_deps task_sigs raw_deps'.split():
			setattr(self,v,{})
class ListContext(BuildContext):
	'''lists the targets to execute'''
	cmd='list'
	def execute(self):
		self.restore()
		if not self.all_envs:
			self.load_envs()
		self.recurse([self.run_dir])
		self.pre_build()
		self.timer=Utils.Timer()
		for g in self.groups:
			for tg in g:
				try:
					f=tg.post
				except AttributeError:
					pass
				else:
					f()
		try:
			self.get_tgen_by_name('')
		except Exception:
			pass
		lst=list(self.task_gen_cache_names.keys())
		lst.sort()
		for k in lst:
			Logs.pprint('GREEN',k)
class StepContext(BuildContext):
	'''executes tasks in a step-by-step fashion, for debugging'''
	cmd='step'
	def __init__(self,**kw):
		super(StepContext,self).__init__(**kw)
		self.files=Options.options.files
	def compile(self):
		if not self.files:
			Logs.warn('Add a pattern for the debug build, for example "waf step --files=main.c,app"')
			BuildContext.compile(self)
			return
		targets=None
		if self.targets and self.targets!='*':
			targets=self.targets.split(',')
		for g in self.groups:
			for tg in g:
				if targets and tg.name not in targets:
					continue
				try:
					f=tg.post
				except AttributeError:
					pass
				else:
					f()
			for pat in self.files.split(','):
				matcher=self.get_matcher(pat)
				for tg in g:
					if isinstance(tg,Task.TaskBase):
						lst=[tg]
					else:
						lst=tg.tasks
					for tsk in lst:
						do_exec=False
						for node in getattr(tsk,'inputs',[]):
							if matcher(node,output=False):
								do_exec=True
								break
						for node in getattr(tsk,'outputs',[]):
							if matcher(node,output=True):
								do_exec=True
								break
						if do_exec:
							ret=tsk.run()
							Logs.info('%s -> exit %r'%(str(tsk),ret))
	def get_matcher(self,pat):
		inn=True
		out=True
		if pat.startswith('in:'):
			out=False
			pat=pat.replace('in:','')
		elif pat.startswith('out:'):
			inn=False
			pat=pat.replace('out:','')
		anode=self.root.find_node(pat)
		pattern=None
		if not anode:
			if not pat.startswith('^'):
				pat='^.+?%s'%pat
			if not pat.endswith('$'):
				pat='%s$'%pat
			pattern=re.compile(pat)
		def match(node,output):
			if output==True and not out:
				return False
			if output==False and not inn:
				return False
			if anode:
				return anode==node
			else:
				return pattern.match(node.abspath())
		return match
BuildContext.store=Utils.nogc(BuildContext.store)
BuildContext.restore=Utils.nogc(BuildContext.restore)
