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

typos={'feature':'features','sources':'source','targets':'target','include':'includes','export_include':'export_includes','define':'defines','importpath':'includes','installpath':'install_path','iscopy':'is_copy',}
meths_typos=['__call__','program','shlib','stlib','objects']
from waflib import Logs,Build,Node,Task,TaskGen,ConfigSet,Errors,Utils
import waflib.Tools.ccroot
def check_same_targets(self):
	mp=Utils.defaultdict(list)
	uids={}
	def check_task(tsk):
		if not isinstance(tsk,Task.Task):
			return
		for node in tsk.outputs:
			mp[node].append(tsk)
		try:
			uids[tsk.uid()].append(tsk)
		except KeyError:
			uids[tsk.uid()]=[tsk]
	for g in self.groups:
		for tg in g:
			try:
				for tsk in tg.tasks:
					check_task(tsk)
			except AttributeError:
				check_task(tg)
	dupe=False
	for(k,v)in mp.items():
		if len(v)>1:
			dupe=True
			msg='* Node %r is created more than once%s. The task generators are:'%(k,Logs.verbose==1 and" (full message on 'waf -v -v')"or"")
			Logs.error(msg)
			for x in v:
				if Logs.verbose>1:
					Logs.error('  %d. %r'%(1+v.index(x),x.generator))
				else:
					Logs.error('  %d. %r in %r'%(1+v.index(x),x.generator.name,getattr(x.generator,'path',None)))
	if not dupe:
		for(k,v)in uids.items():
			if len(v)>1:
				Logs.error('* Several tasks use the same identifier. Please check the information on\n   http://docs.waf.googlecode.com/git/apidocs_16/Task.html#waflib.Task.Task.uid')
				for tsk in v:
					Logs.error('  - object %r (%r) defined in %r'%(tsk.__class__.__name__,tsk,tsk.generator))
def check_invalid_constraints(self):
	feat=set([])
	for x in list(TaskGen.feats.values()):
		feat.union(set(x))
	for(x,y)in TaskGen.task_gen.prec.items():
		feat.add(x)
		feat.union(set(y))
	ext=set([])
	for x in TaskGen.task_gen.mappings.values():
		ext.add(x.__name__)
	invalid=ext&feat
	if invalid:
		Logs.error('The methods %r have invalid annotations:  @extension <-> @feature/@before_method/@after_method'%list(invalid))
	for cls in list(Task.classes.values()):
		for x in('before','after'):
			for y in Utils.to_list(getattr(cls,x,[])):
				if not Task.classes.get(y,None):
					Logs.error('Erroneous order constraint %r=%r on task class %r'%(x,y,cls.__name__))
		if getattr(cls,'rule',None):
			Logs.error('Erroneous attribute "rule" on task class %r (rename to "run_str")'%cls.__name__)
def replace(m):
	oldcall=getattr(Build.BuildContext,m)
	def call(self,*k,**kw):
		ret=oldcall(self,*k,**kw)
		for x in typos:
			if x in kw:
				if x=='iscopy'and'subst'in getattr(self,'features',''):
					continue
				err=True
				Logs.error('Fix the typo %r -> %r on %r'%(x,typos[x],ret))
		return ret
	setattr(Build.BuildContext,m,call)
def enhance_lib():
	for m in meths_typos:
		replace(m)
	def ant_glob(self,*k,**kw):
		if k:
			lst=Utils.to_list(k[0])
			for pat in lst:
				if'..'in pat.split('/'):
					Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'"%k[0])
		if kw.get('remove',True):
			try:
				if self.is_child_of(self.ctx.bldnode)and not kw.get('quiet',False):
					Logs.error('Using ant_glob on the build folder (%r) is dangerous (quiet=True to disable this warning)'%self)
			except AttributeError:
				pass
		return self.old_ant_glob(*k,**kw)
	Node.Node.old_ant_glob=Node.Node.ant_glob
	Node.Node.ant_glob=ant_glob
	old=Task.is_before
	def is_before(t1,t2):
		ret=old(t1,t2)
		if ret and old(t2,t1):
			Logs.error('Contradictory order constraints in classes %r %r'%(t1,t2))
		return ret
	Task.is_before=is_before
	def check_err_features(self):
		lst=self.to_list(self.features)
		if'shlib'in lst:
			Logs.error('feature shlib -> cshlib, dshlib or cxxshlib')
		for x in('c','cxx','d','fc'):
			if not x in lst and lst and lst[0]in[x+y for y in('program','shlib','stlib')]:
				Logs.error('%r features is probably missing %r'%(self,x))
	TaskGen.feature('*')(check_err_features)
	def check_err_order(self):
		if not hasattr(self,'rule')and not'subst'in Utils.to_list(self.features):
			for x in('before','after','ext_in','ext_out'):
				if hasattr(self,x):
					Logs.warn('Erroneous order constraint %r on non-rule based task generator %r'%(x,self))
		else:
			for x in('before','after'):
				for y in self.to_list(getattr(self,x,[])):
					if not Task.classes.get(y,None):
						Logs.error('Erroneous order constraint %s=%r on %r (no such class)'%(x,y,self))
	TaskGen.feature('*')(check_err_order)
	def check_compile(self):
		check_invalid_constraints(self)
		try:
			ret=self.orig_compile()
		finally:
			check_same_targets(self)
		return ret
	Build.BuildContext.orig_compile=Build.BuildContext.compile
	Build.BuildContext.compile=check_compile
	def use_rec(self,name,**kw):
		try:
			y=self.bld.get_tgen_by_name(name)
		except Errors.WafError:
			pass
		else:
			idx=self.bld.get_group_idx(self)
			odx=self.bld.get_group_idx(y)
			if odx>idx:
				msg="Invalid 'use' across build groups:"
				if Logs.verbose>1:
					msg+='\n  target %r\n  uses:\n  %r'%(self,y)
				else:
					msg+=" %r uses %r (try 'waf -v -v' for the full error)"%(self.name,name)
				raise Errors.WafError(msg)
		self.orig_use_rec(name,**kw)
	TaskGen.task_gen.orig_use_rec=TaskGen.task_gen.use_rec
	TaskGen.task_gen.use_rec=use_rec
	def getattri(self,name,default=None):
		if name=='append'or name=='add':
			raise Errors.WafError('env.append and env.add do not exist: use env.append_value/env.append_unique')
		elif name=='prepend':
			raise Errors.WafError('env.prepend does not exist: use env.prepend_value')
		if name in self.__slots__:
			return object.__getattr__(self,name,default)
		else:
			return self[name]
	ConfigSet.ConfigSet.__getattr__=getattri
def options(opt):
	enhance_lib()
def configure(conf):
	pass
