diff --git a/src/.waf-1.7.11-bbc5cd6dca9f655c3704b49a62d00211/waflib/Tools/c_config.py b/src/.waf-1.7.11-bbc5cd6dca9f655c3704b49a62d00211/waflib/Tools/c_config.py
new file mode 100755
index 0000000..690aa65
--- /dev/null
+++ b/src/.waf-1.7.11-bbc5cd6dca9f655c3704b49a62d00211/waflib/Tools/c_config.py
@@ -0,0 +1,729 @@
+#! /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,shlex,sys
+from waflib import Build,Utils,Task,Options,Logs,Errors,ConfigSet,Runner
+from waflib.TaskGen import after_method,feature
+from waflib.Configure import conf
+WAF_CONFIG_H='config.h'
+DEFKEYS='define_key'
+INCKEYS='include_key'
+cfg_ver={'atleast-version':'>=','exact-version':'==','max-version':'<=',}
+SNIP_FUNCTION='''
+int main(int argc, char **argv) {
+	void *p;
+	(void)argc; (void)argv;
+	p=(void*)(%s);
+	return 0;
+}
+'''
+SNIP_TYPE='''
+int main(int argc, char **argv) {
+	(void)argc; (void)argv;
+	if ((%(type_name)s *) 0) return 0;
+	if (sizeof (%(type_name)s)) return 0;
+	return 1;
+}
+'''
+SNIP_EMPTY_PROGRAM='''
+int main(int argc, char **argv) {
+	(void)argc; (void)argv;
+	return 0;
+}
+'''
+SNIP_FIELD='''
+int main(int argc, char **argv) {
+	char *off;
+	(void)argc; (void)argv;
+	off = (char*) &((%(type_name)s*)0)->%(field_name)s;
+	return (size_t) off < sizeof(%(type_name)s);
+}
+'''
+MACRO_TO_DESTOS={'__linux__':'linux','__GNU__':'gnu','__FreeBSD__':'freebsd','__NetBSD__':'netbsd','__OpenBSD__':'openbsd','__sun':'sunos','__hpux':'hpux','__sgi':'irix','_AIX':'aix','__CYGWIN__':'cygwin','__MSYS__':'msys','_UWIN':'uwin','_WIN64':'win32','_WIN32':'win32','__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__':'darwin','__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__':'darwin','__QNX__':'qnx','__native_client__':'nacl'}
+MACRO_TO_DEST_CPU={'__x86_64__':'x86_64','__amd64__':'x86_64','__i386__':'x86','__ia64__':'ia','__mips__':'mips','__sparc__':'sparc','__alpha__':'alpha','__aarch64__':'aarch64','__thumb__':'thumb','__arm__':'arm','__hppa__':'hppa','__powerpc__':'powerpc','__ppc__':'powerpc','__convex__':'convex','__m68k__':'m68k','__s390x__':'s390x','__s390__':'s390','__sh__':'sh',}
+@conf
+def parse_flags(self,line,uselib_store,env=None,force_static=False):
+	assert(isinstance(line,str))
+	env=env or self.env
+	app=env.append_value
+	appu=env.append_unique
+	lex=shlex.shlex(line,posix=False)
+	lex.whitespace_split=True
+	lex.commenters=''
+	lst=list(lex)
+	uselib=uselib_store
+	while lst:
+		x=lst.pop(0)
+		st=x[:2]
+		ot=x[2:]
+		if st=='-I'or st=='/I':
+			if not ot:ot=lst.pop(0)
+			appu('INCLUDES_'+uselib,[ot])
+		elif st=='-include':
+			tmp=[x,lst.pop(0)]
+			app('CFLAGS',tmp)
+			app('CXXFLAGS',tmp)
+		elif st=='-D'or(env.CXX_NAME=='msvc'and st=='/D'):
+			if not ot:ot=lst.pop(0)
+			app('DEFINES_'+uselib,[ot])
+		elif st=='-l':
+			if not ot:ot=lst.pop(0)
+			prefix=force_static and'STLIB_'or'LIB_'
+			appu(prefix+uselib,[ot])
+		elif st=='-L':
+			if not ot:ot=lst.pop(0)
+			appu('LIBPATH_'+uselib,[ot])
+		elif x.startswith('/LIBPATH:'):
+			appu('LIBPATH_'+uselib,[x.replace('/LIBPATH:','')])
+		elif x=='-pthread'or x.startswith('+')or x.startswith('-std'):
+			app('CFLAGS_'+uselib,[x])
+			app('CXXFLAGS_'+uselib,[x])
+			app('LINKFLAGS_'+uselib,[x])
+		elif x=='-framework':
+			appu('FRAMEWORK_'+uselib,[lst.pop(0)])
+		elif x.startswith('-F'):
+			appu('FRAMEWORKPATH_'+uselib,[x[2:]])
+		elif x.startswith('-Wl'):
+			app('LINKFLAGS_'+uselib,[x])
+		elif x.startswith('-m')or x.startswith('-f')or x.startswith('-dynamic'):
+			app('CFLAGS_'+uselib,[x])
+			app('CXXFLAGS_'+uselib,[x])
+		elif x.startswith('-bundle'):
+			app('LINKFLAGS_'+uselib,[x])
+		elif x.startswith('-undefined'):
+			arg=lst.pop(0)
+			app('LINKFLAGS_'+uselib,[x,arg])
+		elif x.startswith('-arch')or x.startswith('-isysroot'):
+			tmp=[x,lst.pop(0)]
+			app('CFLAGS_'+uselib,tmp)
+			app('CXXFLAGS_'+uselib,tmp)
+			app('LINKFLAGS_'+uselib,tmp)
+		elif x.endswith('.a')or x.endswith('.so')or x.endswith('.dylib')or x.endswith('.lib'):
+			appu('LINKFLAGS_'+uselib,[x])
+@conf
+def ret_msg(self,f,kw):
+	if isinstance(f,str):
+		return f
+	return f(kw)
+@conf
+def validate_cfg(self,kw):
+	if not'path'in kw:
+		if not self.env.PKGCONFIG:
+			self.find_program('pkg-config',var='PKGCONFIG')
+		kw['path']=self.env.PKGCONFIG
+	if'atleast_pkgconfig_version'in kw:
+		if not'msg'in kw:
+			kw['msg']='Checking for pkg-config version >= %r'%kw['atleast_pkgconfig_version']
+		return
+	if not'okmsg'in kw:
+		kw['okmsg']='yes'
+	if not'errmsg'in kw:
+		kw['errmsg']='not found'
+	if'modversion'in kw:
+		if not'msg'in kw:
+			kw['msg']='Checking for %r version'%kw['modversion']
+		return
+	for x in cfg_ver.keys():
+		y=x.replace('-','_')
+		if y in kw:
+			if not'package'in kw:
+				raise ValueError('%s requires a package'%x)
+			if not'msg'in kw:
+				kw['msg']='Checking for %r %s %s'%(kw['package'],cfg_ver[x],kw[y])
+			return
+	if not'msg'in kw:
+		kw['msg']='Checking for %r'%(kw['package']or kw['path'])
+@conf
+def exec_cfg(self,kw):
+	def define_it():
+		self.define(self.have_define(kw.get('uselib_store',kw['package'])),1,0)
+	env=kw.get('env',self.env)
+	run_env=env.env or os.environ
+	if'atleast_pkgconfig_version'in kw:
+		cmd=[kw['path'],'--atleast-pkgconfig-version=%s'%kw['atleast_pkgconfig_version']]
+		self.cmd_and_log(cmd,env=run_env)
+		if not'okmsg'in kw:
+			kw['okmsg']='yes'
+		return
+	for x in cfg_ver:
+		y=x.replace('-','_')
+		if y in kw:
+			self.cmd_and_log([kw['path'],'--%s=%s'%(x,kw[y]),kw['package']],env=run_env)
+			if not'okmsg'in kw:
+				kw['okmsg']='yes'
+			define_it()
+			break
+	if'modversion'in kw:
+		version=self.cmd_and_log([kw['path'],'--modversion',kw['modversion']],env=run_env).strip()
+		self.define('%s_VERSION'%Utils.quote_define_name(kw.get('uselib_store',kw['modversion'])),version)
+		return version
+	lst=[kw['path']]
+	defi=kw.get('define_variable',None)
+	if not defi:
+		defi=self.env.PKG_CONFIG_DEFINES or{}
+	for key,val in defi.items():
+		lst.append('--define-variable=%s=%s'%(key,val))
+	if'variables'in kw:
+		uselib=kw.get('uselib_store',kw['package'].upper())
+		vars=Utils.to_list(kw['variables'])
+		for v in vars:
+			val=self.cmd_and_log(lst+['--variable='+v],env=run_env).strip()
+			var='%s_%s'%(uselib,v)
+			env[var]=val
+		if not'okmsg'in kw:
+			kw['okmsg']='yes'
+		return
+	static=False
+	if'args'in kw:
+		args=Utils.to_list(kw['args'])
+		if'--static'in args or'--static-libs'in args:
+			static=True
+		lst+=args
+	lst.extend(Utils.to_list(kw['package']))
+	ret=self.cmd_and_log(lst,env=run_env)
+	if not'okmsg'in kw:
+		kw['okmsg']='yes'
+	define_it()
+	self.parse_flags(ret,kw.get('uselib_store',kw['package'].upper()),kw.get('env',self.env),force_static=static)
+	return ret
+@conf
+def check_cfg(self,*k,**kw):
+	if k:
+		lst=k[0].split()
+		kw['package']=lst[0]
+		kw['args']=' '.join(lst[1:])
+	self.validate_cfg(kw)
+	if'msg'in kw:
+		self.start_msg(kw['msg'])
+	ret=None
+	try:
+		ret=self.exec_cfg(kw)
+	except self.errors.WafError:
+		if'errmsg'in kw:
+			self.end_msg(kw['errmsg'],'YELLOW')
+		if Logs.verbose>1:
+			raise
+		else:
+			self.fatal('The configuration failed')
+	else:
+		kw['success']=ret
+		if'okmsg'in kw:
+			self.end_msg(self.ret_msg(kw['okmsg'],kw))
+	return ret
+@conf
+def validate_c(self,kw):
+	if not'env'in kw:
+		kw['env']=self.env.derive()
+	env=kw['env']
+	if not'compiler'in kw and not'features'in kw:
+		kw['compiler']='c'
+		if env['CXX_NAME']and Task.classes.get('cxx',None):
+			kw['compiler']='cxx'
+			if not self.env['CXX']:
+				self.fatal('a c++ compiler is required')
+		else:
+			if not self.env['CC']:
+				self.fatal('a c compiler is required')
+	if not'compile_mode'in kw:
+		kw['compile_mode']='c'
+		if'cxx'in Utils.to_list(kw.get('features',[]))or kw.get('compiler','')=='cxx':
+			kw['compile_mode']='cxx'
+	if not'type'in kw:
+		kw['type']='cprogram'
+	if not'features'in kw:
+		kw['features']=[kw['compile_mode'],kw['type']]
+	else:
+		kw['features']=Utils.to_list(kw['features'])
+	if not'compile_filename'in kw:
+		kw['compile_filename']='test.c'+((kw['compile_mode']=='cxx')and'pp'or'')
+	def to_header(dct):
+		if'header_name'in dct:
+			dct=Utils.to_list(dct['header_name'])
+			return''.join(['#include <%s>\n'%x for x in dct])
+		return''
+	if'framework_name'in kw:
+		fwkname=kw['framework_name']
+		if not'uselib_store'in kw:
+			kw['uselib_store']=fwkname.upper()
+		if not kw.get('no_header',False):
+			if not'header_name'in kw:
+				kw['header_name']=[]
+			fwk='%s/%s.h'%(fwkname,fwkname)
+			if kw.get('remove_dot_h',None):
+				fwk=fwk[:-2]
+			kw['header_name']=Utils.to_list(kw['header_name'])+[fwk]
+		kw['msg']='Checking for framework %s'%fwkname
+		kw['framework']=fwkname
+	if'function_name'in kw:
+		fu=kw['function_name']
+		if not'msg'in kw:
+			kw['msg']='Checking for function %s'%fu
+		kw['code']=to_header(kw)+SNIP_FUNCTION%fu
+		if not'uselib_store'in kw:
+			kw['uselib_store']=fu.upper()
+		if not'define_name'in kw:
+			kw['define_name']=self.have_define(fu)
+	elif'type_name'in kw:
+		tu=kw['type_name']
+		if not'header_name'in kw:
+			kw['header_name']='stdint.h'
+		if'field_name'in kw:
+			field=kw['field_name']
+			kw['code']=to_header(kw)+SNIP_FIELD%{'type_name':tu,'field_name':field}
+			if not'msg'in kw:
+				kw['msg']='Checking for field %s in %s'%(field,tu)
+			if not'define_name'in kw:
+				kw['define_name']=self.have_define((tu+'_'+field).upper())
+		else:
+			kw['code']=to_header(kw)+SNIP_TYPE%{'type_name':tu}
+			if not'msg'in kw:
+				kw['msg']='Checking for type %s'%tu
+			if not'define_name'in kw:
+				kw['define_name']=self.have_define(tu.upper())
+	elif'header_name'in kw:
+		if not'msg'in kw:
+			kw['msg']='Checking for header %s'%kw['header_name']
+		l=Utils.to_list(kw['header_name'])
+		assert len(l)>0,'list of headers in header_name is empty'
+		kw['code']=to_header(kw)+SNIP_EMPTY_PROGRAM
+		if not'uselib_store'in kw:
+			kw['uselib_store']=l[0].upper()
+		if not'define_name'in kw:
+			kw['define_name']=self.have_define(l[0])
+	if'lib'in kw:
+		if not'msg'in kw:
+			kw['msg']='Checking for library %s'%kw['lib']
+		if not'uselib_store'in kw:
+			kw['uselib_store']=kw['lib'].upper()
+	if'stlib'in kw:
+		if not'msg'in kw:
+			kw['msg']='Checking for static library %s'%kw['stlib']
+		if not'uselib_store'in kw:
+			kw['uselib_store']=kw['stlib'].upper()
+	if'fragment'in kw:
+		kw['code']=kw['fragment']
+		if not'msg'in kw:
+			kw['msg']='Checking for code snippet'
+		if not'errmsg'in kw:
+			kw['errmsg']='no'
+	for(flagsname,flagstype)in[('cxxflags','compiler'),('cflags','compiler'),('linkflags','linker')]:
+		if flagsname in kw:
+			if not'msg'in kw:
+				kw['msg']='Checking for %s flags %s'%(flagstype,kw[flagsname])
+			if not'errmsg'in kw:
+				kw['errmsg']='no'
+	if not'execute'in kw:
+		kw['execute']=False
+	if kw['execute']:
+		kw['features'].append('test_exec')
+	if not'errmsg'in kw:
+		kw['errmsg']='not found'
+	if not'okmsg'in kw:
+		kw['okmsg']='yes'
+	if not'code'in kw:
+		kw['code']=SNIP_EMPTY_PROGRAM
+	if self.env[INCKEYS]:
+		kw['code']='\n'.join(['#include <%s>'%x for x in self.env[INCKEYS]])+'\n'+kw['code']
+	if not kw.get('success'):kw['success']=None
+	if'define_name'in kw:
+		self.undefine(kw['define_name'])
+	assert'msg'in kw,'invalid parameters, read http://freehackers.org/~tnagy/wafbook/single.html#config_helpers_c'
+@conf
+def post_check(self,*k,**kw):
+	is_success=0
+	if kw['execute']:
+		if kw['success']is not None:
+			if kw.get('define_ret',False):
+				is_success=kw['success']
+			else:
+				is_success=(kw['success']==0)
+	else:
+		is_success=(kw['success']==0)
+	if'define_name'in kw:
+		if'header_name'in kw or'function_name'in kw or'type_name'in kw or'fragment'in kw:
+			if kw['execute']and kw.get('define_ret',None)and isinstance(is_success,str):
+				self.define(kw['define_name'],is_success,quote=kw.get('quote',1))
+			else:
+				self.define_cond(kw['define_name'],is_success)
+		else:
+			self.define_cond(kw['define_name'],is_success)
+	if'header_name'in kw:
+		if kw.get('auto_add_header_name',False):
+			self.env.append_value(INCKEYS,Utils.to_list(kw['header_name']))
+	if is_success and'uselib_store'in kw:
+		from waflib.Tools import ccroot
+		_vars=set([])
+		for x in kw['features']:
+			if x in ccroot.USELIB_VARS:
+				_vars|=ccroot.USELIB_VARS[x]
+		for k in _vars:
+			lk=k.lower()
+			if k=='INCLUDES':lk='includes'
+			if k=='DEFINES':lk='defines'
+			if lk in kw:
+				val=kw[lk]
+				if isinstance(val,str):
+					val=val.rstrip(os.path.sep)
+				self.env.append_unique(k+'_'+kw['uselib_store'],val)
+	return is_success
+@conf
+def check(self,*k,**kw):
+	self.validate_c(kw)
+	self.start_msg(kw['msg'])
+	ret=None
+	try:
+		ret=self.run_c_code(*k,**kw)
+	except self.errors.ConfigurationError:
+		self.end_msg(kw['errmsg'],'YELLOW')
+		if Logs.verbose>1:
+			raise
+		else:
+			self.fatal('The configuration failed')
+	else:
+		kw['success']=ret
+	ret=self.post_check(*k,**kw)
+	if not ret:
+		self.end_msg(kw['errmsg'],'YELLOW')
+		self.fatal('The configuration failed %r'%ret)
+	else:
+		self.end_msg(self.ret_msg(kw['okmsg'],kw))
+	return ret
+class test_exec(Task.Task):
+	color='PINK'
+	def run(self):
+		if getattr(self.generator,'rpath',None):
+			if getattr(self.generator,'define_ret',False):
+				self.generator.bld.retval=self.generator.bld.cmd_and_log([self.inputs[0].abspath()])
+			else:
+				self.generator.bld.retval=self.generator.bld.exec_command([self.inputs[0].abspath()])
+		else:
+			env=self.env.env or{}
+			env.update(dict(os.environ))
+			for var in('LD_LIBRARY_PATH','DYLD_LIBRARY_PATH','PATH'):
+				env[var]=self.inputs[0].parent.abspath()+os.path.pathsep+env.get(var,'')
+			if getattr(self.generator,'define_ret',False):
+				self.generator.bld.retval=self.generator.bld.cmd_and_log([self.inputs[0].abspath()],env=env)
+			else:
+				self.generator.bld.retval=self.generator.bld.exec_command([self.inputs[0].abspath()],env=env)
+@feature('test_exec')
+@after_method('apply_link')
+def test_exec_fun(self):
+	self.create_task('test_exec',self.link_task.outputs[0])
+CACHE_RESULTS=1
+COMPILE_ERRORS=2
+@conf
+def run_c_code(self,*k,**kw):
+	lst=[str(v)for(p,v)in kw.items()if p!='env']
+	h=Utils.h_list(lst)
+	dir=self.bldnode.abspath()+os.sep+(not Utils.is_win32 and'.'or'')+'conf_check_'+Utils.to_hex(h)
+	try:
+		os.makedirs(dir)
+	except OSError:
+		pass
+	try:
+		os.stat(dir)
+	except OSError:
+		self.fatal('cannot use the configuration test folder %r'%dir)
+	cachemode=getattr(Options.options,'confcache',None)
+	if cachemode==CACHE_RESULTS:
+		try:
+			proj=ConfigSet.ConfigSet(os.path.join(dir,'cache_run_c_code'))
+		except OSError:
+			pass
+		else:
+			ret=proj['cache_run_c_code']
+			if isinstance(ret,str)and ret.startswith('Test does not build'):
+				self.fatal(ret)
+			return ret
+	bdir=os.path.join(dir,'testbuild')
+	if not os.path.exists(bdir):
+		os.makedirs(bdir)
+	self.test_bld=bld=Build.BuildContext(top_dir=dir,out_dir=bdir)
+	bld.init_dirs()
+	bld.progress_bar=0
+	bld.targets='*'
+	if kw['compile_filename']:
+		node=bld.srcnode.make_node(kw['compile_filename'])
+		node.write(kw['code'])
+	bld.logger=self.logger
+	bld.all_envs.update(self.all_envs)
+	bld.env=kw['env']
+	o=bld(features=kw['features'],source=kw['compile_filename'],target='testprog')
+	for k,v in kw.items():
+		setattr(o,k,v)
+	self.to_log("==>\n%s\n<=="%kw['code'])
+	bld.targets='*'
+	ret=-1
+	try:
+		try:
+			bld.compile()
+		except Errors.WafError:
+			ret='Test does not build: %s'%Utils.ex_stack()
+			self.fatal(ret)
+		else:
+			ret=getattr(bld,'retval',0)
+	finally:
+		proj=ConfigSet.ConfigSet()
+		proj['cache_run_c_code']=ret
+		proj.store(os.path.join(dir,'cache_run_c_code'))
+	return ret
+@conf
+def check_cxx(self,*k,**kw):
+	kw['compiler']='cxx'
+	return self.check(*k,**kw)
+@conf
+def check_cc(self,*k,**kw):
+	kw['compiler']='c'
+	return self.check(*k,**kw)
+@conf
+def define(self,key,val,quote=True):
+	assert key and isinstance(key,str)
+	if val is True:
+		val=1
+	elif val in(False,None):
+		val=0
+	if isinstance(val,int)or isinstance(val,float):
+		s='%s=%s'
+	else:
+		s=quote and'%s="%s"'or'%s=%s'
+	app=s%(key,str(val))
+	ban=key+'='
+	lst=self.env['DEFINES']
+	for x in lst:
+		if x.startswith(ban):
+			lst[lst.index(x)]=app
+			break
+	else:
+		self.env.append_value('DEFINES',app)
+	self.env.append_unique(DEFKEYS,key)
+@conf
+def undefine(self,key):
+	assert key and isinstance(key,str)
+	ban=key+'='
+	lst=[x for x in self.env['DEFINES']if not x.startswith(ban)]
+	self.env['DEFINES']=lst
+	self.env.append_unique(DEFKEYS,key)
+@conf
+def define_cond(self,key,val):
+	assert key and isinstance(key,str)
+	if val:
+		self.define(key,1)
+	else:
+		self.undefine(key)
+@conf
+def is_defined(self,key):
+	assert key and isinstance(key,str)
+	ban=key+'='
+	for x in self.env['DEFINES']:
+		if x.startswith(ban):
+			return True
+	return False
+@conf
+def get_define(self,key):
+	assert key and isinstance(key,str)
+	ban=key+'='
+	for x in self.env['DEFINES']:
+		if x.startswith(ban):
+			return x[len(ban):]
+	return None
+@conf
+def have_define(self,key):
+	return(self.env.HAVE_PAT or'HAVE_%s')%Utils.quote_define_name(key)
+@conf
+def write_config_header(self,configfile='',guard='',top=False,env=None,defines=True,headers=False,remove=True,define_prefix=''):
+	if env:
+		Logs.warn('Cannot pass env to write_config_header')
+	if not configfile:configfile=WAF_CONFIG_H
+	waf_guard=guard or'W_%s_WAF'%Utils.quote_define_name(configfile)
+	node=top and self.bldnode or self.path.get_bld()
+	node=node.make_node(configfile)
+	node.parent.mkdir()
+	lst=['/* WARNING! All changes made to this file will be lost! */\n']
+	lst.append('#ifndef %s\n#define %s\n'%(waf_guard,waf_guard))
+	lst.append(self.get_config_header(defines,headers,define_prefix=define_prefix))
+	lst.append('\n#endif /* %s */\n'%waf_guard)
+	node.write('\n'.join(lst))
+	self.env.append_unique(Build.CFG_FILES,[node.abspath()])
+	if remove:
+		for key in self.env[DEFKEYS]:
+			self.undefine(key)
+		self.env[DEFKEYS]=[]
+@conf
+def get_config_header(self,defines=True,headers=False,define_prefix=''):
+	lst=[]
+	if headers:
+		for x in self.env[INCKEYS]:
+			lst.append('#include <%s>'%x)
+	if defines:
+		for x in self.env[DEFKEYS]:
+			if self.is_defined(x):
+				val=self.get_define(x)
+				lst.append('#define %s %s'%(define_prefix+x,val))
+			else:
+				lst.append('/* #undef %s */'%(define_prefix+x))
+	return"\n".join(lst)
+@conf
+def cc_add_flags(conf):
+	conf.add_os_flags('CPPFLAGS','CFLAGS')
+	conf.add_os_flags('CFLAGS')
+@conf
+def cxx_add_flags(conf):
+	conf.add_os_flags('CPPFLAGS','CXXFLAGS')
+	conf.add_os_flags('CXXFLAGS')
+@conf
+def link_add_flags(conf):
+	conf.add_os_flags('LINKFLAGS')
+	conf.add_os_flags('LDFLAGS','LINKFLAGS')
+@conf
+def cc_load_tools(conf):
+	if not conf.env.DEST_OS:
+		conf.env.DEST_OS=Utils.unversioned_sys_platform()
+	conf.load('c')
+@conf
+def cxx_load_tools(conf):
+	if not conf.env.DEST_OS:
+		conf.env.DEST_OS=Utils.unversioned_sys_platform()
+	conf.load('cxx')
+@conf
+def get_cc_version(conf,cc,gcc=False,icc=False):
+	cmd=cc+['-dM','-E','-']
+	env=conf.env.env or None
+	try:
+		p=Utils.subprocess.Popen(cmd,stdin=Utils.subprocess.PIPE,stdout=Utils.subprocess.PIPE,stderr=Utils.subprocess.PIPE,env=env)
+		p.stdin.write('\n')
+		out=p.communicate()[0]
+	except Exception:
+		conf.fatal('Could not determine the compiler version %r'%cmd)
+	if not isinstance(out,str):
+		out=out.decode(sys.stdout.encoding or'iso8859-1')
+	if gcc:
+		if out.find('__INTEL_COMPILER')>=0:
+			conf.fatal('The intel compiler pretends to be gcc')
+		if out.find('__GNUC__')<0 and out.find('__clang__')<0:
+			conf.fatal('Could not determine the compiler type')
+	if icc and out.find('__INTEL_COMPILER')<0:
+		conf.fatal('Not icc/icpc')
+	k={}
+	if icc or gcc:
+		out=out.splitlines()
+		for line in out:
+			lst=shlex.split(line)
+			if len(lst)>2:
+				key=lst[1]
+				val=lst[2]
+				k[key]=val
+		def isD(var):
+			return var in k
+		def isT(var):
+			return var in k and k[var]!='0'
+		if not conf.env.DEST_OS:
+			conf.env.DEST_OS=''
+		for i in MACRO_TO_DESTOS:
+			if isD(i):
+				conf.env.DEST_OS=MACRO_TO_DESTOS[i]
+				break
+		else:
+			if isD('__APPLE__')and isD('__MACH__'):
+				conf.env.DEST_OS='darwin'
+			elif isD('__unix__'):
+				conf.env.DEST_OS='generic'
+		if isD('__ELF__'):
+			conf.env.DEST_BINFMT='elf'
+		elif isD('__WINNT__')or isD('__CYGWIN__')or isD('_WIN32'):
+			conf.env.DEST_BINFMT='pe'
+			conf.env.LIBDIR=conf.env.BINDIR
+		elif isD('__APPLE__'):
+			conf.env.DEST_BINFMT='mac-o'
+		if not conf.env.DEST_BINFMT:
+			conf.env.DEST_BINFMT=Utils.destos_to_binfmt(conf.env.DEST_OS)
+		for i in MACRO_TO_DEST_CPU:
+			if isD(i):
+				conf.env.DEST_CPU=MACRO_TO_DEST_CPU[i]
+				break
+		Logs.debug('ccroot: dest platform: '+' '.join([conf.env[x]or'?'for x in('DEST_OS','DEST_BINFMT','DEST_CPU')]))
+		if icc:
+			ver=k['__INTEL_COMPILER']
+			conf.env['CC_VERSION']=(ver[:-2],ver[-2],ver[-1])
+		else:
+			if isD('__clang__'):
+				conf.env['CC_VERSION']=(k['__clang_major__'],k['__clang_minor__'],k['__clang_patchlevel__'])
+			else:
+				conf.env['CC_VERSION']=(k['__GNUC__'],k['__GNUC_MINOR__'],k['__GNUC_PATCHLEVEL__'])
+	return k
+@conf
+def get_xlc_version(conf,cc):
+	cmd=cc+['-qversion']
+	try:
+		out,err=conf.cmd_and_log(cmd,output=0)
+	except Errors.WafError:
+		conf.fatal('Could not find xlc %r'%cmd)
+	for v in(r"IBM XL C/C\+\+.* V(?P<major>\d*)\.(?P<minor>\d*)",):
+		version_re=re.compile(v,re.I).search
+		match=version_re(out or err)
+		if match:
+			k=match.groupdict()
+			conf.env['CC_VERSION']=(k['major'],k['minor'])
+			break
+	else:
+		conf.fatal('Could not determine the XLC version.')
+@conf
+def add_as_needed(self):
+	if self.env.DEST_BINFMT=='elf'and'gcc'in(self.env.CXX_NAME,self.env.CC_NAME):
+		self.env.append_unique('LINKFLAGS','--as-needed')
+class cfgtask(Task.TaskBase):
+	def display(self):
+		return''
+	def runnable_status(self):
+		return Task.RUN_ME
+	def uid(self):
+		return Utils.SIG_NIL
+	def run(self):
+		conf=self.conf
+		bld=Build.BuildContext(top_dir=conf.srcnode.abspath(),out_dir=conf.bldnode.abspath())
+		bld.env=conf.env
+		bld.init_dirs()
+		bld.in_msg=1
+		bld.logger=self.logger
+		try:
+			bld.check(**self.args)
+		except Exception:
+			return 1
+@conf
+def multicheck(self,*k,**kw):
+	self.start_msg(kw.get('msg','Executing %d configuration tests'%len(k)))
+	class par(object):
+		def __init__(self):
+			self.keep=False
+			self.cache_global=Options.cache_global
+			self.nocache=Options.options.nocache
+			self.returned_tasks=[]
+			self.task_sigs={}
+		def total(self):
+			return len(tasks)
+		def to_log(self,*k,**kw):
+			return
+	bld=par()
+	tasks=[]
+	for dct in k:
+		x=cfgtask(bld=bld)
+		tasks.append(x)
+		x.args=dct
+		x.bld=bld
+		x.conf=self
+		x.args=dct
+		x.logger=Logs.make_mem_logger(str(id(x)),self.logger)
+	def it():
+		yield tasks
+		while 1:
+			yield[]
+	p=Runner.Parallel(bld,Options.options.jobs)
+	p.biter=it()
+	p.start()
+	for x in tasks:
+		x.logger.memhandler.flush()
+	for x in tasks:
+		if x.hasrun!=Task.SUCCESS:
+			self.end_msg(kw.get('errmsg','no'),color='YELLOW')
+			self.fatal(kw.get('fatalmsg',None)or'One of the tests has failed, see the config.log for more information')
+	self.end_msg('ok')
