diff --git a/src/.waf-1.7.11-bbc5cd6dca9f655c3704b49a62d00211/waflib/TaskGen.py b/src/.waf-1.7.11-bbc5cd6dca9f655c3704b49a62d00211/waflib/TaskGen.py
new file mode 100644
index 0000000..4e04239
--- /dev/null
+++ b/src/.waf-1.7.11-bbc5cd6dca9f655c3704b49a62d00211/waflib/TaskGen.py
@@ -0,0 +1,404 @@
+#! /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 copy,re,os
+from waflib import Task,Utils,Logs,Errors,ConfigSet,Node
+feats=Utils.defaultdict(set)
+class task_gen(object):
+	mappings={}
+	prec=Utils.defaultdict(list)
+	def __init__(self,*k,**kw):
+		self.source=''
+		self.target=''
+		self.meths=[]
+		self.prec=Utils.defaultdict(list)
+		self.mappings={}
+		self.features=[]
+		self.tasks=[]
+		if not'bld'in kw:
+			self.env=ConfigSet.ConfigSet()
+			self.idx=0
+			self.path=None
+		else:
+			self.bld=kw['bld']
+			self.env=self.bld.env.derive()
+			self.path=self.bld.path
+			try:
+				self.idx=self.bld.idx[id(self.path)]=self.bld.idx.get(id(self.path),0)+1
+			except AttributeError:
+				self.bld.idx={}
+				self.idx=self.bld.idx[id(self.path)]=1
+		for key,val in kw.items():
+			setattr(self,key,val)
+	def __str__(self):
+		return"<task_gen %r declared in %s>"%(self.name,self.path.abspath())
+	def __repr__(self):
+		lst=[]
+		for x in self.__dict__.keys():
+			if x not in['env','bld','compiled_tasks','tasks']:
+				lst.append("%s=%s"%(x,repr(getattr(self,x))))
+		return"bld(%s) in %s"%(", ".join(lst),self.path.abspath())
+	def get_name(self):
+		try:
+			return self._name
+		except AttributeError:
+			if isinstance(self.target,list):
+				lst=[str(x)for x in self.target]
+				name=self._name=','.join(lst)
+			else:
+				name=self._name=str(self.target)
+			return name
+	def set_name(self,name):
+		self._name=name
+	name=property(get_name,set_name)
+	def to_list(self,val):
+		if isinstance(val,str):return val.split()
+		else:return val
+	def post(self):
+		if getattr(self,'posted',None):
+			return False
+		self.posted=True
+		keys=set(self.meths)
+		self.features=Utils.to_list(self.features)
+		for x in self.features+['*']:
+			st=feats[x]
+			if not st:
+				if not x in Task.classes:
+					Logs.warn('feature %r does not exist - bind at least one method to it'%x)
+			keys.update(list(st))
+		prec={}
+		prec_tbl=self.prec or task_gen.prec
+		for x in prec_tbl:
+			if x in keys:
+				prec[x]=prec_tbl[x]
+		tmp=[]
+		for a in keys:
+			for x in prec.values():
+				if a in x:break
+			else:
+				tmp.append(a)
+		tmp.sort()
+		out=[]
+		while tmp:
+			e=tmp.pop()
+			if e in keys:out.append(e)
+			try:
+				nlst=prec[e]
+			except KeyError:
+				pass
+			else:
+				del prec[e]
+				for x in nlst:
+					for y in prec:
+						if x in prec[y]:
+							break
+					else:
+						tmp.append(x)
+		if prec:
+			raise Errors.WafError('Cycle detected in the method execution %r'%prec)
+		out.reverse()
+		self.meths=out
+		Logs.debug('task_gen: posting %s %d'%(self,id(self)))
+		for x in out:
+			try:
+				v=getattr(self,x)
+			except AttributeError:
+				raise Errors.WafError('%r is not a valid task generator method'%x)
+			Logs.debug('task_gen: -> %s (%d)'%(x,id(self)))
+			v()
+		Logs.debug('task_gen: posted %s'%self.name)
+		return True
+	def get_hook(self,node):
+		name=node.name
+		for k in self.mappings:
+			if name.endswith(k):
+				return self.mappings[k]
+		for k in task_gen.mappings:
+			if name.endswith(k):
+				return task_gen.mappings[k]
+		raise Errors.WafError("File %r has no mapping in %r (did you forget to load a waf tool?)"%(node,task_gen.mappings.keys()))
+	def create_task(self,name,src=None,tgt=None):
+		task=Task.classes[name](env=self.env.derive(),generator=self)
+		if src:
+			task.set_inputs(src)
+		if tgt:
+			task.set_outputs(tgt)
+		self.tasks.append(task)
+		return task
+	def clone(self,env):
+		newobj=self.bld()
+		for x in self.__dict__:
+			if x in['env','bld']:
+				continue
+			elif x in['path','features']:
+				setattr(newobj,x,getattr(self,x))
+			else:
+				setattr(newobj,x,copy.copy(getattr(self,x)))
+		newobj.posted=False
+		if isinstance(env,str):
+			newobj.env=self.bld.all_envs[env].derive()
+		else:
+			newobj.env=env.derive()
+		return newobj
+def declare_chain(name='',rule=None,reentrant=None,color='BLUE',ext_in=[],ext_out=[],before=[],after=[],decider=None,scan=None,install_path=None,shell=False):
+	ext_in=Utils.to_list(ext_in)
+	ext_out=Utils.to_list(ext_out)
+	if not name:
+		name=rule
+	cls=Task.task_factory(name,rule,color=color,ext_in=ext_in,ext_out=ext_out,before=before,after=after,scan=scan,shell=shell)
+	def x_file(self,node):
+		ext=decider and decider(self,node)or cls.ext_out
+		if ext_in:
+			_ext_in=ext_in[0]
+		tsk=self.create_task(name,node)
+		cnt=0
+		keys=list(self.mappings.keys())+list(self.__class__.mappings.keys())
+		for x in ext:
+			k=node.change_ext(x,ext_in=_ext_in)
+			tsk.outputs.append(k)
+			if reentrant!=None:
+				if cnt<int(reentrant):
+					self.source.append(k)
+			else:
+				for y in keys:
+					if k.name.endswith(y):
+						self.source.append(k)
+						break
+			cnt+=1
+		if install_path:
+			self.bld.install_files(install_path,tsk.outputs)
+		return tsk
+	for x in cls.ext_in:
+		task_gen.mappings[x]=x_file
+	return x_file
+def taskgen_method(func):
+	setattr(task_gen,func.__name__,func)
+	return func
+def feature(*k):
+	def deco(func):
+		setattr(task_gen,func.__name__,func)
+		for name in k:
+			feats[name].update([func.__name__])
+		return func
+	return deco
+def before_method(*k):
+	def deco(func):
+		setattr(task_gen,func.__name__,func)
+		for fun_name in k:
+			if not func.__name__ in task_gen.prec[fun_name]:
+				task_gen.prec[fun_name].append(func.__name__)
+		return func
+	return deco
+before=before_method
+def after_method(*k):
+	def deco(func):
+		setattr(task_gen,func.__name__,func)
+		for fun_name in k:
+			if not fun_name in task_gen.prec[func.__name__]:
+				task_gen.prec[func.__name__].append(fun_name)
+		return func
+	return deco
+after=after_method
+def extension(*k):
+	def deco(func):
+		setattr(task_gen,func.__name__,func)
+		for x in k:
+			task_gen.mappings[x]=func
+		return func
+	return deco
+@taskgen_method
+def to_nodes(self,lst,path=None):
+	tmp=[]
+	path=path or self.path
+	find=path.find_resource
+	if isinstance(lst,self.path.__class__):
+		lst=[lst]
+	for x in Utils.to_list(lst):
+		if isinstance(x,str):
+			node=find(x)
+		else:
+			node=x
+		if not node:
+			raise Errors.WafError("source not found: %r in %r"%(x,self))
+		tmp.append(node)
+	return tmp
+@feature('*')
+def process_source(self):
+	self.source=self.to_nodes(getattr(self,'source',[]))
+	for node in self.source:
+		self.get_hook(node)(self,node)
+@feature('*')
+@before_method('process_source')
+def process_rule(self):
+	if not getattr(self,'rule',None):
+		return
+	name=str(getattr(self,'name',None)or self.target or getattr(self.rule,'__name__',self.rule))
+	try:
+		cache=self.bld.cache_rule_attr
+	except AttributeError:
+		cache=self.bld.cache_rule_attr={}
+	cls=None
+	if getattr(self,'cache_rule','True'):
+		try:
+			cls=cache[(name,self.rule)]
+		except KeyError:
+			pass
+	if not cls:
+		cls=Task.task_factory(name,self.rule,getattr(self,'vars',[]),shell=getattr(self,'shell',True),color=getattr(self,'color','BLUE'),scan=getattr(self,'scan',None))
+		if getattr(self,'scan',None):
+			cls.scan=self.scan
+		elif getattr(self,'deps',None):
+			def scan(self):
+				nodes=[]
+				for x in self.generator.to_list(getattr(self.generator,'deps',None)):
+					node=self.generator.path.find_resource(x)
+					if not node:
+						self.generator.bld.fatal('Could not find %r (was it declared?)'%x)
+					nodes.append(node)
+				return[nodes,[]]
+			cls.scan=scan
+		if getattr(self,'update_outputs',None):
+			Task.update_outputs(cls)
+		if getattr(self,'always',None):
+			Task.always_run(cls)
+		for x in['after','before','ext_in','ext_out']:
+			setattr(cls,x,getattr(self,x,[]))
+		if getattr(self,'cache_rule','True'):
+			cache[(name,self.rule)]=cls
+	tsk=self.create_task(name)
+	if getattr(self,'target',None):
+		if isinstance(self.target,str):
+			self.target=self.target.split()
+		if not isinstance(self.target,list):
+			self.target=[self.target]
+		for x in self.target:
+			if isinstance(x,str):
+				tsk.outputs.append(self.path.find_or_declare(x))
+			else:
+				x.parent.mkdir()
+				tsk.outputs.append(x)
+		if getattr(self,'install_path',None):
+			self.bld.install_files(self.install_path,tsk.outputs)
+	if getattr(self,'source',None):
+		tsk.inputs=self.to_nodes(self.source)
+		self.source=[]
+	if getattr(self,'cwd',None):
+		tsk.cwd=self.cwd
+@feature('seq')
+def sequence_order(self):
+	if self.meths and self.meths[-1]!='sequence_order':
+		self.meths.append('sequence_order')
+		return
+	if getattr(self,'seq_start',None):
+		return
+	if getattr(self.bld,'prev',None):
+		self.bld.prev.post()
+		for x in self.bld.prev.tasks:
+			for y in self.tasks:
+				y.set_run_after(x)
+	self.bld.prev=self
+re_m4=re.compile('@(\w+)@',re.M)
+class subst_pc(Task.Task):
+	def run(self):
+		if getattr(self.generator,'is_copy',None):
+			self.outputs[0].write(self.inputs[0].read('rb'),'wb')
+			if getattr(self.generator,'chmod',None):
+				os.chmod(self.outputs[0].abspath(),self.generator.chmod)
+			return None
+		if getattr(self.generator,'fun',None):
+			self.generator.fun(self)
+		code=self.inputs[0].read(encoding=getattr(self.generator,'encoding','ISO8859-1'))
+		if getattr(self.generator,'subst_fun',None):
+			code=self.generator.subst_fun(self,code)
+			if code:
+				self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','ISO8859-1'))
+			return
+		code=code.replace('%','%%')
+		lst=[]
+		def repl(match):
+			g=match.group
+			if g(1):
+				lst.append(g(1))
+				return"%%(%s)s"%g(1)
+			return''
+		code=re_m4.sub(repl,code)
+		try:
+			d=self.generator.dct
+		except AttributeError:
+			d={}
+			for x in lst:
+				tmp=getattr(self.generator,x,'')or self.env.get_flat(x)or self.env.get_flat(x.upper())
+				d[x]=str(tmp)
+		code=code%d
+		self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','ISO8859-1'))
+		self.generator.bld.raw_deps[self.uid()]=self.dep_vars=lst
+		try:delattr(self,'cache_sig')
+		except AttributeError:pass
+		if getattr(self.generator,'chmod',None):
+			os.chmod(self.outputs[0].abspath(),self.generator.chmod)
+	def sig_vars(self):
+		bld=self.generator.bld
+		env=self.env
+		upd=self.m.update
+		if getattr(self.generator,'fun',None):
+			upd(Utils.h_fun(self.generator.fun))
+		if getattr(self.generator,'subst_fun',None):
+			upd(Utils.h_fun(self.generator.subst_fun))
+		vars=self.generator.bld.raw_deps.get(self.uid(),[])
+		act_sig=bld.hash_env_vars(env,vars)
+		upd(act_sig)
+		lst=[getattr(self.generator,x,'')for x in vars]
+		upd(Utils.h_list(lst))
+		return self.m.digest()
+@extension('.pc.in')
+def add_pcfile(self,node):
+	tsk=self.create_task('subst_pc',node,node.change_ext('.pc','.pc.in'))
+	self.bld.install_files(getattr(self,'install_path','${LIBDIR}/pkgconfig/'),tsk.outputs)
+class subst(subst_pc):
+	pass
+@feature('subst')
+@before_method('process_source','process_rule')
+def process_subst(self):
+	src=Utils.to_list(getattr(self,'source',[]))
+	if isinstance(src,Node.Node):
+		src=[src]
+	tgt=Utils.to_list(getattr(self,'target',[]))
+	if isinstance(tgt,Node.Node):
+		tgt=[tgt]
+	if len(src)!=len(tgt):
+		raise Errors.WafError('invalid number of source/target for %r'%self)
+	for x,y in zip(src,tgt):
+		if not x or not y:
+			raise Errors.WafError('null source or target for %r'%self)
+		a,b=None,None
+		if isinstance(x,str)and isinstance(y,str)and x==y:
+			a=self.path.find_node(x)
+			b=self.path.get_bld().make_node(y)
+			if not os.path.isfile(b.abspath()):
+				b.sig=None
+				b.parent.mkdir()
+		else:
+			if isinstance(x,str):
+				a=self.path.find_resource(x)
+			elif isinstance(x,Node.Node):
+				a=x
+			if isinstance(y,str):
+				b=self.path.find_or_declare(y)
+			elif isinstance(y,Node.Node):
+				b=y
+		if not a:
+			raise Errors.WafError('cound not find %r for %r'%(x,self))
+		has_constraints=False
+		tsk=self.create_task('subst',a,b)
+		for k in('after','before','ext_in','ext_out'):
+			val=getattr(self,k,None)
+			if val:
+				has_constraints=True
+				setattr(tsk,k,val)
+		if not has_constraints and b.name.endswith('.h'):
+			tsk.before=[k for k in('c','cxx')if k in Task.classes]
+		inst_to=getattr(self,'install_path',None)
+		if inst_to:
+			self.bld.install_files(inst_to,b,chmod=getattr(self,'chmod',Utils.O644))
+	self.source=[]
