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,shutil,traceback,errno,sys,stat
6from waflib import Utils,Configure,Logs,Options,ConfigSet,Context,Errors,Build,Node
7build_dir_override=None
8no_climb_commands=['configure']
9default_cmd="build"
10def waf_entry_point(current_directory,version,wafdir):
11	Logs.init_log()
12	if Context.WAFVERSION!=version:
13		Logs.error('Waf script %r and library %r do not match (directory %r)',version,Context.WAFVERSION,wafdir)
14		sys.exit(1)
15	if'--version'in sys.argv:
16		Context.run_dir=current_directory
17		ctx=Context.create_context('options')
18		ctx.curdir=current_directory
19		ctx.parse_args()
20		sys.exit(0)
21	if len(sys.argv)>1:
22		potential_wscript=os.path.join(current_directory,sys.argv[1])
23		if os.path.basename(potential_wscript)=='wscript'and os.path.isfile(potential_wscript):
24			current_directory=os.path.normpath(os.path.dirname(potential_wscript))
25			sys.argv.pop(1)
26	Context.waf_dir=wafdir
27	Context.launch_dir=current_directory
28	no_climb=os.environ.get('NOCLIMB')
29	if not no_climb:
30		for k in no_climb_commands:
31			for y in sys.argv:
32				if y.startswith(k):
33					no_climb=True
34					break
35	for i,x in enumerate(sys.argv):
36		if x.startswith('--top='):
37			Context.run_dir=Context.top_dir=Utils.sane_path(x[6:])
38			sys.argv[i]='--top='+Context.run_dir
39		if x.startswith('--out='):
40			Context.out_dir=Utils.sane_path(x[6:])
41			sys.argv[i]='--out='+Context.out_dir
42	cur=current_directory
43	while cur and not Context.top_dir:
44		try:
45			lst=os.listdir(cur)
46		except OSError:
47			lst=[]
48			Logs.error('Directory %r is unreadable!',cur)
49		if Options.lockfile in lst:
50			env=ConfigSet.ConfigSet()
51			try:
52				env.load(os.path.join(cur,Options.lockfile))
53				ino=os.stat(cur)[stat.ST_INO]
54			except EnvironmentError:
55				pass
56			else:
57				for x in(env.run_dir,env.top_dir,env.out_dir):
58					if Utils.is_win32:
59						if cur==x:
60							load=True
61							break
62					else:
63						try:
64							ino2=os.stat(x)[stat.ST_INO]
65						except OSError:
66							pass
67						else:
68							if ino==ino2:
69								load=True
70								break
71				else:
72					Logs.warn('invalid lock file in %s',cur)
73					load=False
74				if load:
75					Context.run_dir=env.run_dir
76					Context.top_dir=env.top_dir
77					Context.out_dir=env.out_dir
78					break
79		if not Context.run_dir:
80			if Context.WSCRIPT_FILE in lst:
81				Context.run_dir=cur
82		next=os.path.dirname(cur)
83		if next==cur:
84			break
85		cur=next
86		if no_climb:
87			break
88	if not Context.run_dir:
89		if'-h'in sys.argv or'--help'in sys.argv:
90			Logs.warn('No wscript file found: the help message may be incomplete')
91			Context.run_dir=current_directory
92			ctx=Context.create_context('options')
93			ctx.curdir=current_directory
94			ctx.parse_args()
95			sys.exit(0)
96		Logs.error('Waf: Run from a directory containing a file named %r',Context.WSCRIPT_FILE)
97		sys.exit(1)
98	try:
99		os.chdir(Context.run_dir)
100	except OSError:
101		Logs.error('Waf: The folder %r is unreadable',Context.run_dir)
102		sys.exit(1)
103	try:
104		set_main_module(os.path.normpath(os.path.join(Context.run_dir,Context.WSCRIPT_FILE)))
105	except Errors.WafError as e:
106		Logs.pprint('RED',e.verbose_msg)
107		Logs.error(str(e))
108		sys.exit(1)
109	except Exception as e:
110		Logs.error('Waf: The wscript in %r is unreadable',Context.run_dir)
111		traceback.print_exc(file=sys.stdout)
112		sys.exit(2)
113	if'--profile'in sys.argv:
114		import cProfile,pstats
115		cProfile.runctx('from waflib import Scripting; Scripting.run_commands()',{},{},'profi.txt')
116		p=pstats.Stats('profi.txt')
117		p.sort_stats('time').print_stats(75)
118	else:
119		try:
120			run_commands()
121		except Errors.WafError as e:
122			if Logs.verbose>1:
123				Logs.pprint('RED',e.verbose_msg)
124			Logs.error(e.msg)
125			sys.exit(1)
126		except SystemExit:
127			raise
128		except Exception as e:
129			traceback.print_exc(file=sys.stdout)
130			sys.exit(2)
131		except KeyboardInterrupt:
132			Logs.pprint('RED','Interrupted')
133			sys.exit(68)
134def set_main_module(file_path):
135	Context.g_module=Context.load_module(file_path)
136	Context.g_module.root_path=file_path
137	def set_def(obj):
138		name=obj.__name__
139		if not name in Context.g_module.__dict__:
140			setattr(Context.g_module,name,obj)
141	for k in(dist,distclean,distcheck):
142		set_def(k)
143	if not'init'in Context.g_module.__dict__:
144		Context.g_module.init=Utils.nada
145	if not'shutdown'in Context.g_module.__dict__:
146		Context.g_module.shutdown=Utils.nada
147	if not'options'in Context.g_module.__dict__:
148		Context.g_module.options=Utils.nada
149def parse_options():
150	Context.create_context('options').execute()
151	for var in Options.envvars:
152		(name,value)=var.split('=',1)
153		os.environ[name.strip()]=value
154	if not Options.commands:
155		Options.commands=[default_cmd]
156	Options.commands=[x for x in Options.commands if x!='options']
157	Logs.verbose=Options.options.verbose
158	if Options.options.zones:
159		Logs.zones=Options.options.zones.split(',')
160		if not Logs.verbose:
161			Logs.verbose=1
162	elif Logs.verbose>0:
163		Logs.zones=['runner']
164	if Logs.verbose>2:
165		Logs.zones=['*']
166def run_command(cmd_name):
167	ctx=Context.create_context(cmd_name)
168	ctx.log_timer=Utils.Timer()
169	ctx.options=Options.options
170	ctx.cmd=cmd_name
171	try:
172		ctx.execute()
173	finally:
174		ctx.finalize()
175	return ctx
176def run_commands():
177	parse_options()
178	run_command('init')
179	while Options.commands:
180		cmd_name=Options.commands.pop(0)
181		ctx=run_command(cmd_name)
182		Logs.info('%r finished successfully (%s)',cmd_name,ctx.log_timer)
183	run_command('shutdown')
184def distclean_dir(dirname):
185	for(root,dirs,files)in os.walk(dirname):
186		for f in files:
187			if f.endswith(('.o','.moc','.exe')):
188				fname=os.path.join(root,f)
189				try:
190					os.remove(fname)
191				except OSError:
192					Logs.warn('Could not remove %r',fname)
193	for x in(Context.DBFILE,'config.log'):
194		try:
195			os.remove(x)
196		except OSError:
197			pass
198	try:
199		shutil.rmtree('c4che')
200	except OSError:
201		pass
202def distclean(ctx):
203	'''removes the build directory'''
204	lst=os.listdir('.')
205	for f in lst:
206		if f==Options.lockfile:
207			try:
208				proj=ConfigSet.ConfigSet(f)
209			except IOError:
210				Logs.warn('Could not read %r',f)
211				continue
212			if proj['out_dir']!=proj['top_dir']:
213				try:
214					shutil.rmtree(proj['out_dir'])
215				except EnvironmentError as e:
216					if e.errno!=errno.ENOENT:
217						Logs.warn('Could not remove %r',proj['out_dir'])
218			else:
219				distclean_dir(proj['out_dir'])
220			for k in(proj['out_dir'],proj['top_dir'],proj['run_dir']):
221				p=os.path.join(k,Options.lockfile)
222				try:
223					os.remove(p)
224				except OSError as e:
225					if e.errno!=errno.ENOENT:
226						Logs.warn('Could not remove %r',p)
227		if not Options.commands:
228			for x in'.waf-1. waf-1. .waf3-1. waf3-1.'.split():
229				if f.startswith(x):
230					shutil.rmtree(f,ignore_errors=True)
231class Dist(Context.Context):
232	'''creates an archive containing the project source code'''
233	cmd='dist'
234	fun='dist'
235	algo='tar.bz2'
236	ext_algo={}
237	def execute(self):
238		self.recurse([os.path.dirname(Context.g_module.root_path)])
239		self.archive()
240	def archive(self):
241		import tarfile
242		arch_name=self.get_arch_name()
243		try:
244			self.base_path
245		except AttributeError:
246			self.base_path=self.path
247		node=self.base_path.make_node(arch_name)
248		try:
249			node.delete()
250		except OSError:
251			pass
252		files=self.get_files()
253		if self.algo.startswith('tar.'):
254			tar=tarfile.open(arch_name,'w:'+self.algo.replace('tar.',''))
255			for x in files:
256				self.add_tar_file(x,tar)
257			tar.close()
258		elif self.algo=='zip':
259			import zipfile
260			zip=zipfile.ZipFile(arch_name,'w',compression=zipfile.ZIP_DEFLATED)
261			for x in files:
262				archive_name=self.get_base_name()+'/'+x.path_from(self.base_path)
263				zip.write(x.abspath(),archive_name,zipfile.ZIP_DEFLATED)
264			zip.close()
265		else:
266			self.fatal('Valid algo types are tar.bz2, tar.gz, tar.xz or zip')
267		try:
268			from hashlib import sha1
269		except ImportError:
270			digest=''
271		else:
272			digest=' (sha=%r)'%sha1(node.read(flags='rb')).hexdigest()
273		Logs.info('New archive created: %s%s',self.arch_name,digest)
274	def get_tar_path(self,node):
275		return node.abspath()
276	def add_tar_file(self,x,tar):
277		p=self.get_tar_path(x)
278		tinfo=tar.gettarinfo(name=p,arcname=self.get_tar_prefix()+'/'+x.path_from(self.base_path))
279		tinfo.uid=0
280		tinfo.gid=0
281		tinfo.uname='root'
282		tinfo.gname='root'
283		if os.path.isfile(p):
284			fu=open(p,'rb')
285			try:
286				tar.addfile(tinfo,fileobj=fu)
287			finally:
288				fu.close()
289		else:
290			tar.addfile(tinfo)
291	def get_tar_prefix(self):
292		try:
293			return self.tar_prefix
294		except AttributeError:
295			return self.get_base_name()
296	def get_arch_name(self):
297		try:
298			self.arch_name
299		except AttributeError:
300			self.arch_name=self.get_base_name()+'.'+self.ext_algo.get(self.algo,self.algo)
301		return self.arch_name
302	def get_base_name(self):
303		try:
304			self.base_name
305		except AttributeError:
306			appname=getattr(Context.g_module,Context.APPNAME,'noname')
307			version=getattr(Context.g_module,Context.VERSION,'1.0')
308			self.base_name=appname+'-'+version
309		return self.base_name
310	def get_excl(self):
311		try:
312			return self.excl
313		except AttributeError:
314			self.excl=Node.exclude_regs+' **/waf-1.8.* **/.waf-1.8* **/waf3-1.8.* **/.waf3-1.8* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*'
315			if Context.out_dir:
316				nd=self.root.find_node(Context.out_dir)
317				if nd:
318					self.excl+=' '+nd.path_from(self.base_path)
319			return self.excl
320	def get_files(self):
321		try:
322			files=self.files
323		except AttributeError:
324			files=self.base_path.ant_glob('**/*',excl=self.get_excl())
325		return files
326def dist(ctx):
327	'''makes a tarball for redistributing the sources'''
328	pass
329class DistCheck(Dist):
330	fun='distcheck'
331	cmd='distcheck'
332	def execute(self):
333		self.recurse([os.path.dirname(Context.g_module.root_path)])
334		self.archive()
335		self.check()
336	def check(self):
337		import tempfile,tarfile
338		try:
339			t=tarfile.open(self.get_arch_name())
340			for x in t:
341				t.extract(x)
342		finally:
343			t.close()
344		cfg=[]
345		if Options.options.distcheck_args:
346			cfg=shlex.split(Options.options.distcheck_args)
347		else:
348			cfg=[x for x in sys.argv if x.startswith('-')]
349		instdir=tempfile.mkdtemp('.inst',self.get_base_name())
350		ret=Utils.subprocess.Popen([sys.executable,sys.argv[0],'configure','install','uninstall','--destdir='+instdir]+cfg,cwd=self.get_base_name()).wait()
351		if ret:
352			raise Errors.WafError('distcheck failed with code %r'%ret)
353		if os.path.exists(instdir):
354			raise Errors.WafError('distcheck succeeded, but files were left in %s'%instdir)
355		shutil.rmtree(self.get_base_name())
356def distcheck(ctx):
357	'''checks if the project compiles (tarball from 'dist')'''
358	pass
359def autoconfigure(execute_method):
360	def execute(self):
361		if not Configure.autoconfig:
362			return execute_method(self)
363		env=ConfigSet.ConfigSet()
364		do_config=False
365		try:
366			env.load(os.path.join(Context.top_dir,Options.lockfile))
367		except EnvironmentError:
368			Logs.warn('Configuring the project')
369			do_config=True
370		else:
371			if env.run_dir!=Context.run_dir:
372				do_config=True
373			else:
374				h=0
375				for f in env.files:
376					try:
377						h=Utils.h_list((h,Utils.readf(f,'rb')))
378					except EnvironmentError:
379						do_config=True
380						break
381				else:
382					do_config=h!=env.hash
383		if do_config:
384			cmd=env.config_cmd or'configure'
385			if Configure.autoconfig=='clobber':
386				tmp=Options.options.__dict__
387				Options.options.__dict__=env.options
388				try:
389					run_command(cmd)
390				finally:
391					Options.options.__dict__=tmp
392			else:
393				run_command(cmd)
394			run_command(self.cmd)
395		else:
396			return execute_method(self)
397	return execute
398Build.BuildContext.execute=autoconfigure(Build.BuildContext.execute)
399