comparison 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
comparison
equal deleted inserted replaced
377:fe6fb0e0ed23 378:64738befdf3b
1 import os, sys 1 import os,sys
2 import utils.scons.scons_utils as utils
2 from utils.util_scripts.path import path as upath 3 from utils.util_scripts.path import path as upath
3 Import('env') 4 import utils.scons.scons_builders as builders
4 5
5 joinpath = os.path.join 6 Import('env', 'opts')
7
6 _sep = os.path.sep 8 _sep = os.path.sep
7 enginepath = upath('.') 9 src_path = upath(opts['SRC'])
8 extensionpath = upath('./extensions') 10 engine_path = opts['SRC']
11 core_path = os.path.join('engine', 'core')
12 extensionpath = upath(os.path.join(opts['SRC'], 'python', 'fife', 'extensions'))
9 13
10 def is_implfile(fname): 14 #**************************************************************************
11 return fname.endswith('.cpp') or fname.endswith('.cxx') or fname.endswith('.m') 15 #Compile the list of source code to be used
16 #**************************************************************************
12 17
13 def is_headerfile(fname): 18 allfiles = list(src_path.walkfiles())
14 return fname.endswith('.hpp') or fname.endswith('.h') 19 allfiles_base = list()
20 for f in allfiles:
21 allfiles_base.append(utils.relpath(f, opts['SRC']))
15 22
16 def generate_swig_wrappers(target, source, env): 23 extpyfiles = list(extensionpath.walkfiles('*.py'))
17 from string import Template 24 extensionfiles = list()
18 swigoutdir = joinpath('engine', 'swigwrappers') 25 relextensionfiles = list()
19 26 for f in extpyfiles:
20 def generate_language_specifics(lang): 27 extensionfiles.append(utils.relpath(f, opts['SRC']))
21 swigpath = '' 28 relextensionfiles.append(utils.relpath(f, os.path.join(opts['SRC'], 'python', 'fife')))
22 if sys.platform == 'win32': 29
23 swigpath = '"' + os.environ['_SWIG'] + '"\\' 30 headerfiles = [f for f in allfiles_base if utils.is_headerfile(f)]
24 31 implfiles = [f for f in allfiles_base if utils.is_implfile(f)]
25 print " Generating language specific wrappers for " + lang 32 swigfiles = [f for f in allfiles_base if utils.is_swigfile(f)]
26 33 intfiles = utils.filter_by_dir(['swigwrappers'], swigfiles)
27 langoutdir = joinpath(swigoutdir, lang) 34 compilefiles = utils.filter_by_dir(['swigwrappers'], implfiles)
28 templatefile = joinpath(langoutdir,"fife.i.templ")
29
30 template = Template(open(templatefile).read())
31 inclusions = sorted(['%include ' + str(f) for f in source])
32 inclusions = '\n'.join(inclusions)
33 interfacefile = joinpath(langoutdir, 'fife.i')
34 open(interfacefile, 'w').write(template.substitute(inclusions=inclusions))
35
36 includepath = joinpath('engine', 'core')
37 # added -w511 to ignore warnings for "Can't use keyword arguments with overloaded functions"
38 pipe = os.popen(swigpath +'swig -w511 -c++ -%s -I%s -outdir %s %s' % (lang, includepath, langoutdir, interfacefile))
39 if pipe.close():
40 print "\nError while running swig, stopped"
41 Exit(1)
42
43 print "Running swig..."
44 generate_language_specifics(env['script'])
45 print "Swig completed"
46
47 def swig_wrapper_emitter(target, source, env):
48 target_append = []
49 for t in target:
50 t = str(t)
51 if t.endswith('.py'):
52 t = t[:-3]
53 else:
54 continue
55 target_append.append(t + '.i')
56 target_append.append(t + '_wrap.cxx')
57 target_append.append(t + '_wrap.h')
58 for t in target_append:
59 target.append(t)
60 return target, source
61
62 swig_wrapper_builder = Builder(action = generate_swig_wrappers, suffix = '.py', source_suffix = '.i', emitter = swig_wrapper_emitter)
63 env.Append(BUILDERS = {'SwigWrappers': swig_wrapper_builder})
64 35
65 36
66 def remove_based_on_dir_filter(dirfilters, files): 37 #**************************************************************************
67 abspaths = [] 38 #python
68 for pathstr in dirfilters: 39 #**************************************************************************
69 abspaths.append(os.path.abspath(joinpath(*pathstr.split('/'))))
70 40
71 result = [] 41 #generate swig interface file
72 for f in files: 42 utils.gen_swig_interface(os.path.join(engine_path, 'swigwrappers', 'python', 'fife.i.templ'),
73 filtered = False 43 intfiles,
74 for p in abspaths: 44 os.path.join(engine_path, 'swigwrappers', 'python'))
75 if str(f.abspath()).find(p) != -1:
76 filtered = True
77 break
78 if not filtered:
79 result.append(f)
80 return result
81 45
82 def check_for_duplicate_files(files): 46 pyfiles = list(compilefiles)
83 dupePaths = {}; dupes = [] 47 pyfiles.append([os.path.join('swigwrappers', 'python' ,'fife_wrap.cc')])
84 for f in files:
85 fname = os.path.basename(f)
86 try:
87 dupePaths[fname].append(f)
88 except KeyError:
89 dupePaths[fname] = [f]
90 for fname, paths in dupePaths.items():
91 if len(paths) > 1:
92 dupes.append('%s -> %s' % (fname, ', '.join(paths)))
93 if dupes:
94 print "\nError found: All cpp file names must be unique in FIFE, the following were not:"
95 for l in dupes: print l
96 Exit(1)
97 48
98 msvcbuildpath = joinpath('build', 'win32', 'build_environments', 'visual_studio_8') 49 #**************************************************************************
50 #Definition of scons builders for project files
51 #**************************************************************************
99 52
100 def generate_msvc_project(target, source, env): 53 msvc_project_builder = Builder(action = builders.generate_msvc_project, suffix = '.vcproj')
101 def create_dict_tree(source_dict):
102 for f in source_dict.keys():
103 parts = f.split(os.path.sep, 1)
104 if len(parts) > 1:
105 try:
106 source_dict[parts[0]][parts[1]] = {}
107 except KeyError:
108 source_dict[parts[0]] = {}
109 source_dict[parts[0]][parts[1]] = {}
110 del source_dict[f]
111 for k, d in source_dict.items():
112 create_dict_tree(d)
113 return source_dict
114
115 def get_msvc_repr(d, tabcount=2, curpath=''):
116 retstr = []
117 for k in sorted(d.keys()):
118 newpath = os.path.join(curpath, k)
119 if len(d[k].keys()):
120 retstr.append(tabcount * '\t' + '<Filter Name="%s">' % k)
121 retstr.append(get_msvc_repr(d[k], tabcount+1, newpath))
122 retstr.append(tabcount * '\t' + '</Filter>')
123 else:
124 newpath = os.path.join('..', '..', '..', '..', 'engine', newpath)
125 retstr.append(tabcount * '\t' + '<File RelativePath="%s"></File>' % newpath.replace('/','\\'))
126 return '\n'.join(retstr)
127
128 vcpaths = [os.path.abspath(str(f)).rsplit('%sengine%s' % (_sep, _sep))[-1] for f in source]
129 xmlstr = get_msvc_repr(create_dict_tree(dict([[p, {}] for p in vcpaths])))
130 projtxt = open(joinpath(msvcbuildpath, 'engine_template.xml'), 'r').read()
131 projtxt = projtxt.replace('__FILE_INSERTION_POINT__', xmlstr)
132
133 oldprojtxt = ''
134 try:
135 oldprojtxt = open(str(target[0]), 'r').read()
136 except:
137 pass
138
139 if(oldprojtxt <> projtxt):
140 open(str(target[0]), 'w').write(projtxt)
141 print "FIFE msvc project file succesfully created (%s)" % os.path.abspath(str(target[0]))
142 else:
143 print "FIFE msvc project file already up-to-date (%s)" % os.path.abspath(str(target[0]))
144
145 msvc_project_builder = Builder(action = generate_msvc_project, suffix = '.vcproj')
146 env.Append(BUILDERS = {'MSVCProject': msvc_project_builder}) 54 env.Append(BUILDERS = {'MSVCProject': msvc_project_builder})
147 55
148 msvcbuildpath9 = joinpath('build', 'win32', 'build_environments', 'visual_studio_9') 56 msvc_project_builder9 = Builder(action = builders.generate_msvc_project9, suffix = '.vcproj')
149
150 def generate_msvc_project9(target, source, env):
151 def create_dict_tree(source_dict):
152 for f in source_dict.keys():
153 parts = f.split(os.path.sep, 1)
154 if len(parts) > 1:
155 try:
156 source_dict[parts[0]][parts[1]] = {}
157 except KeyError:
158 source_dict[parts[0]] = {}
159 source_dict[parts[0]][parts[1]] = {}
160 del source_dict[f]
161 for k, d in source_dict.items():
162 create_dict_tree(d)
163 return source_dict
164
165 def get_msvc_repr(d, tabcount=2, curpath=''):
166 retstr = []
167 for k in sorted(d.keys()):
168 newpath = os.path.join(curpath, k)
169 if len(d[k].keys()):
170 retstr.append(tabcount * '\t' + '<Filter Name="%s">' % k)
171 retstr.append(get_msvc_repr(d[k], tabcount+1, newpath))
172 retstr.append(tabcount * '\t' + '</Filter>')
173 else:
174 newpath = os.path.join('..', '..', '..', '..', 'engine', newpath)
175 retstr.append(tabcount * '\t' + '<File RelativePath="%s"></File>' % newpath.replace('/','\\'))
176 return '\n'.join(retstr)
177
178 vcpaths = [os.path.abspath(str(f)).rsplit('%sengine%s' % (_sep, _sep))[-1] for f in source]
179 xmlstr = get_msvc_repr(create_dict_tree(dict([[p, {}] for p in vcpaths])))
180 projtxt = open(joinpath(msvcbuildpath9, 'engine_template.xml'), 'r').read()
181 projtxt = projtxt.replace('__FILE_INSERTION_POINT__', xmlstr)
182
183 oldprojtxt = ''
184 try:
185 oldprojtxt = open(str(target[0]), 'r').read()
186 except:
187 pass
188
189 if(oldprojtxt <> projtxt):
190 open(str(target[0]), 'w').write(projtxt)
191 print "FIFE msvc9 project file succesfully created (%s)" % os.path.abspath(str(target[0]))
192 else:
193 print "FIFE msvc9 project file already up-to-date (%s)" % os.path.abspath(str(target[0]))
194
195 msvc_project_builder9 = Builder(action = generate_msvc_project9, suffix = '.vcproj')
196 env.Append(BUILDERS = {'MSVCProject9': msvc_project_builder9}) 57 env.Append(BUILDERS = {'MSVCProject9': msvc_project_builder9})
197 58
198 cbbuildpath_win32 = joinpath('build', 'win32', 'build_environments', 'code_blocks') 59 codeblocks_project_builder_win32 = Builder(action = builders.generate_codeblocks_project_win32, suffix = '.cbp')
199
200 def generate_codeblocks_project_win32(target, source, env):
201 codeblocksHeaderDef = \
202 ''' <Unit filename="..\..\..\engine\%s">
203 <Option compilerVar=""/>
204 <Option compile="0"/>
205 <Option link="0"/>
206 <Option target="default"/>
207 </Unit>'''
208
209 codeblocksCppDef = \
210 ''' <Unit filename="..\..\..\..\engine\%s">
211 <Option compilerVar="CPP"/>
212 <Option target="default"/>
213 </Unit>'''
214 xmlstr = []
215 for f in source:
216 newf = os.path.abspath(str(f)).rsplit('%sengine%s' % (_sep, _sep))[-1]
217 newf = newf.replace('/', '\\')
218 if str(f) in headerfiles:
219 xmlstr.append(codeblocksHeaderDef % newf)
220 else:
221 xmlstr.append(codeblocksCppDef % newf)
222 projtxt = open(joinpath(cbbuildpath_win32, 'engine_template.xml'), 'r').read()
223 projtxt = projtxt.replace('__FILE_INSERTION_POINT__', '\n'.join(xmlstr))
224 open(str(target[0]), 'w').write(projtxt)
225 print "FIFE code::blocks project file succesfully created (%s)" % os.path.abspath(str(target[0]))
226
227 codeblocks_project_builder_win32 = Builder(action = generate_codeblocks_project_win32, suffix = '.cbp')
228 env.Append(BUILDERS = {'CodeblocksProjectWin32': codeblocks_project_builder_win32}) 60 env.Append(BUILDERS = {'CodeblocksProjectWin32': codeblocks_project_builder_win32})
229 61
230 62 codeblocks_project_builder_linux = Builder(action = builders.generate_codeblocks_project_linux, suffix = '.cbp')
231 cbbuildpath_linux = joinpath('build', 'linux', 'code_blocks')
232
233 def generate_codeblocks_project_linux(target, source, env):
234 codeblocksHeaderDef = \
235 ''' <Unit filename="../../../engine/%s">
236 <Option compilerVar=""/>
237 <Option compile="0"/>
238 <Option link="0"/>
239 <Option target="default"/>
240 </Unit>'''
241
242 codeblocksCppDef = \
243 ''' <Unit filename="../../../engine/%s">
244 <Option compilerVar="CPP"/>
245 <Option target="default"/>
246 </Unit>'''
247 xmlstr = []
248 for f in source:
249 newf = os.path.abspath(str(f)).rsplit('%sengine%s' % (_sep, _sep))[-1]
250 newf = newf.replace('/', '\\')
251 if str(f) in headerfiles:
252 xmlstr.append(codeblocksHeaderDef % newf)
253 else:
254 xmlstr.append(codeblocksCppDef % newf)
255 projtxt = open(joinpath(cbbuildpath_linux, 'engine_template.xml'), 'r').read()
256 projtxt = projtxt.replace('__FILE_INSERTION_POINT__', '\n'.join(xmlstr))
257 open(str(target[0]), 'w').write(projtxt)
258 print "FIFE code::blocks project file succesfully created (%s)" % os.path.abspath(str(target[0]))
259
260 codeblocks_project_builder_linux = Builder(action = generate_codeblocks_project_linux, suffix = '.cbp')
261 env.Append(BUILDERS = {'CodeblocksProjectLinux': codeblocks_project_builder_linux}) 63 env.Append(BUILDERS = {'CodeblocksProjectLinux': codeblocks_project_builder_linux})
262 64
65 python_extensions_builder = Builder(action = "$SWIG -o $TARGET ${_SWIGOUTDIR} ${_SWIGINCFLAGS} $SWIGFLAGS $SOURCES")
66 env.Append(BUILDERS = {'PythonExtensions': python_extensions_builder})
263 67
264 variated_dirs = eval(open(joinpath('config', 'variated_dirs'), 'r').read())
265 # filter out swigwrappers. fife_wrap.cxx is appended manually
266 # as it might not exist yet during SConscript parsing
267 filteredpaths = ['swigwrappers']
268 for flag, paths in variated_dirs.items():
269 value = None
270 if flag.find('-') != -1:
271 flag, value = flag.split('-')
272 if (value and (not env[flag] == value)) or (not env[flag]):
273 filteredpaths.extend(paths)
274 68
275 tmpfiles = remove_based_on_dir_filter(filteredpaths, list(enginepath.walkfiles('*.i'))) 69 #**************************************************************************
276 interfacefiles = [] 70 #project files target
277 for f in tmpfiles: 71 #**************************************************************************
278 if f.startswith('.' + _sep):
279 interfacefiles.append(f[2:])
280 else:
281 interfacefiles.append(f)
282 72
283 swig = env.SwigWrappers('swigwrappers/python/fife', interfacefiles) 73 projectfiles = compilefiles + headerfiles
284 env.Install('$PREFIX/lib/python%s/site-packages/fife'%sys.version[:3], ['swigwrappers/python/fife.py']) 74 #projectfiles.append('swigwrappers/python/fife_wrap.cc')
285 75
286 allfiles = list(enginepath.walkfiles()) 76 msvcproj = env.MSVCProject(os.path.join('..', '..','..', builders.msvcbuildpath, 'fife'), projectfiles)
287 headerfiles = [f for f in allfiles if is_headerfile(f)] 77 msvcproj9 = env.MSVCProject9(os.path.join('..', '..','..', builders.msvcbuildpath9, 'fife'), projectfiles)
288 implfiles = [f for f in allfiles if is_implfile(f)] 78 cbproj_win32 = env.CodeblocksProjectWin32(os.path.join('..', '..','..', builders.cbbuildpath_win32, 'fife_engine'), projectfiles)
289 extensionfiles = list(extensionpath.walkfiles('*.py')) 79 cbproj_linux = env.CodeblocksProjectLinux(os.path.join('..', '..','..', builders.cbbuildpath_linux, 'fife_engine'), projectfiles)
290 80
291 filtered_prj_paths = eval(open(joinpath('config', 'removed_from_project_files'), 'r').read())
292 filtered_prj_paths = [joinpath(*p.split('/')) for p in filtered_prj_paths]
293 projectfiles = [str(f) for f in remove_based_on_dir_filter(filtered_prj_paths, headerfiles + implfiles)]
294 81
295 projectfiles.append('./swigwrappers/%s/fife_wrap.cxx' % env['script']) 82 #**************************************************************************
83 #shared library target
84 #**************************************************************************
296 85
297 msvcproj = env.MSVCProject(joinpath('..', msvcbuildpath, 'fife'), projectfiles) 86 if sys.platform == 'win32':
298 msvcproj9 = env.MSVCProject9(joinpath('..', msvcbuildpath9, 'fife'), projectfiles) 87 sharedlib = env.SharedLibrary(target = 'fife',
299 cbproj_win32 = env.CodeblocksProjectWin32(joinpath('..', cbbuildpath_win32, 'fife_engine'), projectfiles) 88 source = compilefiles,
300 cbproj_linux = env.CodeblocksProjectLinux(joinpath('..', cbbuildpath_linux, 'fife_engine'), projectfiles) 89 LINKFLAGS=['-Wl'],
90 OBJPREFIX='shared_',
91 SHLIBEMITTER = '')
92 else:
93 sharedlib = env.SharedLibrary(target = 'fife',
94 source = compilefiles,
95 LINKFLAGS=['-Wl'])
301 96
302 if not env['projectfiles_only']: 97 #**************************************************************************
303 env.Append(CPPPATH = ['#/engine/core', '#/engine/swigwrappers']) 98 #python library target
304 compilefiles = [str(f) for f in remove_based_on_dir_filter(filteredpaths, implfiles)] 99 #**************************************************************************
305 compilefiles.append('./swigwrappers/%s/fife_wrap.cxx' % env['script']) 100 if sys.platform == 'win32':
306 if sys.platform == 'darwin': 101 dest_suffix = '.pyd'
307 flib = env.SharedLibrary('fife', compilefiles, LINKFLAGS=['-Wl']) 102 else:
308 else: 103 dest_suffix = '.so'
309 flib = env.SharedLibrary('fife', compilefiles, LINKFLAGS=['-Wl,-rpath,../../ext/install/lib,-rpath,../ext/install/lib,-rpath,ext/install/lib']) 104
310 if sys.platform != 'win32': 105 pythonlib = env.SharedLibrary(target = 'fife',
311 env.Command('swigwrappers/%s/_fife.so' % env['script'], flib, [Copy('$TARGET', '$SOURCE')]) 106 source = pyfiles,
312 if sys.platform != 'darwin': 107 OBJPREFIX='py_',
313 env.Install('$PREFIX/lib/python%s/site-packages/fife'%sys.version[:3], flib) 108 SHLIBPREFIX='_',
314 # env.Install('$PREFIX/lib/python%s/site-packages/fife'%sys.version[:3], [str(f) for f in extensionfiles]) 109 SHLIBSUFFIX=dest_suffix,
110 LINKFLAGS=['-Wl'],
111 SHLIBEMITTER = '')
112
113 pythonext = env.PythonExtensions(target = [os.path.join('swigwrappers', 'python' ,'fife_wrap.cc'), os.path.join('python', 'fife', 'fife.py')],
114 source = os.path.join('swigwrappers', 'python' ,'fife.i'),
115 SWIGFLAGS=['-python','-c++','-w511'],
116 SWIGPATH='core',
117 SWIGOUTDIR=Dir('#/engine/python/fife').srcnode().path)
118
119
120 copy_dest = os.path.join(opts['PYLIB_COPY_DEST'], '_fife' + dest_suffix)
121 copy_cmd = env.Command(copy_dest, pythonlib, [Copy('$TARGET', '$SOURCE')])
122 copy_cmd2 = env.Command(os.path.join(opts['WRAP_COPY_DEST'], 'fife_wrap.h'),
123 os.path.join('swigwrappers','python','fife_wrap.h'),
124 [Copy('$TARGET', '$SOURCE')])
125 copy_cmd3 = env.Command(os.path.join(opts['WRAP_COPY_DEST'], 'fife_wrap.cc'),
126 os.path.join('swigwrappers','python','fife_wrap.cc'),
127 [Copy('$TARGET', '$SOURCE')])
128
129 #**************************************************************************
130 #static library target
131 #**************************************************************************
132
133 staticlib = env.StaticLibrary(target = 'fife',
134 source = compilefiles,
135 LINKFLAGS=['-Wl'])
136
137 #**************************************************************************
138 #Install targets
139 #**************************************************************************
140
141 #TODO: This is not complete. Because of the current linux rpath issue this
142 #will not work as expected.
143 install_static = env.Install(os.path.join(opts['PREFIX'], 'lib'), staticlib)
144 install_shared = env.Install(os.path.join(opts['PREFIX'], 'lib'), sharedlib)
145
146 headerdestlist = utils.gen_dest_files(os.path.join(opts['PREFIX'], 'include', 'fife'), headerfiles)
147 install_headers = env.InstallAs(headerdestlist, headerfiles)
148
149 pypath = os.path.join(opts['PYTHON_PREFIX'], 'fife')
150 extdestfilelist = utils.gen_dest_files(pypath, relextensionfiles)
151
152 install_python_lib = env.Install(pypath, pythonlib)
153 install_python_module = env.Install(pypath, ['#/engine/python/fife/fife.py','#/engine/python/fife/__init__.py'])
154 install_python_extensions = env.InstallAs(extdestfilelist, extensionfiles)
155
156 #**************************************************************************
157 #Alias definitions
158 #**************************************************************************
159
160 alias_msvc = Alias('msvc',msvcproj)
161 alias_msvc9 = Alias('msvc9',msvcproj9)
162 alias_cbwin32 = Alias('cbwin32',cbproj_win32)
163 alias_cblinux = Alias('cblinux',cbproj_linux)
164 Alias('projects',[alias_msvc, alias_msvc9, alias_cbwin32, alias_cblinux])
165
166 alias_shared = Alias('fife-shared', sharedlib)
167 alias_static = Alias('fife-static', staticlib)
168 alias_swig = Alias('fife-swig', [pythonext, copy_cmd2, copy_cmd3])
169 alias_python = Alias('fife-python', [pythonlib, copy_cmd, alias_swig])
170 Alias('fife', [alias_shared, alias_static, alias_python])
171
172 alias_install_shared = Alias('install-shared', install_shared)
173 alias_install_static = Alias('install-static', install_static)
174 alias_install_python = Alias('install-python', [alias_python, install_python_lib, install_python_module, install_python_extensions])
175 alias_install_dev = Alias('install-dev', [alias_install_shared, alias_install_static, install_headers])
176 Alias('install-all', [alias_install_python, alias_install_dev])