diff engine/SConscript @ 378:64738befdf3b

bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author vtchill@33b003aa-7bff-0310-803a-e67f0ece8222
date Mon, 11 Jan 2010 23:34:52 +0000
parents 1587ff8fa3a0
children 621b062e752d
line wrap: on
line diff
--- a/engine/SConscript	Wed Dec 09 17:01:52 2009 +0000
+++ b/engine/SConscript	Mon Jan 11 23:34:52 2010 +0000
@@ -1,314 +1,176 @@
-import os, sys
+import os,sys
+import utils.scons.scons_utils as utils
 from utils.util_scripts.path import path as upath
-Import('env')
+import utils.scons.scons_builders as builders
 
-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')
+Import('env', 'opts')
 
-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')
+_sep = os.path.sep
+src_path = upath(opts['SRC'])
+engine_path = opts['SRC']
+core_path = os.path.join('engine', 'core')
+extensionpath = upath(os.path.join(opts['SRC'], 'python', 'fife', 'extensions'))
 
-	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")
+#**************************************************************************
+#Compile the list of source code to be used
+#**************************************************************************
 
-		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"
+allfiles = list(src_path.walkfiles())
+allfiles_base = list()
+for f in allfiles:
+	allfiles_base.append(utils.relpath(f, opts['SRC']))
 
-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})
+extpyfiles = list(extensionpath.walkfiles('*.py'))
+extensionfiles = list()
+relextensionfiles = list()
+for f in extpyfiles:
+	extensionfiles.append(utils.relpath(f, opts['SRC']))
+	relextensionfiles.append(utils.relpath(f, os.path.join(opts['SRC'], 'python', 'fife')))
+	
+headerfiles = [f for f in allfiles_base if utils.is_headerfile(f)]
+implfiles = [f for f in allfiles_base if utils.is_implfile(f)]
+swigfiles = [f for f in allfiles_base if utils.is_swigfile(f)]
+intfiles = utils.filter_by_dir(['swigwrappers'], swigfiles)
+compilefiles = utils.filter_by_dir(['swigwrappers'], implfiles)
 
 
-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
+#**************************************************************************
+#python
+#**************************************************************************
 
-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')
+#generate swig interface file
+utils.gen_swig_interface(os.path.join(engine_path, 'swigwrappers', 'python', 'fife.i.templ'), 
+		   intfiles,
+		   os.path.join(engine_path, 'swigwrappers', 'python'))
 
-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
+pyfiles = list(compilefiles)
+pyfiles.append([os.path.join('swigwrappers', 'python' ,'fife_wrap.cc')])
 
-	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)
+#**************************************************************************
+#Definition of scons builders for project files
+#**************************************************************************
 
-	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')
+msvc_project_builder = Builder(action = builders.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')
+msvc_project_builder9 = Builder(action = builders.generate_msvc_project9, suffix = '.vcproj')
 env.Append(BUILDERS = {'MSVCProject9': msvc_project_builder9})
 
-cbbuildpath_win32 = joinpath('build', 'win32', 'build_environments', 'code_blocks')
+codeblocks_project_builder_win32 = Builder(action = builders.generate_codeblocks_project_win32, suffix = '.cbp')
+env.Append(BUILDERS = {'CodeblocksProjectWin32': codeblocks_project_builder_win32})
 
-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>'''
+codeblocks_project_builder_linux = Builder(action = builders.generate_codeblocks_project_linux, suffix = '.cbp')
+env.Append(BUILDERS = {'CodeblocksProjectLinux': codeblocks_project_builder_linux})
+
+python_extensions_builder = Builder(action = "$SWIG -o $TARGET ${_SWIGOUTDIR} ${_SWIGINCFLAGS} $SWIGFLAGS $SOURCES")
+env.Append(BUILDERS = {'PythonExtensions': python_extensions_builder})
+
 
-	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]))
+#**************************************************************************
+#project files target
+#**************************************************************************
 
-codeblocks_project_builder_win32 = Builder(action = generate_codeblocks_project_win32, suffix = '.cbp')
-env.Append(BUILDERS = {'CodeblocksProjectWin32': codeblocks_project_builder_win32})
+projectfiles = compilefiles + headerfiles
+#projectfiles.append('swigwrappers/python/fife_wrap.cc')
+
+msvcproj = env.MSVCProject(os.path.join('..', '..','..', builders.msvcbuildpath, 'fife'), projectfiles)
+msvcproj9 = env.MSVCProject9(os.path.join('..', '..','..', builders.msvcbuildpath9, 'fife'), projectfiles)
+cbproj_win32 = env.CodeblocksProjectWin32(os.path.join('..', '..','..', builders.cbbuildpath_win32, 'fife_engine'), projectfiles)
+cbproj_linux = env.CodeblocksProjectLinux(os.path.join('..', '..','..', builders.cbbuildpath_linux, 'fife_engine'), projectfiles)
 
 
-cbbuildpath_linux = joinpath('build', 'linux', 'code_blocks')
+#**************************************************************************
+#shared library target
+#**************************************************************************
 
-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>'''
+if sys.platform == 'win32':
+	sharedlib = env.SharedLibrary(target = 'fife',
+								  source = compilefiles,
+								  LINKFLAGS=['-Wl'],
+								  OBJPREFIX='shared_',
+								  SHLIBEMITTER = '')
+else:
+	sharedlib = env.SharedLibrary(target = 'fife',
+								  source = compilefiles,
+								  LINKFLAGS=['-Wl'])
 
-	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]))
+#**************************************************************************
+#python library target
+#**************************************************************************
+if sys.platform == 'win32':
+	dest_suffix = '.pyd'
+else:
+	dest_suffix = '.so'
+	
+pythonlib = env.SharedLibrary(target = 'fife',
+							  source = pyfiles,
+							  OBJPREFIX='py_',
+							  SHLIBPREFIX='_',
+							  SHLIBSUFFIX=dest_suffix,
+							  LINKFLAGS=['-Wl'],
+							  SHLIBEMITTER = '')
 
-codeblocks_project_builder_linux = Builder(action = generate_codeblocks_project_linux, suffix = '.cbp')
-env.Append(BUILDERS = {'CodeblocksProjectLinux': codeblocks_project_builder_linux})
+pythonext = env.PythonExtensions(target = [os.path.join('swigwrappers', 'python' ,'fife_wrap.cc'), os.path.join('python', 'fife', 'fife.py')],
+							  source = os.path.join('swigwrappers', 'python' ,'fife.i'),
+							  SWIGFLAGS=['-python','-c++','-w511'],
+							  SWIGPATH='core',
+							  SWIGOUTDIR=Dir('#/engine/python/fife').srcnode().path)
+							  
 
+copy_dest = os.path.join(opts['PYLIB_COPY_DEST'], '_fife' + dest_suffix)
+copy_cmd = env.Command(copy_dest, pythonlib, [Copy('$TARGET', '$SOURCE')])
+copy_cmd2 = env.Command(os.path.join(opts['WRAP_COPY_DEST'], 'fife_wrap.h'),
+				os.path.join('swigwrappers','python','fife_wrap.h'),
+				[Copy('$TARGET', '$SOURCE')])
+copy_cmd3 = env.Command(os.path.join(opts['WRAP_COPY_DEST'], 'fife_wrap.cc'),
+				os.path.join('swigwrappers','python','fife_wrap.cc'),
+				[Copy('$TARGET', '$SOURCE')])
 
-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)
+#**************************************************************************
+#static library target
+#**************************************************************************
+
+staticlib = env.StaticLibrary(target = 'fife',
+							  source = compilefiles,
+							  LINKFLAGS=['-Wl'])
 
-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)
+#**************************************************************************
+#Install targets
+#**************************************************************************
 
-swig = env.SwigWrappers('swigwrappers/python/fife', interfacefiles)
-env.Install('$PREFIX/lib/python%s/site-packages/fife'%sys.version[:3], ['swigwrappers/python/fife.py'])
+#TODO: This is not complete.  Because of the current linux rpath issue this
+#will not work as expected.
+install_static = env.Install(os.path.join(opts['PREFIX'], 'lib'), staticlib)
+install_shared = env.Install(os.path.join(opts['PREFIX'], 'lib'), sharedlib)
+
+headerdestlist = utils.gen_dest_files(os.path.join(opts['PREFIX'], 'include', 'fife'), headerfiles)
+install_headers = env.InstallAs(headerdestlist, headerfiles)
+
+pypath = os.path.join(opts['PYTHON_PREFIX'], 'fife') 
+extdestfilelist = utils.gen_dest_files(pypath, relextensionfiles)
 
-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'))
+install_python_lib = env.Install(pypath, pythonlib)
+install_python_module = env.Install(pypath, ['#/engine/python/fife/fife.py','#/engine/python/fife/__init__.py'])
+install_python_extensions = env.InstallAs(extdestfilelist, extensionfiles)
 
-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'])
+#**************************************************************************
+#Alias definitions
+#**************************************************************************
 
-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)
+alias_msvc = Alias('msvc',msvcproj)
+alias_msvc9 = Alias('msvc9',msvcproj9)
+alias_cbwin32 = Alias('cbwin32',cbproj_win32)
+alias_cblinux = Alias('cblinux',cbproj_linux)
+Alias('projects',[alias_msvc, alias_msvc9, alias_cbwin32, alias_cblinux])
 
-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])
+alias_shared = Alias('fife-shared', sharedlib)
+alias_static = Alias('fife-static', staticlib)
+alias_swig = Alias('fife-swig', [pythonext, copy_cmd2, copy_cmd3])
+alias_python = Alias('fife-python', [pythonlib, copy_cmd, alias_swig])
+Alias('fife', [alias_shared, alias_static, alias_python])
+
+alias_install_shared = Alias('install-shared', install_shared)
+alias_install_static = Alias('install-static', install_static)
+alias_install_python = Alias('install-python', [alias_python, install_python_lib, install_python_module, install_python_extensions])
+alias_install_dev = Alias('install-dev', [alias_install_shared, alias_install_static, install_headers])
+Alias('install-all', [alias_install_python, alias_install_dev])