comparison SConstruct @ 2:e2a8e3805b04

Made parpg-core the main repository to pull from and build. * Added parpg-assets as a subrepo under the data folder. * Moved the SConstruct script into parpg-core and modified it to build and install parpg-assets as well. * Made a few minor changes to the SConstruct file from the defunct parpg-main repository. * Modified unix parpg executable script template to be more forgiving of installing the parpg Python package outside of PYTHONPATH. * Updated the .hgignore file to include temporary SCons files.
author M. George Hansen <technopolitica@gmail.com>
date Sun, 15 May 2011 14:51:41 -0700
parents
children 33684971cdb1
comparison
equal deleted inserted replaced
0:1fd2201f5c36 2:e2a8e3805b04
1 import sys
2 import os
3 import platform
4 import compileall
5 import fnmatch
6 from collections import Sequence
7 from multiprocessing import cpu_count
8
9 def InstallChmod(env, dest, source, mode):
10 targets = env.Install(dest, source)
11 for target in targets:
12 env.AddPostAction(target, Chmod(target, mode))
13 return targets
14
15 def InstallExecutable(env, dest, source):
16 return env.InstallChmod(dest, source, mode=0755)
17
18 def InstallReadOnly(env, dest, source):
19 if not isinstance(source, Sequence):
20 source = [source]
21 targets = []
22 for entry in map(Entry, source):
23 entry.disambiguate()
24 if entry.isdir():
25 target = env.InstallChmod(dest, entry, mode=0755)
26 elif entry.isfile():
27 target = env.InstallChmod(dest, entry, mode=0644)
28 else:
29 # Something really weird happened and entry is not a Dir or a
30 # File... (Note: Yes this can happen!)
31 error_message = \
32 'expected entry to be a Dir or a File, but got {0!r}'
33 raise ValueError(error_message.format(entry))
34 targets.append(target)
35 return targets
36
37 def InstallPyPackages(env, dest, source, compile=True):
38 # Remove all existing *.pyc and *.pyo files for a sanitary install
39 # environment.
40 def _remove_compiled_modules(path):
41 for dir_path, dir_names, file_names in os.walk(path):
42 for file_name in fnmatch.filter(file_names, '*.py[co]'):
43 file_path = os.path.join(dir_path, file_name)
44 os.remove(file_path)
45
46 def _add_targets(path):
47 for dir_path, dir_names, file_names in os.walk(path):
48 for file_name in fnmatch.filter(file_names, '*.py[co]'):
49 file_path = os.path.join(dir_path, file_name)
50 env.Clean(path, file_path)
51 source_file_path = file_path.rstrip('oc')
52 env.Depends(file_path, source_file_path)
53
54 if not isinstance(source, Sequence):
55 source = [source]
56 for dir in source:
57 _remove_compiled_modules(str(dir))
58 if compile:
59 compileall.compile_dir(str(dir), ddir=str(dest), force=True)
60 _add_targets(str(dir))
61 targets = env.InstallReadOnly(dest, source)
62 return targets
63
64 AddMethod(Environment, InstallChmod)
65 AddMethod(Environment, InstallExecutable)
66 AddMethod(Environment, InstallReadOnly)
67 AddMethod(Environment, InstallPyPackages)
68
69 EnsurePythonVersion(2, 6)
70
71 AddOption(
72 '--stand-alone',
73 dest='stand_alone',
74 action='store_true',
75 default=False,
76 help='install the entire program under installation prefix instead of in '
77 'various system folders'
78 )
79 AddOption(
80 '--no-compile',
81 dest='compile',
82 action='store_false',
83 default=True,
84 help='don\'t compile any Python modules into .pyc files',
85 )
86 SetOption('num_jobs', cpu_count())
87
88 def is_abs_path(key, val, env):
89 if not os.path.isabs(val):
90 error_message = '${key} must be an absolute path'
91 raise ValueError(error_message.format(key=key))
92 env[key] = os.path.normpath(val)
93
94 variables = Variables()
95 # NOTE M. George Hansen 2011-05-13: Path variables are based on the GNU
96 # standards as defined at http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
97
98 # Platform-specific variable defaults.
99 # FIXME M. George Hansen 2011-05-12: Define the MacOS-specific
100 # environmental variables (and check version...)
101 platform_name = platform.system()
102 if platform_name in ['Linux', 'MacOS']:
103 if GetOption('stand_alone'):
104 PREFIX_DEFAULT = '/opt'
105 else:
106 PREFIX_DEFAULT = '/usr/local'
107 BIN_DIR_DEFAULT = '$EXEC_PREFIX/bin'
108 DATA_ROOT_DIR_DEFAULT = '$PREFIX/share/$PROJECT_NAME'
109 SYS_CONF_DIR_DEFAULT = '$PREFIX/etc/$PROJECT_NAME'
110 INCLUDE_DIR_DEFAULT = '$PREFIX/include/$PROJECT_NAME'
111 DOC_DIR_DEFAULT = '$DATA_ROOT_DIR/doc/$PROJECT_NAME'
112 LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib'
113 dist_name, dist_version, dist_id = \
114 platform.linux_distribution(full_distribution_name=False)
115 if dist_name in ['debian', 'Ubuntu']:
116 # Debian uses dist-packages instead of site-packages for Python
117 # versions > 2.5.
118 PY_LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib/python$PY_VERSION_SHORT/' \
119 'dist-packages'
120 else:
121 PY_LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib/python$PY_VERSION_SHORT/' \
122 'site-packages'
123 elif platform_name == 'Windows':
124 try:
125 PREFIX_DEFAULT = os.environ['ProgramFiles'] + r'\$PROGRAM_NAME'
126 except KeyError:
127 PREFIX_DEFAULT = ''
128 error_message = '%ProgramFiles% environmental variable is not ' \
129 'set, unable to determine path to Program Files ' \
130 'folder (use --prefix to override)'
131 raise SConfWarning(error_message)
132 BIN_DIR_DEFAULT = '$EXEC_PREFIX'
133 DATA_ROOT_DIR_DEFAULT = '$PREFIX/data'
134 SYS_CONF_DIR_DEFAULT = '$PREFIX/config'
135 INCLUDE_DIR_DEFAULT = '$PREFIX/include'
136 DOC_DIR_DEFAULT = '$PREFIX/doc/'
137 LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib'
138 PY_LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib'
139 if GetOption('stand_alone'):
140 PY_LIB_DIR_DEFAULT = '$PREFIX/lib'
141 else:
142 python_prefix = sys.prefix
143 # FIXME M. George Hansen 2011-05-12: Does sys.prefix include the
144 # PythonX.Y part on Windows?
145 PY_LIB_DIR_DEFAULT = \
146 os.path.join(python_prefix, 'Lib', 'site-packages')
147
148 # Platform-independant variables:
149 variables.AddVariables(
150 PathVariable(
151 'PREFIX',
152 'directory under which most or all of the program components should '
153 'be installed',
154 PREFIX_DEFAULT,
155 is_abs_path,
156 ),
157 PathVariable(
158 'EXEC_PREFIX',
159 'directory under which machine-specific compiled libraries and '
160 'objects should be installed',
161 '$PREFIX',
162 is_abs_path,
163 ),
164 PathVariable(
165 'BIN_DIR',
166 'directory where program executables should be installed',
167 BIN_DIR_DEFAULT,
168 is_abs_path,
169 ),
170 PathVariable(
171 'DATA_ROOT_DIR',
172 'directory under which read-only, architecture-independant data files '
173 'should be installed',
174 DATA_ROOT_DIR_DEFAULT,
175 is_abs_path,
176 ),
177 PathVariable(
178 'DATA_DIR',
179 'directory where read-only, architecture-independant data files '
180 'should be installed',
181 '$DATA_ROOT_DIR',
182 is_abs_path,
183 ),
184 PathVariable(
185 'SYS_CONF_DIR',
186 'directory where read-only, machine-specific data files should be '
187 'installed',
188 SYS_CONF_DIR_DEFAULT,
189 is_abs_path,
190 ),
191 PathVariable(
192 'INCLUDE_DIR',
193 'directory where C/C++ header files should be installed',
194 INCLUDE_DIR_DEFAULT,
195 is_abs_path,
196 ),
197 PathVariable(
198 'DOC_DIR',
199 'directory where program documentation should be installed',
200 DOC_DIR_DEFAULT,
201 is_abs_path,
202 ),
203 PathVariable(
204 'LIB_DIR',
205 'directory where platform-dependant, compiled library and object '
206 'files should be installed',
207 LIB_DIR_DEFAULT,
208 is_abs_path,
209 ),
210 PathVariable(
211 'PY_LIB_DIR',
212 'directory where pure Python modules and packages should be installed',
213 PY_LIB_DIR_DEFAULT,
214 is_abs_path,
215 ),
216 PathVariable(
217 'INCLUDE_DIR',
218 'directory where C/C++ header files should be installed',
219 INCLUDE_DIR_DEFAULT,
220 is_abs_path,
221 ),
222 )
223
224 platform_name = platform.system()
225 python_version_tuple = platform.python_version_tuple()
226
227 environment = Environment(
228 tools=['default', 'textfile', 'packaging'],
229 variables=variables,
230 PROJECT_NAME='parpg',
231 PROJECT_VERSION_MAJOR=0,
232 PROJECT_VERSION_MINOR=2,
233 PROJECT_VERSION_PATCH=0,
234 PROJECT_VERSION_SHORT='$PROJECT_VERSION_MAJOR.$PROJECT_VERSION_MAJOR',
235 PROJECT_VERSION_LONG='$PROJECT_VERSION_MAJOR.$PROJECT_VERSION_MINOR.'
236 '$PROJECT_VERSION_PATCH',
237 PYTHON=sys.executable,
238 PY_VERSION_SHORT='.'.join(python_version_tuple[:-1]),
239 PY_VERSION_LONG='.'.join(python_version_tuple),
240 PY_PACKAGES=[],
241 CONFIG_FILES=[],
242 DATA_FILES=[],
243 EXECUTABLES=[],
244 )
245 Help(variables.GenerateHelpText(environment))
246
247 config_dict = [('@{0}@'.format(key), environment.Dictionary()[key]) for key in
248 ('PREFIX', 'LIB_DIR', 'PY_LIB_DIR', 'BIN_DIR', 'SYS_CONF_DIR',
249 'DATA_DIR', 'PYTHON')]
250
251 environment['PY_PACKAGES'] += [
252 Dir('src/parpg'),
253 ]
254 config_file_template = File('system.cfg.in')
255 subst_config_file = environment.Substfile(config_file_template,
256 SUBST_DICT=config_dict)
257 environment['CONFIG_FILES'] += [subst_config_file]
258 environment['DATA_FILES'] += Glob('data/*')
259 # TODO M. George Hansen 2011-05-12: Implement windows executable.
260 executable_template = File('bin/unix/parpg.in')
261 subst_executable = environment.Substfile(executable_template,
262 SUBST_DICT=config_dict)
263 environment['EXECUTABLES'] += [subst_executable]
264
265 sources = environment.InstallPyPackages(
266 '$PY_LIB_DIR',
267 environment['PY_PACKAGES'],
268 compile=GetOption('compile'),
269 )
270 config_files = environment.InstallChmod(
271 '$SYS_CONF_DIR',
272 environment['CONFIG_FILES'],
273 mode=0755,
274 )
275 Requires(config_files, subst_config_file)
276 data_files = environment.InstallReadOnly(
277 '$DATA_DIR',
278 environment['DATA_FILES'],
279 )
280 executables = environment.InstallExecutable(
281 '$BIN_DIR',
282 environment['EXECUTABLES'],
283 )
284 Requires(executables, subst_executable)
285
286 # TODO M. George Hansen 2011-05-12: Implement package builder.
287 #package = environment.Package(
288 # NAME='parpg',
289 # VERSION='0.2.0',
290 # PACKAGEVERSION=0,
291 # LICENSE='gpl',
292 # SUMMARY='',
293 # DESCRIPTION='',
294 # X_RPM_GROUP='Application/parpg',
295 #)
296
297 Default([sources, config_files, data_files, executables])
298 Alias('install', [sources, config_files, data_files, executables])