#! /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,re
from waflib import Task,Utils,Node,Errors
from waflib.TaskGen import after_method,before_method,feature,taskgen_method,extension
from waflib.Tools import c_aliases,c_preproc,c_config,c_osx,c_tests
from waflib.Configure import conf
SYSTEM_LIB_PATHS=['/usr/lib64','/usr/lib','/usr/local/lib64','/usr/local/lib']
USELIB_VARS=Utils.defaultdict(set)
USELIB_VARS['c']=set(['INCLUDES','FRAMEWORKPATH','DEFINES','CPPFLAGS','CCDEPS','CFLAGS','ARCH'])
USELIB_VARS['cxx']=set(['INCLUDES','FRAMEWORKPATH','DEFINES','CPPFLAGS','CXXDEPS','CXXFLAGS','ARCH'])
USELIB_VARS['d']=set(['INCLUDES','DFLAGS'])
USELIB_VARS['includes']=set(['INCLUDES','FRAMEWORKPATH','ARCH'])
USELIB_VARS['cprogram']=USELIB_VARS['cxxprogram']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS','FRAMEWORK','FRAMEWORKPATH','ARCH'])
USELIB_VARS['cshlib']=USELIB_VARS['cxxshlib']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS','FRAMEWORK','FRAMEWORKPATH','ARCH'])
USELIB_VARS['cstlib']=USELIB_VARS['cxxstlib']=set(['ARFLAGS','LINKDEPS'])
USELIB_VARS['dprogram']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS'])
USELIB_VARS['dshlib']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS'])
USELIB_VARS['dstlib']=set(['ARFLAGS','LINKDEPS'])
USELIB_VARS['asm']=set(['ASFLAGS'])
@taskgen_method
def create_compiled_task(self,name,node):
	out='%s.%d.o'%(node.name,self.idx)
	task=self.create_task(name,node,node.parent.find_or_declare(out))
	try:
		self.compiled_tasks.append(task)
	except AttributeError:
		self.compiled_tasks=[task]
	return task
@taskgen_method
def to_incnodes(self,inlst):
	lst=[]
	seen=set([])
	for x in self.to_list(inlst):
		if x in seen or not x:
			continue
		seen.add(x)
		if isinstance(x,Node.Node):
			lst.append(x)
		else:
			if os.path.isabs(x):
				lst.append(self.bld.root.make_node(x)or x)
			else:
				if x[0]=='#':
					p=self.bld.bldnode.make_node(x[1:])
					v=self.bld.srcnode.make_node(x[1:])
				else:
					p=self.path.get_bld().make_node(x)
					v=self.path.make_node(x)
				if p.is_child_of(self.bld.bldnode):
					p.mkdir()
				lst.append(p)
				lst.append(v)
	return lst
@feature('c','cxx','d','asm','fc','includes')
@after_method('propagate_uselib_vars','process_source')
def apply_incpaths(self):
	lst=self.to_incnodes(self.to_list(getattr(self,'includes',[]))+self.env['INCLUDES'])
	self.includes_nodes=lst
	self.env['INCPATHS']=[x.abspath()for x in lst]
class link_task(Task.Task):
	color='YELLOW'
	inst_to=None
	chmod=Utils.O755
	def add_target(self,target):
		if isinstance(target,str):
			pattern=self.env[self.__class__.__name__+'_PATTERN']
			if not pattern:
				pattern='%s'
			folder,name=os.path.split(target)
			if self.__class__.__name__.find('shlib')>0:
				if self.env.DEST_BINFMT=='pe'and getattr(self.generator,'vnum',None):
					name=name+'-'+self.generator.vnum.split('.')[0]
			tmp=folder+os.sep+pattern%name
			target=self.generator.path.find_or_declare(tmp)
		self.set_outputs(target)
class stlink_task(link_task):
	run_str='${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}'
def rm_tgt(cls):
	old=cls.run
	def wrap(self):
		try:os.remove(self.outputs[0].abspath())
		except OSError:pass
		return old(self)
	setattr(cls,'run',wrap)
rm_tgt(stlink_task)
@feature('c','cxx','d','fc','asm')
@after_method('process_source')
def apply_link(self):
	for x in self.features:
		if x=='cprogram'and'cxx'in self.features:
			x='cxxprogram'
		elif x=='cshlib'and'cxx'in self.features:
			x='cxxshlib'
		if x in Task.classes:
			if issubclass(Task.classes[x],link_task):
				link=x
				break
	else:
		return
	objs=[t.outputs[0]for t in getattr(self,'compiled_tasks',[])]
	self.link_task=self.create_task(link,objs)
	self.link_task.add_target(self.target)
	try:
		inst_to=self.install_path
	except AttributeError:
		inst_to=self.link_task.__class__.inst_to
	if inst_to:
		self.install_task=self.bld.install_files(inst_to,self.link_task.outputs[:],env=self.env,chmod=self.link_task.chmod)
@taskgen_method
def use_rec(self,name,**kw):
	if name in self.tmp_use_not or name in self.tmp_use_seen:
		return
	try:
		y=self.bld.get_tgen_by_name(name)
	except Errors.WafError:
		self.uselib.append(name)
		self.tmp_use_not.add(name)
		return
	self.tmp_use_seen.append(name)
	y.post()
	y.tmp_use_objects=objects=kw.get('objects',True)
	y.tmp_use_stlib=stlib=kw.get('stlib',True)
	try:
		link_task=y.link_task
	except AttributeError:
		y.tmp_use_var=''
	else:
		objects=False
		if not isinstance(link_task,stlink_task):
			stlib=False
			y.tmp_use_var='LIB'
		else:
			y.tmp_use_var='STLIB'
	p=self.tmp_use_prec
	for x in self.to_list(getattr(y,'use',[])):
		try:
			p[x].append(name)
		except KeyError:
			p[x]=[name]
		self.use_rec(x,objects=objects,stlib=stlib)
@feature('c','cxx','d','use','fc')
@before_method('apply_incpaths','propagate_uselib_vars')
@after_method('apply_link','process_source')
def process_use(self):
	use_not=self.tmp_use_not=set([])
	self.tmp_use_seen=[]
	use_prec=self.tmp_use_prec={}
	self.uselib=self.to_list(getattr(self,'uselib',[]))
	self.includes=self.to_list(getattr(self,'includes',[]))
	names=self.to_list(getattr(self,'use',[]))
	for x in names:
		self.use_rec(x)
	for x in use_not:
		if x in use_prec:
			del use_prec[x]
	out=[]
	tmp=[]
	for x in self.tmp_use_seen:
		for k in use_prec.values():
			if x in k:
				break
		else:
			tmp.append(x)
	while tmp:
		e=tmp.pop()
		out.append(e)
		try:
			nlst=use_prec[e]
		except KeyError:
			pass
		else:
			del use_prec[e]
			for x in nlst:
				for y in use_prec:
					if x in use_prec[y]:
						break
				else:
					tmp.append(x)
	if use_prec:
		raise Errors.WafError('Cycle detected in the use processing %r'%use_prec)
	out.reverse()
	link_task=getattr(self,'link_task',None)
	for x in out:
		y=self.bld.get_tgen_by_name(x)
		var=y.tmp_use_var
		if var and link_task:
			if var=='LIB'or y.tmp_use_stlib:
				self.env.append_value(var,[y.target[y.target.rfind(os.sep)+1:]])
				self.link_task.dep_nodes.extend(y.link_task.outputs)
				tmp_path=y.link_task.outputs[0].parent.path_from(self.bld.bldnode)
				self.env.append_value(var+'PATH',[tmp_path])
		else:
			if y.tmp_use_objects:
				self.add_objects_from_tgen(y)
		if getattr(y,'export_includes',None):
			self.includes.extend(y.to_incnodes(y.export_includes))
		if getattr(y,'export_defines',None):
			self.env.append_value('DEFINES',self.to_list(y.export_defines))
	for x in names:
		try:
			y=self.bld.get_tgen_by_name(x)
		except Exception:
			if not self.env['STLIB_'+x]and not x in self.uselib:
				self.uselib.append(x)
		else:
			for k in self.to_list(getattr(y,'uselib',[])):
				if not self.env['STLIB_'+k]and not k in self.uselib:
					self.uselib.append(k)
@taskgen_method
def accept_node_to_link(self,node):
	return not node.name.endswith('.pdb')
@taskgen_method
def add_objects_from_tgen(self,tg):
	try:
		link_task=self.link_task
	except AttributeError:
		pass
	else:
		for tsk in getattr(tg,'compiled_tasks',[]):
			for x in tsk.outputs:
				if self.accept_node_to_link(x):
					link_task.inputs.append(x)
@taskgen_method
def get_uselib_vars(self):
	_vars=set([])
	for x in self.features:
		if x in USELIB_VARS:
			_vars|=USELIB_VARS[x]
	return _vars
@feature('c','cxx','d','fc','javac','cs','uselib','asm')
@after_method('process_use')
def propagate_uselib_vars(self):
	_vars=self.get_uselib_vars()
	env=self.env
	for x in _vars:
		y=x.lower()
		env.append_unique(x,self.to_list(getattr(self,y,[])))
	for x in self.features:
		for var in _vars:
			compvar='%s_%s'%(var,x)
			env.append_value(var,env[compvar])
	for x in self.to_list(getattr(self,'uselib',[])):
		for v in _vars:
			env.append_value(v,env[v+'_'+x])
@feature('cshlib','cxxshlib','fcshlib')
@after_method('apply_link')
def apply_implib(self):
	if not self.env.DEST_BINFMT=='pe':
		return
	dll=self.link_task.outputs[0]
	if isinstance(self.target,Node.Node):
		name=self.target.name
	else:
		name=os.path.split(self.target)[1]
	implib=self.env['implib_PATTERN']%name
	implib=dll.parent.find_or_declare(implib)
	self.env.append_value('LINKFLAGS',self.env['IMPLIB_ST']%implib.bldpath())
	self.link_task.outputs.append(implib)
	if getattr(self,'defs',None)and self.env.DEST_BINFMT=='pe':
		node=self.path.find_resource(self.defs)
		if not node:
			raise Errors.WafError('invalid def file %r'%self.defs)
		if'msvc'in(self.env.CC_NAME,self.env.CXX_NAME):
			self.env.append_value('LINKFLAGS','/def:%s'%node.path_from(self.bld.bldnode))
			self.link_task.dep_nodes.append(node)
		else:
			self.link_task.inputs.append(node)
	try:
		inst_to=self.install_path
	except AttributeError:
		inst_to=self.link_task.__class__.inst_to
	if not inst_to:
		return
	self.implib_install_task=self.bld.install_as('${LIBDIR}/%s'%implib.name,implib,self.env)
re_vnum=re.compile('^([1-9]\\d*|0)[.]([1-9]\\d*|0)[.]([1-9]\\d*|0)$')
@feature('cshlib','cxxshlib','dshlib','fcshlib','vnum')
@after_method('apply_link','propagate_uselib_vars')
def apply_vnum(self):
	if not getattr(self,'vnum','')or os.name!='posix'or self.env.DEST_BINFMT not in('elf','mac-o'):
		return
	link=self.link_task
	if not re_vnum.match(self.vnum):
		raise Errors.WafError('Invalid version %r for %r'%(self.vnum,self))
	nums=self.vnum.split('.')
	node=link.outputs[0]
	libname=node.name
	if libname.endswith('.dylib'):
		name3=libname.replace('.dylib','.%s.dylib'%self.vnum)
		name2=libname.replace('.dylib','.%s.dylib'%nums[0])
	else:
		name3=libname+'.'+self.vnum
		name2=libname+'.'+nums[0]
	if self.env.SONAME_ST:
		v=self.env.SONAME_ST%name2
		self.env.append_value('LINKFLAGS',v.split())
	self.create_task('vnum',node,[node.parent.find_or_declare(name2),node.parent.find_or_declare(name3)])
	if getattr(self,'install_task',None):
		self.install_task.hasrun=Task.SKIP_ME
		bld=self.bld
		path=self.install_task.dest
		t1=bld.install_as(path+os.sep+name3,node,env=self.env,chmod=self.link_task.chmod)
		t2=bld.symlink_as(path+os.sep+name2,name3)
		t3=bld.symlink_as(path+os.sep+libname,name3)
		self.vnum_install_task=(t1,t2,t3)
	if'-dynamiclib'in self.env['LINKFLAGS']:
		try:
			inst_to=self.install_path
		except AttributeError:
			inst_to=self.link_task.__class__.inst_to
		if inst_to:
			p=Utils.subst_vars(inst_to,self.env)
			path=os.path.join(p,self.link_task.outputs[0].name)
			self.env.append_value('LINKFLAGS',['-install_name',path])
class vnum(Task.Task):
	color='CYAN'
	quient=True
	ext_in=['.bin']
	def run(self):
		for x in self.outputs:
			path=x.abspath()
			try:
				os.remove(path)
			except OSError:
				pass
			try:
				os.symlink(self.inputs[0].name,path)
			except OSError:
				return 1
class fake_shlib(link_task):
	def runnable_status(self):
		for t in self.run_after:
			if not t.hasrun:
				return Task.ASK_LATER
		for x in self.outputs:
			x.sig=Utils.h_file(x.abspath())
		return Task.SKIP_ME
class fake_stlib(stlink_task):
	def runnable_status(self):
		for t in self.run_after:
			if not t.hasrun:
				return Task.ASK_LATER
		for x in self.outputs:
			x.sig=Utils.h_file(x.abspath())
		return Task.SKIP_ME
@conf
def read_shlib(self,name,paths=[],export_includes=[],export_defines=[]):
	return self(name=name,features='fake_lib',lib_paths=paths,lib_type='shlib',export_includes=export_includes,export_defines=export_defines)
@conf
def read_stlib(self,name,paths=[],export_includes=[],export_defines=[]):
	return self(name=name,features='fake_lib',lib_paths=paths,lib_type='stlib',export_includes=export_includes,export_defines=export_defines)
lib_patterns={'shlib':['lib%s.so','%s.so','lib%s.dylib','lib%s.dll','%s.dll'],'stlib':['lib%s.a','%s.a','lib%s.dll','%s.dll','lib%s.lib','%s.lib'],}
@feature('fake_lib')
def process_lib(self):
	node=None
	names=[x%self.name for x in lib_patterns[self.lib_type]]
	for x in self.lib_paths+[self.path]+SYSTEM_LIB_PATHS:
		if not isinstance(x,Node.Node):
			x=self.bld.root.find_node(x)or self.path.find_node(x)
			if not x:
				continue
		for y in names:
			node=x.find_node(y)
			if node:
				node.sig=Utils.h_file(node.abspath())
				break
		else:
			continue
		break
	else:
		raise Errors.WafError('could not find library %r'%self.name)
	self.link_task=self.create_task('fake_%s'%self.lib_type,[],[node])
	self.target=self.name
class fake_o(Task.Task):
	def runnable_status(self):
		return Task.SKIP_ME
@extension('.o','.obj')
def add_those_o_files(self,node):
	tsk=self.create_task('fake_o',[],node)
	try:
		self.compiled_tasks.append(tsk)
	except AttributeError:
		self.compiled_tasks=[tsk]
@feature('fake_obj')
@before_method('process_source')
def process_objs(self):
	for node in self.to_nodes(self.source):
		self.add_those_o_files(node)
	self.source=[]
@conf
def read_object(self,obj):
	if not isinstance(obj,self.path.__class__):
		obj=self.path.find_resource(obj)
	return self(features='fake_obj',source=obj,name=obj.name)
