#! /usr/bin/env python
# encoding: utf-8
# Thomas Nagy, 2006-2010 (ita)

# the following two variables are used by the target "waf dist"
VERSION='0.0.1'
APPNAME='cc_test'

top = '.'

import waflib.Configure
waflib.Configure.autoconfig = True

def options(opt):
	opt.load('compiler_c')
	opt.load('gnu_dirs')

def build(bld):
	bld.recurse('program stlib shlib stlib2')


lst = 'debug release foo bar one two'.split()

def configure(conf):
	conf.load('compiler_c')
	conf.check_features()
	conf.check_cc(fragment="""#include<stdio.h>\nint main(){fprintf(stderr, "mu"); printf("%d", 22);return 0;}\n""", execute=True, define_name='HAVE_MU')
	conf.write_config_header('config.h')


	# gotcha - the config.h must be written for each variant
	txt = conf.bldnode.search('config.h').read()
	for x in lst:
		node = conf.bldnode.make_node(x + '/config.h')
		node.parent.mkdir()
		node.write(txt)

from waflib import Utils, Build
class buildall_ctx(Build.BuildContext):
	cmd = fun = 'buildall'
	def compile(self):
		pass

def buildall(ctx):
	"""call 'waf buildall' to build all the variants in parallel"""

	timer = Utils.Timer()
	threads = []
	count = [0]
	line_lock = Utils.threading.Lock()
	class sub_build(Utils.threading.Thread):
		def run(self):
			bld = self.bld = self.cls(top_dir=ctx.top_dir, out_dir=ctx.out_dir)
			bld.load()
			bld.siblings = threads
			bld.count = count
			bld.line_lock = line_lock
			bld.timer = timer
			bld.logger = ctx.logger
			bld.load_envs()
			bld.targets = ctx.targets
			bld.recurse([bld.run_dir])
			bld.compile()

	for x in lst:
		cls = type(Build.BuildContext)(x, (Build.BuildContext,), {'cmd': x, 'variant': x})
		cls.progress_line = locked_progress_line
		f = sub_build()
		f.cls = cls
		threads.append(f)
		f.start()

	for x in threads:
		x.join()

def locked_progress_line(self, state, total, col1, col2):
	try:
		self.line_lock.acquire()
		self.count[0] += 1
		total = 0
		for x in self.siblings:
			try:
				p = x.bld.producer
			except:
				pass
			else:
				total += p.total

		return Build.BuildContext.progress_line(self, self.count[0], total, col1, col2)
	finally:
		self.line_lock.release()



class cleanall_ctx(Build.CleanContext):
	cmd = fun = 'cleanall'

def cleanall(ctx):
	for x in lst:
		cls = type(Build.CleanContext)(x, (Build.CleanContext,), {'cmd': x, 'variant': x})
		bld = cls(top_dir=ctx.top_dir, out_dir=ctx.out_dir)
		bld.load()
		bld.load_envs()
		bld.recurse([bld.run_dir])
		try:
			bld.clean()
		finally:
			bld.save()



features_str = '''
#include <stdio.h>
int is_big_endian()
{
	long one = 1;
	return !(*((char *)(&one)));
}
int main()
{
	if (is_big_endian()) printf("bigendian=1\\n");
	else printf("bigendian=0\\n");
	printf("int_size=%d\\n", sizeof(int));
	printf("long_int_size=%d\\n", sizeof(long int));
	printf("long_long_int_size=%d\\n", sizeof(long long int));
	printf("double_size=%d\\n", sizeof(double));
	return 0;
}
'''

def check_features(self):

	mp = self.check(fragment=features_str, define_ret=True, execute=True)
	try:
		mp = mp.decode('utf-8')
	except:
		pass

	t = Utils.str_to_dict(mp)
	try:
		is_big = int(t['bigendian'])
	except KeyError:
		raise Configure.ConfigurationError('endian test failed %s (see the config.log)' % features_str)

	if is_big: strbig = 'big endian'
	else: strbig = 'little endian'
	self.msg('endianness', strbig)

	self.msg('int size', t['int_size'])
	self.msg('long int size', t['long_int_size'])
	self.msg('long long int size', t['long_long_int_size'])
	self.msg('double size', t['double_size'])

	self.define_cond('IS_BIGENDIAN', is_big)
	self.define_cond('INT_SIZE', int(t['int_size']))
	self.define_cond('LONG_INT_SIZE', int(t['long_int_size']))
	self.define_cond('LONG_LONG_INT_SIZE', int(t['long_long_int_size']))
	self.define_cond('DOUBLE_SIZE', int(t['double_size']))

	return is_big

from waflib import Configure
Configure.conf(check_features) # bind the method


