Mercurial > parpg-core
comparison SConstruct @ 6:dd4ed4945411
Ported binary launcher to Windows.
* Reorganized the parpg executable source so that it now compiles with the MSVC compiler (tested with MSVC Express 2010).
* Cleaned up the launcher source by adding a bunch of const statements and removing the superfluous NULL_TERMINATE macro.
* Fixed a few memory leaks in the launcher source by freeing malloced/calloced pointers;
* Added a new SubstfileEscape builder to the SConstruct script used to escape certain sequences when substituting a template file. This is used to escape backslashes ("\") in c strings in the bin/parpg.c.in template for Windows paths.
* Fixed the PY_LIB_DIR_DEFAULT for Windows so that it now correctly points to the default Python installation path.
* Modified the SConstruct script to support compiling the launcher executable with debugging symbols in Windows with the DEBUG flag.
author | M. George Hansen |
---|---|
date | Sun, 22 May 2011 00:53:59 -0700 |
parents | 33684971cdb1 |
children | 4706e0194af3 |
comparison
equal
deleted
inserted
replaced
5:33684971cdb1 | 6:dd4ed4945411 |
---|---|
4 import compileall | 4 import compileall |
5 import fnmatch | 5 import fnmatch |
6 from collections import Sequence | 6 from collections import Sequence |
7 from types import StringType | 7 from types import StringType |
8 from multiprocessing import cpu_count | 8 from multiprocessing import cpu_count |
9 | |
10 from SCons.Util import is_Sequence, is_Dict | |
9 | 11 |
10 def InstallChmod(env, dest, source, mode): | 12 def InstallChmod(env, dest, source, mode): |
11 targets = env.Install(dest, source) | 13 targets = env.Install(dest, source) |
12 for target in targets: | 14 for target in targets: |
13 env.AddPostAction(target, Chmod(target, mode)) | 15 env.AddPostAction(target, Chmod(target, mode)) |
60 compileall.compile_dir(str(dir), ddir=str(dest), force=True) | 62 compileall.compile_dir(str(dir), ddir=str(dest), force=True) |
61 _add_targets(str(dir)) | 63 _add_targets(str(dir)) |
62 targets = env.InstallReadOnly(dest, source) | 64 targets = env.InstallReadOnly(dest, source) |
63 return targets | 65 return targets |
64 | 66 |
67 def SubstfileEscape(env, *args, **kwargs): | |
68 subst_dict = kwargs.get('SUBST_DICT') or env.get('SUBST_DICT') | |
69 escape_sequences = kwargs.get('ESCAPE_SEQUENCES') or env.get('ESCAPE_SEQUENCES') | |
70 if subst_dict is not None and escape_sequences is not None: | |
71 if not is_Dict(subst_dict) and is_Sequence(subst_dict): | |
72 subst_dict = dict(subst_dict) | |
73 else: | |
74 error_message = 'SUBST_DICT must be dict or sequence' | |
75 raise SCons.Errors.UserError(error_message) | |
76 escaped_subst_dict = {} | |
77 for key, value in subst_dict.items(): | |
78 escaped_value = value | |
79 for seq, escaped_seq in escape_sequences.items(): | |
80 escaped_value = escaped_value.replace(seq, escaped_seq) | |
81 escaped_subst_dict[key] = escaped_value | |
82 kwargs['SUBST_DICT'] = escaped_subst_dict | |
83 | |
84 target = env.Substfile(*args, **kwargs) | |
85 return target | |
86 | |
65 AddMethod(Environment, InstallChmod) | 87 AddMethod(Environment, InstallChmod) |
66 AddMethod(Environment, InstallExecutable) | 88 AddMethod(Environment, InstallExecutable) |
67 AddMethod(Environment, InstallReadOnly) | 89 AddMethod(Environment, InstallReadOnly) |
68 AddMethod(Environment, InstallPyPackages) | 90 AddMethod(Environment, InstallPyPackages) |
91 AddMethod(Environment, SubstfileEscape) | |
69 | 92 |
70 EnsurePythonVersion(2, 6) | 93 EnsurePythonVersion(2, 6) |
71 | 94 |
72 AddOption( | 95 AddOption( |
73 '--stand-alone', | 96 '--stand-alone', |
137 DATA_ROOT_DIR_DEFAULT = '$PREFIX/data' | 160 DATA_ROOT_DIR_DEFAULT = '$PREFIX/data' |
138 SYS_CONF_DIR_DEFAULT = '$PREFIX/config' | 161 SYS_CONF_DIR_DEFAULT = '$PREFIX/config' |
139 INCLUDE_DIR_DEFAULT = '$PREFIX/include' | 162 INCLUDE_DIR_DEFAULT = '$PREFIX/include' |
140 DOC_DIR_DEFAULT = '$PREFIX/doc/' | 163 DOC_DIR_DEFAULT = '$PREFIX/doc/' |
141 LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib' | 164 LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib' |
142 PY_LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib' | |
143 # FIXME M. George Hansen 2011-05-12: Does sys.prefix include the | 165 # FIXME M. George Hansen 2011-05-12: Does sys.prefix include the |
144 # PythonX.Y part on Windows? | 166 # PythonX.Y part on Windows? |
145 python_prefix = sys.prefix | 167 python_prefix = sys.prefix |
146 if GetOption('stand_alone'): | 168 if GetOption('stand_alone'): |
147 PY_PACKAGES_DIR_DEFAULT = '$PREFIX/lib' | 169 PY_PACKAGES_DIR_DEFAULT = '$PREFIX/lib' |
148 else: | 170 else: |
149 PY_PACKAGES_DIR_DEFAULT = \ | 171 PY_PACKAGES_DIR_DEFAULT = \ |
150 os.path.join(python_prefix, 'Lib', 'site-packages') | 172 os.path.join(python_prefix, 'Lib', 'site-packages') |
151 PY_HEADERS_DIR_DEFAULT = os.path.join(python_prefix, 'include') | 173 PY_HEADERS_DIR_DEFAULT = os.path.join(python_prefix, 'include') |
152 try: | 174 PY_LIB_DIR_DEFAULT = os.path.join(python_prefix, 'libs') |
153 PY_LIB_DIR_DEFAULT = os.environ['SYSTEMROOT'] | |
154 except KeyError: | |
155 PY_LIB_DIR_DEFAULT = '' | |
156 error_message = '%SYSTEMROOT% environmental variable is not set, ' \ | |
157 'unable to determine path to Windows system folder' | |
158 raise SConfWarning(error_message) | |
159 PY_LIB_NAME = 'python$PY_VERSION_MAJOR$PY_VERSION_MINOR' | 175 PY_LIB_NAME = 'python$PY_VERSION_MAJOR$PY_VERSION_MINOR' |
160 | 176 |
161 # Platform-independant variables: | 177 # Platform-independant variables: |
162 variables.AddVariables( | 178 variables.AddVariables( |
163 PathVariable( | 179 PathVariable( |
248 'symbols', | 264 'symbols', |
249 False, | 265 False, |
250 ), | 266 ), |
251 ) | 267 ) |
252 | 268 |
253 platform_name = platform.system() | |
254 python_version_tuple = platform.python_version_tuple() | 269 python_version_tuple = platform.python_version_tuple() |
255 | 270 |
256 environment = Environment( | 271 environment = Environment( |
257 tools=['default', 'cc', 'textfile', 'packaging'], | 272 tools=['default', 'textfile', 'packaging'], |
258 variables=variables, | 273 variables=variables, |
259 PROJECT_NAME='parpg', | 274 PROJECT_NAME='parpg', |
260 PROJECT_VERSION_MAJOR=0, | 275 PROJECT_VERSION_MAJOR=0, |
261 PROJECT_VERSION_MINOR=2, | 276 PROJECT_VERSION_MINOR=2, |
262 PROJECT_VERSION_PATCH=0, | 277 PROJECT_VERSION_PATCH=0, |
275 CONFIG_FILES=[], | 290 CONFIG_FILES=[], |
276 DATA_FILES=[], | 291 DATA_FILES=[], |
277 EXECUTABLES=[], | 292 EXECUTABLES=[], |
278 ) | 293 ) |
279 if environment['DEBUG']: | 294 if environment['DEBUG']: |
280 environment.AppendUnique(CCFLAGS=['-gdwarf-2', '-g3']) | 295 if platform_name == 'Windows': |
296 environment['CCPDBFLAGS'] = '/Z7 /Od' | |
297 environment.AppendUnique(LINKFLAGS='/DEBUG') | |
298 else: | |
299 environment.AppendUnique(CCFLAGS=['-gdwarf-2', '-g3']) | |
281 | 300 |
282 Help(variables.GenerateHelpText(environment)) | 301 Help(variables.GenerateHelpText(environment)) |
283 | 302 |
284 config_dict = [('@{0}@'.format(key), environment.Dictionary()[key]) for key in | 303 config_dict = [('@{0}@'.format(key), environment.Dictionary()[key]) for key in |
285 ('PREFIX', 'LIB_DIR', 'PY_PACKAGES_DIR', 'BIN_DIR', | 304 ('PREFIX', 'LIB_DIR', 'PY_PACKAGES_DIR', 'BIN_DIR', |
305 install_data = environment.InstallReadOnly( | 324 install_data = environment.InstallReadOnly( |
306 '$DATA_DIR', | 325 '$DATA_DIR', |
307 Glob('data/*'), | 326 Glob('data/*'), |
308 ) | 327 ) |
309 | 328 |
310 executable_source = environment.Substfile( | 329 # FIXME M. George Hansen 2011-05-20: Do any other sequences need to be escaped |
330 # in a C string? | |
331 executable_source = environment.SubstfileEscape( | |
311 'bin/parpg.c.in', | 332 'bin/parpg.c.in', |
312 SUBST_DICT=config_dict, | 333 SUBST_DICT=config_dict, |
334 ESCAPE_SEQUENCES={'\\': r'\\\\', '"': r'\\"'}, | |
313 ) | 335 ) |
314 build_executable = environment.Program( | 336 build_executable = environment.Program( |
315 executable_source, | 337 executable_source, |
316 LIBS=['$PY_LIB_NAME'], | 338 LIBS=['$PY_LIB_NAME'], |
317 LIBPATH='$PY_LIB_DIR', | 339 LIBPATH='$PY_LIB_DIR', |
318 CPPPATH=['$PY_HEADERS_DIR'], | 340 CPPPATH=['$PY_HEADERS_DIR'], |
319 ) | 341 ) |
320 # FIXME M. George Hansen 2011-05-17: Should the executable target be hard-coded | 342 # Clean up any files created by the MSVC compiler on Windows. |
321 # like this? | 343 if platform_name == 'Windows': |
344 environment.Clean(build_executable, 'bin/parpg.ilk') | |
345 environment.Clean(build_executable, 'bin/parpg.pdb') | |
322 install_executable = environment.InstallExecutable( | 346 install_executable = environment.InstallExecutable( |
323 '$BIN_DIR', | 347 '$BIN_DIR', |
324 'bin/parpg', | 348 build_executable, |
325 ) | 349 ) |
326 | 350 |
327 # TODO M. George Hansen 2011-05-12: Implement package builder. | 351 # TODO M. George Hansen 2011-05-12: Implement package builder. |
328 #package = environment.Package( | 352 #package = environment.Package( |
329 # NAME='parpg', | 353 # NAME='parpg', |