view engine/SConscript @ 164:5b04a7d3ded6

typo fix some missing event (de)registrations ability to capture one event multiple times (instead of only having one slot, we have groups and each group has an own slot, the default group is "default" so we are backward compatible
author spq@33b003aa-7bff-0310-803a-e67f0ece8222
date Wed, 15 Oct 2008 14:57:04 +0000
parents ab8b11adfb70
children ea04dfe54aae
line wrap: on
line source

import os, sys
from utils.util_scripts.path import path as upath
Import('env')

joinpath = os.path.join
_sep = os.path.sep
enginepath = upath('.')
extensionpath = upath('./extensions')

def is_implfile(fname):
	return fname.endswith('.cpp') or fname.endswith('.cxx') or fname.endswith('.m')

def is_headerfile(fname):
	return fname.endswith('.hpp') or fname.endswith('.h')

def generate_swig_wrappers(target, source, env):
	from string import Template
	swigoutdir = joinpath('engine', 'swigwrappers')

	def generate_language_specifics(lang):
		swigpath = ''
		if sys.platform == 'win32':
			swigpath = '"' + os.environ['_SWIG'] + '"\\'

		print "   Generating language specific wrappers for " + lang
		
		langoutdir = joinpath(swigoutdir, lang)
		templatefile = joinpath(langoutdir,"fife.i.templ")
		
		template = Template(open(templatefile).read())
		inclusions = sorted(['%include ' + str(f) for f in source])
		inclusions = '\n'.join(inclusions)
		interfacefile = joinpath(langoutdir, 'fife.i')
		open(interfacefile, 'w').write(template.substitute(inclusions=inclusions))

		includepath = joinpath('engine', 'core')
		# added -w511 to ignore warnings for "Can't use keyword arguments with overloaded functions"
		pipe = os.popen(swigpath +'swig -w511 -c++ -%s -I%s -outdir %s %s' % (lang, includepath, langoutdir, interfacefile))
		if pipe.close():
			print "\nError while running swig, stopped"
			Exit(1)

	print "Running swig..."
	generate_language_specifics(env['script'])
	print "Swig completed"

def swig_wrapper_emitter(target, source, env):
	target_append = []
	for t in target:
		t = str(t)
		if t.endswith('.py'):
			t = t[:-3]
		else:
			continue
		target_append.append(t + '.i')
		target_append.append(t + '_wrap.cxx')
		target_append.append(t + '_wrap.h')
	for t in target_append:
		target.append(t)
	return target, source

swig_wrapper_builder = Builder(action = generate_swig_wrappers, suffix = '.py', source_suffix = '.i', emitter = swig_wrapper_emitter)
env.Append(BUILDERS = {'SwigWrappers': swig_wrapper_builder})


def remove_based_on_dir_filter(dirfilters, files):
	abspaths = []
	for pathstr in dirfilters:
		abspaths.append(os.path.abspath(joinpath(*pathstr.split('/'))))

	result = []
	for f in files:
		filtered = False
		for p in abspaths:
			if str(f.abspath()).find(p) != -1:
				filtered = True
				break
		if not filtered:
			result.append(f)
	return result

def check_for_duplicate_files(files):
	dupePaths = {}; dupes = []
	for f in files:
		fname = os.path.basename(f)
		try:
			dupePaths[fname].append(f)
		except KeyError:
			dupePaths[fname] = [f]
	for fname, paths in dupePaths.items():
		if len(paths) > 1:
			dupes.append('%s -> %s' % (fname, ', '.join(paths)))
	if dupes:
		print "\nError found: All cpp file names must be unique in FIFE, the following were not:"
		for l in dupes: print l
		Exit(1)

msvcbuildpath = joinpath('build', 'win32', 'build_environments', 'visual_studio_8')

def generate_msvc_project(target, source, env):
	def create_dict_tree(source_dict):
		for f in source_dict.keys():
			parts = f.split(os.path.sep, 1)
			if len(parts) > 1:
				try:
					source_dict[parts[0]][parts[1]] = {}
				except KeyError:
					source_dict[parts[0]] = {}
					source_dict[parts[0]][parts[1]] = {}
				del source_dict[f]
		for k, d in source_dict.items():
			create_dict_tree(d)
		return source_dict
	
	def get_msvc_repr(d, tabcount=2, curpath=''):
		retstr = []
		for k in sorted(d.keys()):
			newpath = os.path.join(curpath, k)
			if len(d[k].keys()):
				retstr.append(tabcount * '\t' + '<Filter Name="%s">' % k)
				retstr.append(get_msvc_repr(d[k], tabcount+1, newpath))
				retstr.append(tabcount * '\t' + '</Filter>')
			else:
				newpath = os.path.join('..', '..', '..', '..', 'engine', newpath)
				retstr.append(tabcount * '\t' + '<File RelativePath="%s"></File>' % newpath.replace('/','\\'))
		return '\n'.join(retstr)
			
	vcpaths = [os.path.abspath(str(f)).split('%sengine%s' % (_sep, _sep))[-1] for f in source]
	xmlstr = get_msvc_repr(create_dict_tree(dict([[p, {}] for p in vcpaths])))
	projtxt = open(joinpath(msvcbuildpath, 'engine_template.xml'), 'r').read()
	projtxt = projtxt.replace('__FILE_INSERTION_POINT__', xmlstr)

	oldprojtxt = ''
	try:
		oldprojtxt = open(str(target[0]), 'r').read()
	except:
		pass

	if(oldprojtxt <> projtxt):
		open(str(target[0]), 'w').write(projtxt)
		print "FIFE msvc project file succesfully created (%s)" % os.path.abspath(str(target[0]))
	else:
		print "FIFE msvc project file already up-to-date (%s)" % os.path.abspath(str(target[0]))

msvc_project_builder = Builder(action = generate_msvc_project, suffix = '.vcproj')
env.Append(BUILDERS = {'MSVCProject': msvc_project_builder})

msvcbuildpath9 = joinpath('build', 'win32', 'build_environments', 'visual_studio_9')

def generate_msvc_project9(target, source, env):
	def create_dict_tree(source_dict):
		for f in source_dict.keys():
			parts = f.split(os.path.sep, 1)
			if len(parts) > 1:
				try:
					source_dict[parts[0]][parts[1]] = {}
				except KeyError:
					source_dict[parts[0]] = {}
					source_dict[parts[0]][parts[1]] = {}
				del source_dict[f]
		for k, d in source_dict.items():
			create_dict_tree(d)
		return source_dict
	
	def get_msvc_repr(d, tabcount=2, curpath=''):
		retstr = []
		for k in sorted(d.keys()):
			newpath = os.path.join(curpath, k)
			if len(d[k].keys()):
				retstr.append(tabcount * '\t' + '<Filter Name="%s">' % k)
				retstr.append(get_msvc_repr(d[k], tabcount+1, newpath))
				retstr.append(tabcount * '\t' + '</Filter>')
			else:
				newpath = os.path.join('..', '..', '..', '..', 'engine', newpath)
				retstr.append(tabcount * '\t' + '<File RelativePath="%s"></File>' % newpath.replace('/','\\'))
		return '\n'.join(retstr)
			
	vcpaths = [os.path.abspath(str(f)).split('%sengine%s' % (_sep, _sep))[-1] for f in source]
	xmlstr = get_msvc_repr(create_dict_tree(dict([[p, {}] for p in vcpaths])))
	projtxt = open(joinpath(msvcbuildpath9, 'engine_template.xml'), 'r').read()
	projtxt = projtxt.replace('__FILE_INSERTION_POINT__', xmlstr)

	oldprojtxt = ''
	try:
		oldprojtxt = open(str(target[0]), 'r').read()
	except:
		pass

	if(oldprojtxt <> projtxt):
		open(str(target[0]), 'w').write(projtxt)
		print "FIFE msvc9 project file succesfully created (%s)" % os.path.abspath(str(target[0]))
	else:
		print "FIFE msvc9 project file already up-to-date (%s)" % os.path.abspath(str(target[0]))

msvc_project_builder9 = Builder(action = generate_msvc_project9, suffix = '.vcproj')
env.Append(BUILDERS = {'MSVCProject9': msvc_project_builder9})

cbbuildpath_win32 = joinpath('build', 'win32', 'build_environments', 'code_blocks')

def generate_codeblocks_project_win32(target, source, env):
	codeblocksHeaderDef = \
	'''		<Unit filename="..\..\..\engine\%s">
				<Option compilerVar=""/>
				<Option compile="0"/>
				<Option link="0"/>
				<Option target="default"/>
			</Unit>'''
	
	codeblocksCppDef = \
	'''		<Unit filename="..\..\..\..\engine\%s">
				<Option compilerVar="CPP"/>
				<Option target="default"/>
			</Unit>'''
	xmlstr = []
	for f in source:
		newf = os.path.abspath(str(f)).split('%sengine%s' % (_sep, _sep))[-1]
		newf = newf.replace('/', '\\')
		if str(f) in headerfiles:
			xmlstr.append(codeblocksHeaderDef % newf)
		else:
			xmlstr.append(codeblocksCppDef % newf)
	projtxt = open(joinpath(cbbuildpath_win32, 'engine_template.xml'), 'r').read()
	projtxt = projtxt.replace('__FILE_INSERTION_POINT__', '\n'.join(xmlstr))
	open(str(target[0]), 'w').write(projtxt)
	print "FIFE code::blocks project file succesfully created (%s)" % os.path.abspath(str(target[0]))

codeblocks_project_builder_win32 = Builder(action = generate_codeblocks_project_win32, suffix = '.cbp')
env.Append(BUILDERS = {'CodeblocksProjectWin32': codeblocks_project_builder_win32})


cbbuildpath_linux = joinpath('build', 'linux', 'code_blocks')

def generate_codeblocks_project_linux(target, source, env):
	codeblocksHeaderDef = \
	'''		<Unit filename="../../../engine/%s">
				<Option compilerVar=""/>
				<Option compile="0"/>
				<Option link="0"/>
				<Option target="default"/>
			</Unit>'''
	
	codeblocksCppDef = \
	'''		<Unit filename="../../../engine/%s">
				<Option compilerVar="CPP"/>
				<Option target="default"/>
			</Unit>'''
	xmlstr = []
	for f in source:
		newf = os.path.abspath(str(f)).split('%sengine%s' % (_sep, _sep))[-1]
		newf = newf.replace('/', '\\')
		if str(f) in headerfiles:
			xmlstr.append(codeblocksHeaderDef % newf)
		else:
			xmlstr.append(codeblocksCppDef % newf)
	projtxt = open(joinpath(cbbuildpath_linux, 'engine_template.xml'), 'r').read()
	projtxt = projtxt.replace('__FILE_INSERTION_POINT__', '\n'.join(xmlstr))
	open(str(target[0]), 'w').write(projtxt)
	print "FIFE code::blocks project file succesfully created (%s)" % os.path.abspath(str(target[0]))

codeblocks_project_builder_linux = Builder(action = generate_codeblocks_project_linux, suffix = '.cbp')
env.Append(BUILDERS = {'CodeblocksProjectLinux': codeblocks_project_builder_linux})


variated_dirs = eval(open(joinpath('config', 'variated_dirs'), 'r').read())
# filter out swigwrappers. fife_wrap.cxx is appended manually
# as it might not exist yet during SConscript parsing
filteredpaths = ['swigwrappers']
for flag, paths in variated_dirs.items():
	value = None
	if flag.find('-') != -1:
		flag, value = flag.split('-')
	if (value and (not env[flag] == value)) or (not env[flag]):
		filteredpaths.extend(paths)

tmpfiles = remove_based_on_dir_filter(filteredpaths, list(enginepath.walkfiles('*.i')))
interfacefiles = []
for f in tmpfiles:
	if f.startswith('.' + _sep):
		interfacefiles.append(f[2:])
	else:
		interfacefiles.append(f)

swig = env.SwigWrappers('swigwrappers/python/fife', interfacefiles)
env.Install('$PREFIX/lib/python2.5/site-packages/fife', ['swigwrappers/python/fife.py'])

allfiles = list(enginepath.walkfiles())
headerfiles = [f for f in allfiles if is_headerfile(f)]
implfiles = [f for f in allfiles if is_implfile(f)]
extensionfiles = list(extensionpath.walkfiles('*.py'))

filtered_prj_paths = eval(open(joinpath('config', 'removed_from_project_files'), 'r').read())
filtered_prj_paths = [joinpath(*p.split('/')) for p in filtered_prj_paths]
projectfiles = [str(f) for f in remove_based_on_dir_filter(filtered_prj_paths, headerfiles + implfiles)]

projectfiles.append('./swigwrappers/%s/fife_wrap.cxx' % env['script'])

msvcproj = env.MSVCProject(joinpath('..', msvcbuildpath, 'fife'), projectfiles)
msvcproj9 = env.MSVCProject9(joinpath('..', msvcbuildpath9, 'fife'), projectfiles)
cbproj_win32 = env.CodeblocksProjectWin32(joinpath('..', cbbuildpath_win32, 'fife_engine'), projectfiles)
cbproj_linux = env.CodeblocksProjectLinux(joinpath('..', cbbuildpath_linux, 'fife_engine'), projectfiles)

if not env['projectfiles_only']:
	env.Append(CPPPATH = ['#/engine/core', '#/engine/swigwrappers'])
	compilefiles = [str(f) for f in remove_based_on_dir_filter(filteredpaths, implfiles)]
	compilefiles.append('./swigwrappers/%s/fife_wrap.cxx' % env['script'])
	if sys.platform == 'darwin':
		flib = env.SharedLibrary('fife', compilefiles, LINKFLAGS=['-Wl'])
	else:
		flib = env.SharedLibrary('fife', compilefiles, LINKFLAGS=['-Wl,-rpath,../../ext/install/lib,-rpath,../ext/install/lib,-rpath,ext/install/lib'])
	if sys.platform != 'win32':
		env.Command('swigwrappers/%s/_fife.so' % env['script'], flib, [Copy('$TARGET', '$SOURCE')])
		if sys.platform != 'darwin':
			env.Install('$PREFIX/lib/python2.5/site-packages/fife', flib)
#			env.Install('$PREFIX/lib/python2.5/site-packages/fife', [str(f) for f in extensionfiles])