1#! /usr/bin/env python
2# encoding: utf-8
3# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file
4
5import os,re,shlex
6from waflib import Build,Utils,Task,Options,Logs,Errors,Runner
7from waflib.TaskGen import after_method,feature
8from waflib.Configure import conf
9WAF_CONFIG_H='config.h'
10DEFKEYS='define_key'
11INCKEYS='include_key'
12cfg_ver={'atleast-version':'>=','exact-version':'==','max-version':'<=',}
13SNIP_FUNCTION='''
14int main(int argc, char **argv) {
15	void (*p)();
16	(void)argc; (void)argv;
17	p=(void(*)())(%s);
18	return !p;
19}
20'''
21SNIP_TYPE='''
22int main(int argc, char **argv) {
23	(void)argc; (void)argv;
24	if ((%(type_name)s *) 0) return 0;
25	if (sizeof (%(type_name)s)) return 0;
26	return 1;
27}
28'''
29SNIP_EMPTY_PROGRAM='''
30int main(int argc, char **argv) {
31	(void)argc; (void)argv;
32	return 0;
33}
34'''
35SNIP_FIELD='''
36int main(int argc, char **argv) {
37	char *off;
38	(void)argc; (void)argv;
39	off = (char*) &((%(type_name)s*)0)->%(field_name)s;
40	return (size_t) off < sizeof(%(type_name)s);
41}
42'''
43MACRO_TO_DESTOS={'__linux__':'linux','__GNU__':'gnu','__FreeBSD__':'freebsd','__NetBSD__':'netbsd','__OpenBSD__':'openbsd','__sun':'sunos','__hpux':'hpux','__sgi':'irix','_AIX':'aix','__CYGWIN__':'cygwin','__MSYS__':'cygwin','_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'}
44MACRO_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','__xtensa__':'xtensa',}
45@conf
46def parse_flags(self,line,uselib_store,env=None,force_static=False,posix=None):
47	assert(isinstance(line,str))
48	env=env or self.env
49	if posix is None:
50		posix=True
51		if'\\'in line:
52			posix=('\\ 'in line)or('\\\\'in line)
53	lex=shlex.shlex(line,posix=posix)
54	lex.whitespace_split=True
55	lex.commenters=''
56	lst=list(lex)
57	uselib=uselib_store
58	def app(var,val):
59		env.append_value('%s_%s'%(var,uselib),val)
60	def appu(var,val):
61		env.append_unique('%s_%s'%(var,uselib),val)
62	static=False
63	while lst:
64		x=lst.pop(0)
65		st=x[:2]
66		ot=x[2:]
67		if st=='-I'or st=='/I':
68			if not ot:
69				ot=lst.pop(0)
70			appu('INCLUDES',ot)
71		elif st=='-i':
72			tmp=[x,lst.pop(0)]
73			app('CFLAGS',tmp)
74			app('CXXFLAGS',tmp)
75		elif st=='-D'or(env.CXX_NAME=='msvc'and st=='/D'):
76			if not ot:
77				ot=lst.pop(0)
78			app('DEFINES',ot)
79		elif st=='-l':
80			if not ot:
81				ot=lst.pop(0)
82			prefix='STLIB'if(force_static or static)else'LIB'
83			app(prefix,ot)
84		elif st=='-L':
85			if not ot:
86				ot=lst.pop(0)
87			prefix='STLIBPATH'if(force_static or static)else'LIBPATH'
88			appu(prefix,ot)
89		elif x.startswith('/LIBPATH:'):
90			prefix='STLIBPATH'if(force_static or static)else'LIBPATH'
91			appu(prefix,x.replace('/LIBPATH:',''))
92		elif x.startswith('-std='):
93			prefix='CXXFLAGS'if'++'in x else'CFLAGS'
94			app(prefix,x)
95		elif x=='-pthread'or x.startswith('+'):
96			app('CFLAGS',x)
97			app('CXXFLAGS',x)
98			app('LINKFLAGS',x)
99		elif x=='-framework':
100			appu('FRAMEWORK',lst.pop(0))
101		elif x.startswith('-F'):
102			appu('FRAMEWORKPATH',x[2:])
103		elif x=='-Wl,-rpath'or x=='-Wl,-R':
104			app('RPATH',lst.pop(0).lstrip('-Wl,'))
105		elif x.startswith('-Wl,-R,'):
106			app('RPATH',x[7:])
107		elif x.startswith('-Wl,-R'):
108			app('RPATH',x[6:])
109		elif x.startswith('-Wl,-rpath,'):
110			app('RPATH',x[11:])
111		elif x=='-Wl,-Bstatic'or x=='-Bstatic':
112			static=True
113		elif x=='-Wl,-Bdynamic'or x=='-Bdynamic':
114			static=False
115		elif x.startswith('-Wl'):
116			app('LINKFLAGS',x)
117		elif x.startswith(('-m','-f','-dynamic')):
118			app('CFLAGS',x)
119			app('CXXFLAGS',x)
120		elif x.startswith('-bundle'):
121			app('LINKFLAGS',x)
122		elif x.startswith(('-undefined','-Xlinker')):
123			arg=lst.pop(0)
124			app('LINKFLAGS',[x,arg])
125		elif x.startswith(('-arch','-isysroot')):
126			tmp=[x,lst.pop(0)]
127			app('CFLAGS',tmp)
128			app('CXXFLAGS',tmp)
129			app('LINKFLAGS',tmp)
130		elif x.endswith(('.a','.so','.dylib','.lib')):
131			appu('LINKFLAGS',x)
132@conf
133def validate_cfg(self,kw):
134	if not'path'in kw:
135		if not self.env.PKGCONFIG:
136			self.find_program('pkg-config',var='PKGCONFIG')
137		kw['path']=self.env.PKGCONFIG
138	if'atleast_pkgconfig_version'in kw:
139		if not'msg'in kw:
140			kw['msg']='Checking for pkg-config version >= %r'%kw['atleast_pkgconfig_version']
141		return
142	if not'okmsg'in kw:
143		kw['okmsg']='yes'
144	if not'errmsg'in kw:
145		kw['errmsg']='not found'
146	if'modversion'in kw:
147		if not'msg'in kw:
148			kw['msg']='Checking for %r version'%kw['modversion']
149		if not'uselib_store'in kw:
150			kw['uselib_store']=kw['modversion']
151		if not'define_name'in kw:
152			kw['define_name']='%s_VERSION'%Utils.quote_define_name(kw['uselib_store'])
153		return
154	if not'package'in kw:
155		raise ValueError('a package name is required')
156	if not'uselib_store'in kw:
157		kw['uselib_store']=kw['package'].upper()
158	if not'define_name'in kw:
159		kw['define_name']=self.have_define(kw['uselib_store'])
160	if not'msg'in kw:
161		kw['msg']='Checking for %r'%(kw['package']or kw['path'])
162	for x in cfg_ver:
163		y=x.replace('-','_')
164		if y in kw:
165			package=kw['package']
166			if Logs.verbose:
167				Logs.warn('Passing %r to conf.check_cfg() is obsolete, pass parameters directly, eg:',y)
168				Logs.warn(" conf.check_cfg(package='%s', args=['--libs', '--cflags', '%s >= 1.6'])",package,package)
169			if not'msg'in kw:
170				kw['msg']='Checking for %r %s %s'%(package,cfg_ver[x],kw[y])
171			break
172@conf
173def exec_cfg(self,kw):
174	path=Utils.to_list(kw['path'])
175	env=self.env.env or None
176	if kw.get('pkg_config_path'):
177		if not env:
178			env=dict(self.environ)
179		env['PKG_CONFIG_PATH']=kw['pkg_config_path']
180	def define_it():
181		define_name=kw['define_name']
182		if kw.get('global_define',1):
183			self.define(define_name,1,False)
184		else:
185			self.env.append_unique('DEFINES_%s'%kw['uselib_store'],"%s=1"%define_name)
186		if kw.get('add_have_to_env',1):
187			self.env[define_name]=1
188	if'atleast_pkgconfig_version'in kw:
189		cmd=path+['--atleast-pkgconfig-version=%s'%kw['atleast_pkgconfig_version']]
190		self.cmd_and_log(cmd,env=env)
191		if not'okmsg'in kw:
192			kw['okmsg']='yes'
193		return
194	for x in cfg_ver:
195		y=x.replace('-','_')
196		if y in kw:
197			self.cmd_and_log(path+['--%s=%s'%(x,kw[y]),kw['package']],env=env)
198			if not'okmsg'in kw:
199				kw['okmsg']='yes'
200			define_it()
201			break
202	if'modversion'in kw:
203		version=self.cmd_and_log(path+['--modversion',kw['modversion']],env=env).strip()
204		self.define(kw['define_name'],version)
205		return version
206	lst=[]+path
207	defi=kw.get('define_variable')
208	if not defi:
209		defi=self.env.PKG_CONFIG_DEFINES or{}
210	for key,val in defi.items():
211		lst.append('--define-variable=%s=%s'%(key,val))
212	static=kw.get('force_static',False)
213	if'args'in kw:
214		args=Utils.to_list(kw['args'])
215		if'--static'in args or'--static-libs'in args:
216			static=True
217		lst+=args
218	lst.extend(Utils.to_list(kw['package']))
219	if'variables'in kw:
220		v_env=kw.get('env',self.env)
221		vars=Utils.to_list(kw['variables'])
222		for v in vars:
223			val=self.cmd_and_log(lst+['--variable='+v],env=env).strip()
224			var='%s_%s'%(kw['uselib_store'],v)
225			v_env[var]=val
226		if not'okmsg'in kw:
227			kw['okmsg']='yes'
228		return
229	ret=self.cmd_and_log(lst,env=env)
230	if not'okmsg'in kw:
231		kw['okmsg']='yes'
232	define_it()
233	self.parse_flags(ret,kw['uselib_store'],kw.get('env',self.env),force_static=static,posix=kw.get('posix'))
234	return ret
235@conf
236def check_cfg(self,*k,**kw):
237	if k:
238		lst=k[0].split()
239		kw['package']=lst[0]
240		kw['args']=' '.join(lst[1:])
241	self.validate_cfg(kw)
242	if'msg'in kw:
243		self.start_msg(kw['msg'],**kw)
244	ret=None
245	try:
246		ret=self.exec_cfg(kw)
247	except self.errors.WafError:
248		if'errmsg'in kw:
249			self.end_msg(kw['errmsg'],'YELLOW',**kw)
250		if Logs.verbose>1:
251			raise
252		else:
253			self.fatal('The configuration failed')
254	else:
255		if not ret:
256			ret=True
257		kw['success']=ret
258		if'okmsg'in kw:
259			self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw)
260	return ret
261def build_fun(bld):
262	if bld.kw['compile_filename']:
263		node=bld.srcnode.make_node(bld.kw['compile_filename'])
264		node.write(bld.kw['code'])
265	o=bld(features=bld.kw['features'],source=bld.kw['compile_filename'],target='testprog')
266	for k,v in bld.kw.items():
267		setattr(o,k,v)
268	if not bld.kw.get('quiet'):
269		bld.conf.to_log("==>\n%s\n<=="%bld.kw['code'])
270@conf
271def validate_c(self,kw):
272	if not'build_fun'in kw:
273		kw['build_fun']=build_fun
274	if not'env'in kw:
275		kw['env']=self.env.derive()
276	env=kw['env']
277	if not'compiler'in kw and not'features'in kw:
278		kw['compiler']='c'
279		if env.CXX_NAME and Task.classes.get('cxx'):
280			kw['compiler']='cxx'
281			if not self.env.CXX:
282				self.fatal('a c++ compiler is required')
283		else:
284			if not self.env.CC:
285				self.fatal('a c compiler is required')
286	if not'compile_mode'in kw:
287		kw['compile_mode']='c'
288		if'cxx'in Utils.to_list(kw.get('features',[]))or kw.get('compiler','')=='cxx':
289			kw['compile_mode']='cxx'
290	if not'type'in kw:
291		kw['type']='cprogram'
292	if not'features'in kw:
293		if not'header_name'in kw or kw.get('link_header_test',True):
294			kw['features']=[kw['compile_mode'],kw['type']]
295		else:
296			kw['features']=[kw['compile_mode']]
297	else:
298		kw['features']=Utils.to_list(kw['features'])
299	if not'compile_filename'in kw:
300		kw['compile_filename']='test.c'+((kw['compile_mode']=='cxx')and'pp'or'')
301	def to_header(dct):
302		if'header_name'in dct:
303			dct=Utils.to_list(dct['header_name'])
304			return''.join(['#include <%s>\n'%x for x in dct])
305		return''
306	if'framework_name'in kw:
307		fwkname=kw['framework_name']
308		if not'uselib_store'in kw:
309			kw['uselib_store']=fwkname.upper()
310		if not kw.get('no_header',False):
311			if not'header_name'in kw:
312				kw['header_name']=[]
313			fwk='%s/%s.h'%(fwkname,fwkname)
314			if kw.get('remove_dot_h'):
315				fwk=fwk[:-2]
316			kw['header_name']=Utils.to_list(kw['header_name'])+[fwk]
317		kw['msg']='Checking for framework %s'%fwkname
318		kw['framework']=fwkname
319	if'function_name'in kw:
320		fu=kw['function_name']
321		if not'msg'in kw:
322			kw['msg']='Checking for function %s'%fu
323		kw['code']=to_header(kw)+SNIP_FUNCTION%fu
324		if not'uselib_store'in kw:
325			kw['uselib_store']=fu.upper()
326		if not'define_name'in kw:
327			kw['define_name']=self.have_define(fu)
328	elif'type_name'in kw:
329		tu=kw['type_name']
330		if not'header_name'in kw:
331			kw['header_name']='stdint.h'
332		if'field_name'in kw:
333			field=kw['field_name']
334			kw['code']=to_header(kw)+SNIP_FIELD%{'type_name':tu,'field_name':field}
335			if not'msg'in kw:
336				kw['msg']='Checking for field %s in %s'%(field,tu)
337			if not'define_name'in kw:
338				kw['define_name']=self.have_define((tu+'_'+field).upper())
339		else:
340			kw['code']=to_header(kw)+SNIP_TYPE%{'type_name':tu}
341			if not'msg'in kw:
342				kw['msg']='Checking for type %s'%tu
343			if not'define_name'in kw:
344				kw['define_name']=self.have_define(tu.upper())
345	elif'header_name'in kw:
346		if not'msg'in kw:
347			kw['msg']='Checking for header %s'%kw['header_name']
348		l=Utils.to_list(kw['header_name'])
349		assert len(l),'list of headers in header_name is empty'
350		kw['code']=to_header(kw)+SNIP_EMPTY_PROGRAM
351		if not'uselib_store'in kw:
352			kw['uselib_store']=l[0].upper()
353		if not'define_name'in kw:
354			kw['define_name']=self.have_define(l[0])
355	if'lib'in kw:
356		if not'msg'in kw:
357			kw['msg']='Checking for library %s'%kw['lib']
358		if not'uselib_store'in kw:
359			kw['uselib_store']=kw['lib'].upper()
360	if'stlib'in kw:
361		if not'msg'in kw:
362			kw['msg']='Checking for static library %s'%kw['stlib']
363		if not'uselib_store'in kw:
364			kw['uselib_store']=kw['stlib'].upper()
365	if'fragment'in kw:
366		kw['code']=kw['fragment']
367		if not'msg'in kw:
368			kw['msg']='Checking for code snippet'
369		if not'errmsg'in kw:
370			kw['errmsg']='no'
371	for(flagsname,flagstype)in(('cxxflags','compiler'),('cflags','compiler'),('linkflags','linker')):
372		if flagsname in kw:
373			if not'msg'in kw:
374				kw['msg']='Checking for %s flags %s'%(flagstype,kw[flagsname])
375			if not'errmsg'in kw:
376				kw['errmsg']='no'
377	if not'execute'in kw:
378		kw['execute']=False
379	if kw['execute']:
380		kw['features'].append('test_exec')
381		kw['chmod']=Utils.O755
382	if not'errmsg'in kw:
383		kw['errmsg']='not found'
384	if not'okmsg'in kw:
385		kw['okmsg']='yes'
386	if not'code'in kw:
387		kw['code']=SNIP_EMPTY_PROGRAM
388	if self.env[INCKEYS]:
389		kw['code']='\n'.join(['#include <%s>'%x for x in self.env[INCKEYS]])+'\n'+kw['code']
390	if kw.get('merge_config_header',False)or env.merge_config_header:
391		kw['code']='%s\n\n%s'%(self.get_config_header(),kw['code'])
392		env.DEFINES=[]
393	if not kw.get('success'):kw['success']=None
394	if'define_name'in kw:
395		self.undefine(kw['define_name'])
396	if not'msg'in kw:
397		self.fatal('missing "msg" in conf.check(...)')
398@conf
399def post_check(self,*k,**kw):
400	is_success=0
401	if kw['execute']:
402		if kw['success']is not None:
403			if kw.get('define_ret',False):
404				is_success=kw['success']
405			else:
406				is_success=(kw['success']==0)
407	else:
408		is_success=(kw['success']==0)
409	if kw.get('define_name'):
410		comment=kw.get('comment','')
411		define_name=kw['define_name']
412		if kw['execute']and kw.get('define_ret')and isinstance(is_success,str):
413			if kw.get('global_define',1):
414				self.define(define_name,is_success,quote=kw.get('quote',1),comment=comment)
415			else:
416				if kw.get('quote',1):
417					succ='"%s"'%is_success
418				else:
419					succ=int(is_success)
420				val='%s=%s'%(define_name,succ)
421				var='DEFINES_%s'%kw['uselib_store']
422				self.env.append_value(var,val)
423		else:
424			if kw.get('global_define',1):
425				self.define_cond(define_name,is_success,comment=comment)
426			else:
427				var='DEFINES_%s'%kw['uselib_store']
428				self.env.append_value(var,'%s=%s'%(define_name,int(is_success)))
429		if kw.get('add_have_to_env',1):
430			if kw.get('uselib_store'):
431				self.env[self.have_define(kw['uselib_store'])]=1
432			else:
433				self.env[define_name]=int(is_success)
434	if'header_name'in kw:
435		if kw.get('auto_add_header_name',False):
436			self.env.append_value(INCKEYS,Utils.to_list(kw['header_name']))
437	if is_success and'uselib_store'in kw:
438		from waflib.Tools import ccroot
439		_vars=set([])
440		for x in kw['features']:
441			if x in ccroot.USELIB_VARS:
442				_vars|=ccroot.USELIB_VARS[x]
443		for k in _vars:
444			x=k.lower()
445			if x in kw:
446				self.env.append_value(k+'_'+kw['uselib_store'],kw[x])
447	return is_success
448@conf
449def check(self,*k,**kw):
450	self.validate_c(kw)
451	self.start_msg(kw['msg'],**kw)
452	ret=None
453	try:
454		ret=self.run_build(*k,**kw)
455	except self.errors.ConfigurationError:
456		self.end_msg(kw['errmsg'],'YELLOW',**kw)
457		if Logs.verbose>1:
458			raise
459		else:
460			self.fatal('The configuration failed')
461	else:
462		kw['success']=ret
463	ret=self.post_check(*k,**kw)
464	if not ret:
465		self.end_msg(kw['errmsg'],'YELLOW',**kw)
466		self.fatal('The configuration failed %r'%ret)
467	else:
468		self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw)
469	return ret
470class test_exec(Task.Task):
471	color='PINK'
472	def run(self):
473		if getattr(self.generator,'rpath',None):
474			if getattr(self.generator,'define_ret',False):
475				self.generator.bld.retval=self.generator.bld.cmd_and_log([self.inputs[0].abspath()])
476			else:
477				self.generator.bld.retval=self.generator.bld.exec_command([self.inputs[0].abspath()])
478		else:
479			env=self.env.env or{}
480			env.update(dict(os.environ))
481			for var in('LD_LIBRARY_PATH','DYLD_LIBRARY_PATH','PATH'):
482				env[var]=self.inputs[0].parent.abspath()+os.path.pathsep+env.get(var,'')
483			if getattr(self.generator,'define_ret',False):
484				self.generator.bld.retval=self.generator.bld.cmd_and_log([self.inputs[0].abspath()],env=env)
485			else:
486				self.generator.bld.retval=self.generator.bld.exec_command([self.inputs[0].abspath()],env=env)
487@feature('test_exec')
488@after_method('apply_link')
489def test_exec_fun(self):
490	self.create_task('test_exec',self.link_task.outputs[0])
491@conf
492def check_cxx(self,*k,**kw):
493	kw['compiler']='cxx'
494	return self.check(*k,**kw)
495@conf
496def check_cc(self,*k,**kw):
497	kw['compiler']='c'
498	return self.check(*k,**kw)
499@conf
500def set_define_comment(self,key,comment):
501	coms=self.env.DEFINE_COMMENTS
502	if not coms:
503		coms=self.env.DEFINE_COMMENTS={}
504	coms[key]=comment or''
505@conf
506def get_define_comment(self,key):
507	coms=self.env.DEFINE_COMMENTS or{}
508	return coms.get(key,'')
509@conf
510def define(self,key,val,quote=True,comment=''):
511	assert isinstance(key,str)
512	if not key:
513		return
514	if val is True:
515		val=1
516	elif val in(False,None):
517		val=0
518	if isinstance(val,int)or isinstance(val,float):
519		s='%s=%s'
520	else:
521		s=quote and'%s="%s"'or'%s=%s'
522	app=s%(key,str(val))
523	ban=key+'='
524	lst=self.env.DEFINES
525	for x in lst:
526		if x.startswith(ban):
527			lst[lst.index(x)]=app
528			break
529	else:
530		self.env.append_value('DEFINES',app)
531	self.env.append_unique(DEFKEYS,key)
532	self.set_define_comment(key,comment)
533@conf
534def undefine(self,key,comment=''):
535	assert isinstance(key,str)
536	if not key:
537		return
538	ban=key+'='
539	lst=[x for x in self.env.DEFINES if not x.startswith(ban)]
540	self.env.DEFINES=lst
541	self.env.append_unique(DEFKEYS,key)
542	self.set_define_comment(key,comment)
543@conf
544def define_cond(self,key,val,comment=''):
545	assert isinstance(key,str)
546	if not key:
547		return
548	if val:
549		self.define(key,1,comment=comment)
550	else:
551		self.undefine(key,comment=comment)
552@conf
553def is_defined(self,key):
554	assert key and isinstance(key,str)
555	ban=key+'='
556	for x in self.env.DEFINES:
557		if x.startswith(ban):
558			return True
559	return False
560@conf
561def get_define(self,key):
562	assert key and isinstance(key,str)
563	ban=key+'='
564	for x in self.env.DEFINES:
565		if x.startswith(ban):
566			return x[len(ban):]
567	return None
568@conf
569def have_define(self,key):
570	return(self.env.HAVE_PAT or'HAVE_%s')%Utils.quote_define_name(key)
571@conf
572def write_config_header(self,configfile='',guard='',top=False,defines=True,headers=False,remove=True,define_prefix=''):
573	if not configfile:configfile=WAF_CONFIG_H
574	waf_guard=guard or'W_%s_WAF'%Utils.quote_define_name(configfile)
575	node=top and self.bldnode or self.path.get_bld()
576	node=node.make_node(configfile)
577	node.parent.mkdir()
578	lst=['/* WARNING! All changes made to this file will be lost! */\n']
579	lst.append('#ifndef %s\n#define %s\n'%(waf_guard,waf_guard))
580	lst.append(self.get_config_header(defines,headers,define_prefix=define_prefix))
581	lst.append('\n#endif /* %s */\n'%waf_guard)
582	node.write('\n'.join(lst))
583	self.env.append_unique(Build.CFG_FILES,[node.abspath()])
584	if remove:
585		for key in self.env[DEFKEYS]:
586			self.undefine(key)
587		self.env[DEFKEYS]=[]
588@conf
589def get_config_header(self,defines=True,headers=False,define_prefix=''):
590	lst=[]
591	if self.env.WAF_CONFIG_H_PRELUDE:
592		lst.append(self.env.WAF_CONFIG_H_PRELUDE)
593	if headers:
594		for x in self.env[INCKEYS]:
595			lst.append('#include <%s>'%x)
596	if defines:
597		tbl={}
598		for k in self.env.DEFINES:
599			a,_,b=k.partition('=')
600			tbl[a]=b
601		for k in self.env[DEFKEYS]:
602			caption=self.get_define_comment(k)
603			if caption:
604				caption=' /* %s */'%caption
605			try:
606				txt='#define %s%s %s%s'%(define_prefix,k,tbl[k],caption)
607			except KeyError:
608				txt='/* #undef %s%s */%s'%(define_prefix,k,caption)
609			lst.append(txt)
610	return"\n".join(lst)
611@conf
612def cc_add_flags(conf):
613	conf.add_os_flags('CPPFLAGS',dup=False)
614	conf.add_os_flags('CFLAGS',dup=False)
615@conf
616def cxx_add_flags(conf):
617	conf.add_os_flags('CPPFLAGS',dup=False)
618	conf.add_os_flags('CXXFLAGS',dup=False)
619@conf
620def link_add_flags(conf):
621	conf.add_os_flags('LINKFLAGS',dup=False)
622	conf.add_os_flags('LDFLAGS',dup=False)
623@conf
624def cc_load_tools(conf):
625	if not conf.env.DEST_OS:
626		conf.env.DEST_OS=Utils.unversioned_sys_platform()
627	conf.load('c')
628@conf
629def cxx_load_tools(conf):
630	if not conf.env.DEST_OS:
631		conf.env.DEST_OS=Utils.unversioned_sys_platform()
632	conf.load('cxx')
633@conf
634def get_cc_version(conf,cc,gcc=False,icc=False,clang=False):
635	cmd=cc+['-dM','-E','-']
636	env=conf.env.env or None
637	try:
638		out,err=conf.cmd_and_log(cmd,output=0,input='\n'.encode(),env=env)
639	except Exception:
640		conf.fatal('Could not determine the compiler version %r'%cmd)
641	if gcc:
642		if out.find('__INTEL_COMPILER')>=0:
643			conf.fatal('The intel compiler pretends to be gcc')
644		if out.find('__GNUC__')<0 and out.find('__clang__')<0:
645			conf.fatal('Could not determine the compiler type')
646	if icc and out.find('__INTEL_COMPILER')<0:
647		conf.fatal('Not icc/icpc')
648	if clang and out.find('__clang__')<0:
649		conf.fatal('Not clang/clang++')
650	if not clang and out.find('__clang__')>=0:
651		conf.fatal('Could not find gcc/g++ (only Clang), if renamed try eg: CC=gcc48 CXX=g++48 waf configure')
652	k={}
653	if icc or gcc or clang:
654		out=out.splitlines()
655		for line in out:
656			lst=shlex.split(line)
657			if len(lst)>2:
658				key=lst[1]
659				val=lst[2]
660				k[key]=val
661		def isD(var):
662			return var in k
663		if not conf.env.DEST_OS:
664			conf.env.DEST_OS=''
665		for i in MACRO_TO_DESTOS:
666			if isD(i):
667				conf.env.DEST_OS=MACRO_TO_DESTOS[i]
668				break
669		else:
670			if isD('__APPLE__')and isD('__MACH__'):
671				conf.env.DEST_OS='darwin'
672			elif isD('__unix__'):
673				conf.env.DEST_OS='generic'
674		if isD('__ELF__'):
675			conf.env.DEST_BINFMT='elf'
676		elif isD('__WINNT__')or isD('__CYGWIN__')or isD('_WIN32'):
677			conf.env.DEST_BINFMT='pe'
678			conf.env.LIBDIR=conf.env.BINDIR
679		elif isD('__APPLE__'):
680			conf.env.DEST_BINFMT='mac-o'
681		if not conf.env.DEST_BINFMT:
682			conf.env.DEST_BINFMT=Utils.destos_to_binfmt(conf.env.DEST_OS)
683		for i in MACRO_TO_DEST_CPU:
684			if isD(i):
685				conf.env.DEST_CPU=MACRO_TO_DEST_CPU[i]
686				break
687		Logs.debug('ccroot: dest platform: '+' '.join([conf.env[x]or'?'for x in('DEST_OS','DEST_BINFMT','DEST_CPU')]))
688		if icc:
689			ver=k['__INTEL_COMPILER']
690			conf.env.CC_VERSION=(ver[:-2],ver[-2],ver[-1])
691		else:
692			if isD('__clang__')and isD('__clang_major__'):
693				conf.env.CC_VERSION=(k['__clang_major__'],k['__clang_minor__'],k['__clang_patchlevel__'])
694			else:
695				conf.env.CC_VERSION=(k['__GNUC__'],k['__GNUC_MINOR__'],k.get('__GNUC_PATCHLEVEL__','0'))
696	return k
697@conf
698def get_xlc_version(conf,cc):
699	cmd=cc+['-qversion']
700	try:
701		out,err=conf.cmd_and_log(cmd,output=0)
702	except Errors.WafError:
703		conf.fatal('Could not find xlc %r'%cmd)
704	for v in(r"IBM XL C/C\+\+.* V(?P<major>\d*)\.(?P<minor>\d*)",):
705		version_re=re.compile(v,re.I).search
706		match=version_re(out or err)
707		if match:
708			k=match.groupdict()
709			conf.env.CC_VERSION=(k['major'],k['minor'])
710			break
711	else:
712		conf.fatal('Could not determine the XLC version.')
713@conf
714def get_suncc_version(conf,cc):
715	cmd=cc+['-V']
716	try:
717		out,err=conf.cmd_and_log(cmd,output=0)
718	except Errors.WafError as e:
719		if not(hasattr(e,'returncode')and hasattr(e,'stdout')and hasattr(e,'stderr')):
720			conf.fatal('Could not find suncc %r'%cmd)
721		out=e.stdout
722		err=e.stderr
723	version=(out or err)
724	version=version.splitlines()[0]
725	version_re=re.compile(r'cc: (studio.*?|\s+)?(sun\s+(c\+\+|c)|(WorkShop\s+Compilers))?\s+(?P<major>\d*)\.(?P<minor>\d*)',re.I).search
726	match=version_re(version)
727	if match:
728		k=match.groupdict()
729		conf.env.CC_VERSION=(k['major'],k['minor'])
730	else:
731		conf.fatal('Could not determine the suncc version.')
732@conf
733def add_as_needed(self):
734	if self.env.DEST_BINFMT=='elf'and'gcc'in(self.env.CXX_NAME,self.env.CC_NAME):
735		self.env.append_unique('LINKFLAGS','-Wl,--as-needed')
736class cfgtask(Task.TaskBase):
737	def display(self):
738		return''
739	def runnable_status(self):
740		return Task.RUN_ME
741	def uid(self):
742		return Utils.SIG_NIL
743	def run(self):
744		conf=self.conf
745		bld=Build.BuildContext(top_dir=conf.srcnode.abspath(),out_dir=conf.bldnode.abspath())
746		bld.env=conf.env
747		bld.init_dirs()
748		bld.in_msg=1
749		bld.logger=self.logger
750		bld.multicheck_task=self
751		args=self.args
752		try:
753			if'func'in args:
754				bld.test(build_fun=args['func'],msg=args.get('msg',''),okmsg=args.get('okmsg',''),errmsg=args.get('errmsg',''),)
755			else:
756				args['multicheck_mandatory']=args.get('mandatory',True)
757				args['mandatory']=True
758				try:
759					bld.check(**args)
760				finally:
761					args['mandatory']=args['multicheck_mandatory']
762		except Exception:
763			return 1
764@conf
765def multicheck(self,*k,**kw):
766	self.start_msg(kw.get('msg','Executing %d configuration tests'%len(k)),**kw)
767	for var in('DEFINES',DEFKEYS):
768		self.env.append_value(var,[])
769	self.env.DEFINE_COMMENTS=self.env.DEFINE_COMMENTS or{}
770	class par(object):
771		def __init__(self):
772			self.keep=False
773			self.task_sigs={}
774			self.progress_bar=0
775		def total(self):
776			return len(tasks)
777		def to_log(self,*k,**kw):
778			return
779	bld=par()
780	bld.keep=kw.get('run_all_tests',True)
781	tasks=[]
782	for dct in k:
783		x=Task.classes['cfgtask'](bld=bld)
784		tasks.append(x)
785		x.args=dct
786		x.bld=bld
787		x.conf=self
788		x.args=dct
789		x.logger=Logs.make_mem_logger(str(id(x)),self.logger)
790	def it():
791		yield tasks
792		while 1:
793			yield[]
794	bld.producer=p=Runner.Parallel(bld,Options.options.jobs)
795	p.biter=it()
796	p.start()
797	for x in tasks:
798		x.logger.memhandler.flush()
799	if p.error:
800		for x in p.error:
801			if getattr(x,'err_msg',None):
802				self.to_log(x.err_msg)
803				self.end_msg('fail',color='RED')
804				raise Errors.WafError('There is an error in the library, read config.log for more information')
805	failure_count=0
806	for x in tasks:
807		if x.hasrun not in(Task.SUCCESS,Task.NOT_RUN):
808			failure_count+=1
809	if failure_count:
810		self.end_msg(kw.get('errmsg','%s test failed'%failure_count),color='YELLOW',**kw)
811	else:
812		self.end_msg('all ok',**kw)
813	for x in tasks:
814		if'msg'in x.args:
815			self.start_msg(x.args['msg'])
816			if x.hasrun==Task.NOT_RUN:
817				self.end_msg('test cancelled','YELLOW')
818			elif x.hasrun!=Task.SUCCESS:
819				self.end_msg(x.args.get('errmsg','no'),'YELLOW')
820			else:
821				self.end_msg(x.args.get('okmsg','yes'),'GREEN')
822	for x in tasks:
823		if x.hasrun!=Task.SUCCESS:
824			if x.args.get('mandatory',True):
825				self.fatal(kw.get('fatalmsg')or'One of the tests has failed, read config.log for more information')
826