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,shlex,sys,time,re,shutil
6from waflib import ConfigSet,Utils,Options,Logs,Context,Build,Errors
7WAF_CONFIG_LOG='config.log'
8autoconfig=False
9conf_template='''# project %(app)s configured on %(now)s by
10# waf %(wafver)s (abi %(abi)s, python %(pyver)x on %(systype)s)
11# using %(args)s
12#'''
13class ConfigurationContext(Context.Context):
14	'''configures the project'''
15	cmd='configure'
16	error_handlers=[]
17	def __init__(self,**kw):
18		super(ConfigurationContext,self).__init__(**kw)
19		self.environ=dict(os.environ)
20		self.all_envs={}
21		self.top_dir=None
22		self.out_dir=None
23		self.tools=[]
24		self.hash=0
25		self.files=[]
26		self.tool_cache=[]
27		self.setenv('')
28	def setenv(self,name,env=None):
29		if name not in self.all_envs or env:
30			if not env:
31				env=ConfigSet.ConfigSet()
32				self.prepare_env(env)
33			else:
34				env=env.derive()
35			self.all_envs[name]=env
36		self.variant=name
37	def get_env(self):
38		return self.all_envs[self.variant]
39	def set_env(self,val):
40		self.all_envs[self.variant]=val
41	env=property(get_env,set_env)
42	def init_dirs(self):
43		top=self.top_dir
44		if not top:
45			top=Options.options.top
46		if not top:
47			top=getattr(Context.g_module,Context.TOP,None)
48		if not top:
49			top=self.path.abspath()
50		top=os.path.abspath(top)
51		self.srcnode=(os.path.isabs(top)and self.root or self.path).find_dir(top)
52		assert(self.srcnode)
53		out=self.out_dir
54		if not out:
55			out=Options.options.out
56		if not out:
57			out=getattr(Context.g_module,Context.OUT,None)
58		if not out:
59			out=Options.lockfile.replace('.lock-waf_%s_'%sys.platform,'').replace('.lock-waf','')
60		out=os.path.realpath(out)
61		self.bldnode=(os.path.isabs(out)and self.root or self.path).make_node(out)
62		self.bldnode.mkdir()
63		if not os.path.isdir(self.bldnode.abspath()):
64			conf.fatal('Could not create the build directory %s'%self.bldnode.abspath())
65	def execute(self):
66		self.init_dirs()
67		self.cachedir=self.bldnode.make_node(Build.CACHE_DIR)
68		self.cachedir.mkdir()
69		path=os.path.join(self.bldnode.abspath(),WAF_CONFIG_LOG)
70		self.logger=Logs.make_logger(path,'cfg')
71		app=getattr(Context.g_module,'APPNAME','')
72		if app:
73			ver=getattr(Context.g_module,'VERSION','')
74			if ver:
75				app="%s (%s)"%(app,ver)
76		params={'now':time.ctime(),'pyver':sys.hexversion,'systype':sys.platform,'args':" ".join(sys.argv),'wafver':Context.WAFVERSION,'abi':Context.ABI,'app':app}
77		self.to_log(conf_template%params)
78		self.msg('Setting top to',self.srcnode.abspath())
79		self.msg('Setting out to',self.bldnode.abspath())
80		if id(self.srcnode)==id(self.bldnode):
81			Logs.warn('Setting top == out')
82		elif id(self.path)!=id(self.srcnode):
83			if self.srcnode.is_child_of(self.path):
84				Logs.warn('Are you certain that you do not want to set top="." ?')
85		super(ConfigurationContext,self).execute()
86		self.store()
87		Context.top_dir=self.srcnode.abspath()
88		Context.out_dir=self.bldnode.abspath()
89		env=ConfigSet.ConfigSet()
90		env.argv=sys.argv
91		env.options=Options.options.__dict__
92		env.config_cmd=self.cmd
93		env.run_dir=Context.run_dir
94		env.top_dir=Context.top_dir
95		env.out_dir=Context.out_dir
96		env.hash=self.hash
97		env.files=self.files
98		env.environ=dict(self.environ)
99		if not self.env.NO_LOCK_IN_RUN and not getattr(Options.options,'no_lock_in_run'):
100			env.store(os.path.join(Context.run_dir,Options.lockfile))
101		if not self.env.NO_LOCK_IN_TOP and not getattr(Options.options,'no_lock_in_top'):
102			env.store(os.path.join(Context.top_dir,Options.lockfile))
103		if not self.env.NO_LOCK_IN_OUT and not getattr(Options.options,'no_lock_in_out'):
104			env.store(os.path.join(Context.out_dir,Options.lockfile))
105	def prepare_env(self,env):
106		if not env.PREFIX:
107			if Options.options.prefix or Utils.is_win32:
108				env.PREFIX=Utils.sane_path(Options.options.prefix)
109			else:
110				env.PREFIX=''
111		if not env.BINDIR:
112			if Options.options.bindir:
113				env.BINDIR=Utils.sane_path(Options.options.bindir)
114			else:
115				env.BINDIR=Utils.subst_vars('${PREFIX}/bin',env)
116		if not env.LIBDIR:
117			if Options.options.libdir:
118				env.LIBDIR=Utils.sane_path(Options.options.libdir)
119			else:
120				env.LIBDIR=Utils.subst_vars('${PREFIX}/lib%s'%Utils.lib64(),env)
121	def store(self):
122		n=self.cachedir.make_node('build.config.py')
123		n.write('version = 0x%x\ntools = %r\n'%(Context.HEXVERSION,self.tools))
124		if not self.all_envs:
125			self.fatal('nothing to store in the configuration context!')
126		for key in self.all_envs:
127			tmpenv=self.all_envs[key]
128			tmpenv.store(os.path.join(self.cachedir.abspath(),key+Build.CACHE_SUFFIX))
129	def load(self,input,tooldir=None,funs=None,with_sys_path=True,cache=False):
130		tools=Utils.to_list(input)
131		if tooldir:tooldir=Utils.to_list(tooldir)
132		for tool in tools:
133			if cache:
134				mag=(tool,id(self.env),tooldir,funs)
135				if mag in self.tool_cache:
136					self.to_log('(tool %s is already loaded, skipping)'%tool)
137					continue
138				self.tool_cache.append(mag)
139			module=None
140			try:
141				module=Context.load_tool(tool,tooldir,ctx=self,with_sys_path=with_sys_path)
142			except ImportError as e:
143				self.fatal('Could not load the Waf tool %r from %r\n%s'%(tool,sys.path,e))
144			except Exception as e:
145				self.to_log('imp %r (%r & %r)'%(tool,tooldir,funs))
146				self.to_log(Utils.ex_stack())
147				raise
148			if funs is not None:
149				self.eval_rules(funs)
150			else:
151				func=getattr(module,'configure',None)
152				if func:
153					if type(func)is type(Utils.readf):func(self)
154					else:self.eval_rules(func)
155			self.tools.append({'tool':tool,'tooldir':tooldir,'funs':funs})
156	def post_recurse(self,node):
157		super(ConfigurationContext,self).post_recurse(node)
158		self.hash=Utils.h_list((self.hash,node.read('rb')))
159		self.files.append(node.abspath())
160	def eval_rules(self,rules):
161		self.rules=Utils.to_list(rules)
162		for x in self.rules:
163			f=getattr(self,x)
164			if not f:
165				self.fatal('No such configuration function %r'%x)
166			f()
167def conf(f):
168	def fun(*k,**kw):
169		mandatory=True
170		if'mandatory'in kw:
171			mandatory=kw['mandatory']
172			del kw['mandatory']
173		try:
174			return f(*k,**kw)
175		except Errors.ConfigurationError:
176			if mandatory:
177				raise
178	fun.__name__=f.__name__
179	setattr(ConfigurationContext,f.__name__,fun)
180	setattr(Build.BuildContext,f.__name__,fun)
181	return f
182@conf
183def add_os_flags(self,var,dest=None,dup=False):
184	try:
185		flags=shlex.split(self.environ[var])
186	except KeyError:
187		return
188	if dup or''.join(flags)not in''.join(Utils.to_list(self.env[dest or var])):
189		self.env.append_value(dest or var,flags)
190@conf
191def cmd_to_list(self,cmd):
192	if isinstance(cmd,str):
193		if os.path.isfile(cmd):
194			return[cmd]
195		if os.sep=='/':
196			return shlex.split(cmd)
197		else:
198			try:
199				return shlex.split(cmd,posix=False)
200			except TypeError:
201				return shlex.split(cmd)
202	return cmd
203@conf
204def check_waf_version(self,mini='1.8.99',maxi='2.0.0',**kw):
205	self.start_msg('Checking for waf version in %s-%s'%(str(mini),str(maxi)),**kw)
206	ver=Context.HEXVERSION
207	if Utils.num2ver(mini)>ver:
208		self.fatal('waf version should be at least %r (%r found)'%(Utils.num2ver(mini),ver))
209	if Utils.num2ver(maxi)<ver:
210		self.fatal('waf version should be at most %r (%r found)'%(Utils.num2ver(maxi),ver))
211	self.end_msg('ok',**kw)
212@conf
213def find_file(self,filename,path_list=[]):
214	for n in Utils.to_list(filename):
215		for d in Utils.to_list(path_list):
216			p=os.path.expanduser(os.path.join(d,n))
217			if os.path.exists(p):
218				return p
219	self.fatal('Could not find %r'%filename)
220@conf
221def find_program(self,filename,**kw):
222	exts=kw.get('exts',Utils.is_win32 and'.exe,.com,.bat,.cmd'or',.sh,.pl,.py')
223	environ=kw.get('environ',getattr(self,'environ',os.environ))
224	ret=''
225	filename=Utils.to_list(filename)
226	msg=kw.get('msg',', '.join(filename))
227	var=kw.get('var','')
228	if not var:
229		var=re.sub(r'[-.]','_',filename[0].upper())
230	path_list=kw.get('path_list','')
231	if path_list:
232		path_list=Utils.to_list(path_list)
233	else:
234		path_list=environ.get('PATH','').split(os.pathsep)
235	if kw.get('value'):
236		ret=self.cmd_to_list(kw['value'])
237	elif var in environ:
238		ret=self.cmd_to_list(environ[var])
239	elif self.env[var]:
240		ret=self.cmd_to_list(self.env[var])
241	else:
242		if not ret:
243			ret=self.find_binary(filename,exts.split(','),path_list)
244		if not ret and Utils.winreg:
245			ret=Utils.get_registry_app_path(Utils.winreg.HKEY_CURRENT_USER,filename)
246		if not ret and Utils.winreg:
247			ret=Utils.get_registry_app_path(Utils.winreg.HKEY_LOCAL_MACHINE,filename)
248		ret=self.cmd_to_list(ret)
249	if ret:
250		if len(ret)==1:
251			retmsg=ret[0]
252		else:
253			retmsg=ret
254	else:
255		retmsg=False
256	self.msg('Checking for program %r'%msg,retmsg,**kw)
257	if not kw.get('quiet'):
258		self.to_log('find program=%r paths=%r var=%r -> %r'%(filename,path_list,var,ret))
259	if not ret:
260		self.fatal(kw.get('errmsg','')or'Could not find the program %r'%filename)
261	interpreter=kw.get('interpreter')
262	if interpreter is None:
263		if not Utils.check_exe(ret[0],env=environ):
264			self.fatal('Program %r is not executable'%ret)
265		self.env[var]=ret
266	else:
267		self.env[var]=self.env[interpreter]+ret
268	return ret
269@conf
270def find_binary(self,filenames,exts,paths):
271	for f in filenames:
272		for ext in exts:
273			exe_name=f+ext
274			if os.path.isabs(exe_name):
275				if os.path.isfile(exe_name):
276					return exe_name
277			else:
278				for path in paths:
279					x=os.path.expanduser(os.path.join(path,exe_name))
280					if os.path.isfile(x):
281						return x
282	return None
283@conf
284def run_build(self,*k,**kw):
285	lst=[str(v)for(p,v)in kw.items()if p!='env']
286	h=Utils.h_list(lst)
287	dir=self.bldnode.abspath()+os.sep+(not Utils.is_win32 and'.'or'')+'conf_check_'+Utils.to_hex(h)
288	try:
289		os.makedirs(dir)
290	except OSError:
291		pass
292	try:
293		os.stat(dir)
294	except OSError:
295		self.fatal('cannot use the configuration test folder %r'%dir)
296	cachemode=getattr(Options.options,'confcache',None)
297	if cachemode==1:
298		try:
299			proj=ConfigSet.ConfigSet(os.path.join(dir,'cache_run_build'))
300		except EnvironmentError:
301			pass
302		else:
303			ret=proj['cache_run_build']
304			if isinstance(ret,str)and ret.startswith('Test does not build'):
305				self.fatal(ret)
306			return ret
307	bdir=os.path.join(dir,'testbuild')
308	if not os.path.exists(bdir):
309		os.makedirs(bdir)
310	self.test_bld=bld=Context.create_context('build',top_dir=dir,out_dir=bdir)
311	bld.init_dirs()
312	bld.progress_bar=0
313	bld.targets='*'
314	bld.logger=self.logger
315	bld.all_envs.update(self.all_envs)
316	bld.env=kw['env']
317	bld.kw=kw
318	bld.conf=self
319	kw['build_fun'](bld)
320	ret=-1
321	try:
322		try:
323			bld.compile()
324		except Errors.WafError:
325			ret='Test does not build: %s'%Utils.ex_stack()
326			self.fatal(ret)
327		else:
328			ret=getattr(bld,'retval',0)
329	finally:
330		if cachemode==1:
331			proj=ConfigSet.ConfigSet()
332			proj['cache_run_build']=ret
333			proj.store(os.path.join(dir,'cache_run_build'))
334		else:
335			shutil.rmtree(dir)
336	return ret
337@conf
338def ret_msg(self,msg,args):
339	if isinstance(msg,str):
340		return msg
341	return msg(args)
342@conf
343def test(self,*k,**kw):
344	if not'env'in kw:
345		kw['env']=self.env.derive()
346	if kw.get('validate'):
347		kw['validate'](kw)
348	self.start_msg(kw['msg'],**kw)
349	ret=None
350	try:
351		ret=self.run_build(*k,**kw)
352	except self.errors.ConfigurationError:
353		self.end_msg(kw['errmsg'],'YELLOW',**kw)
354		if Logs.verbose>1:
355			raise
356		else:
357			self.fatal('The configuration failed')
358	else:
359		kw['success']=ret
360	if kw.get('post_check'):
361		ret=kw['post_check'](kw)
362	if ret:
363		self.end_msg(kw['errmsg'],'YELLOW',**kw)
364		self.fatal('The configuration failed %r'%ret)
365	else:
366		self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw)
367	return ret
368