view engine/SConscript @ 374:1115f7cae9a3

Editor: * The editor will now force filenames to be lowercase, as VFS does not like uppercase path names. * If a map filename does not have a .xml extension on save, it will be automatically added. * Log modules set to "all" by default. Only new users will be affected by this without having to modify or remove their configuration file. * Log level set to LOGLEVEL_WARN
author cheesesucker@33b003aa-7bff-0310-803a-e67f0ece8222
date Sat, 21 Nov 2009 13:11:56 +0000
parents 1587ff8fa3a0
children 64738befdf3b
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)).rsplit('%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)).rsplit('%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)).rsplit('%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)).rsplit('%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/python%s/site-packages/fife'%sys.version[:3], ['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/python%s/site-packages/fife'%sys.version[:3], flib)
#			env.Install('$PREFIX/lib/python%s/site-packages/fife'%sys.version[:3], [str(f) for f in extensionfiles])