comparison site_scons/site_tools/cpython/__init__.py @ 11:4706e0194af3

Various improvements to the build process including support for self-contained builds. * Note that despite all of these changes PARPG still does not run because asset paths are not standardized, * Modified the SCons script so that by default running `scons` with no arguments creates a self-contained "build" under a build subdirectory to make in-source testing easier. To install PARPG, use `scons install` instead. * Got rid of the binary launcher and replaced it with a shell script for unix and a batch script for Windows (batch script is untested). The binary turned out to be too much trouble to maintain. * Modified the parpg.settings module and parpg.main entry script so that PARPG searches through several default search paths for configuration file(s). PARPG thus no longer crashes if it can't find a configuration file in any particular search path, but will crash it if can't find any configuration files. * Paths supplied to parpg.main are now appended as search paths for the configuration file(s). * Changed the default configuration file name to "parpg.cfg" to simplify searches. * Created the site_scons directory tree where SCons extensions and tools should be placed. * Created a new SCons builder, CopyRecurse, which can copy only certain files and folders from a directory tree using filters (files and folders that start with a leading dot "." e.g. ".svn" are ignored by default). * Added the CPython SCons tool (stands for Compile-Python - I didn't name it!), which provides the InstallPython builder for pre-compiling python sources before they are installed. However, it is currently broken and only installs the python sources.
author M. George Hansen <technopolitica@gmail.com>
date Tue, 31 May 2011 02:46:20 -0700
parents
children
comparison
equal deleted inserted replaced
10:5deaf494934a 11:4706e0194af3
1 """SCons.Tool.cpython
2
3 Tool-specific initialization for Python binary builder.
4
5 There normally shouldn't be any need to import this module directly.
6 It will usually be imported through the generic SCons.Tool.Tool()
7 selection method.
8
9 """
10
11 #
12 # Copyright (c) 2001-7,2010 The SCons Foundation
13 #
14 # Permission is hereby granted, free of charge, to any person obtaining
15 # a copy of this software and associated documentation files (the
16 # "Software"), to deal in the Software without restriction, including
17 # without limitation the rights to use, copy, modify, merge, publish,
18 # distribute, sublicense, and/or sell copies of the Software, and to
19 # permit persons to whom the Software is furnished to do so, subject to
20 # the following conditions:
21 #
22 # The above copyright notice and this permission notice shall be included
23 # in all copies or substantial portions of the Software.
24 #
25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #
33
34 __revision__ = "src/engine/SCons/Tool/python.py 3263 2008/07/31 13:50:51 MatiGruca"
35
36 import os
37 try:
38 import py_compile
39 except ImportError:
40 raise SCons.Errors.InternalError, "Couldn't import py_compile module"
41 try:
42 import compileall
43 except ImportError:
44 raise SCons.Errors.InternalError, "Couldn't import compileall module"
45 import glob
46
47 import SCons.Action
48 import SCons.Builder
49 import SCons.Errors
50 import SCons.Node
51 from SCons.Tool.install import installFunc, add_targets_to_INSTALLED_FILES
52 from SCons.Tool.install import copyFunc
53
54 ##########################################################################
55 # Create Python builder
56 def createPythonBuilder(env):
57 """
58 This is a utility function that creates the InstallPython
59 Builder in an Environment if it's not there already.
60
61 If it's there already, we return the existing one.
62
63 This builder is based on Install/InstallAs methods. It makes use
64 of those builder's functions: installFunc(), and
65 add_targets_to_INSTALLED_FILES()).
66 """
67
68 try:
69 InstallPythonBuilder = env['BUILDERS']['InstallPython']
70 except KeyError:
71 installpython_action = SCons.Action.Action(installFunc, '$PYTHON_PYCOMSTR')
72 InstallPythonBuilder = SCons.Builder.Builder(
73 action=installpython_action,
74 src_suffix='$PYTHON_SUFFIX',
75 target_factory=env.fs.Entry,
76 source_factory=env.fs.Entry,
77 multi=1,
78 emitter=[add_targets_to_INSTALLED_FILES],
79 name='InstallPythonBuilder'
80 )
81
82 return InstallPythonBuilder
83
84 def InstallPython(env, target=None, source=None):
85 """
86 InstallPython creates .pyc or .pyo files for .py source files
87 and adds them to the list of targets along with the source files.
88 They are later copied to the destination (target) directory.
89
90 InstallPython takes a target (destination) directory as its first
91 argument and a list of source files/directories as a second argument.
92
93 InstallPython returns the list of target files to copy to the
94 target directory.
95 """
96 try:
97 target_nodes = env.arg2nodes(target, env.fs.Dir)
98 except TypeError:
99 raise SCons.Errors.UserError, "Target `%s' of Install() is a file, but should be a directory. Perhaps you have the InstallPython() arguments backwards?" % str(dir)
100
101 source_nodes = env.arg2nodes(source, env.fs.Entry)
102 targets = []
103
104 # import `compileall` module only if there is a dir in sources list
105 dir_in_sources = any(entry.isdir() for entry in sources)
106
107 compile_py = env['PYTHON_COMPILE']
108 optimize = env['PYTHON_OPTIMIZE']
109 if optimize:
110 PYTHON_TARGETSUFFIX = 'o'
111 else:
112 PYTHON_TARGETSUFFIX = 'c'
113
114 for target_node in target_nodes:
115 for source_node in source_nodes:
116 # add *.py and *.pyc files from a directory to tgt list
117 if source_node.isdir() and compile_py:
118 compileall.compile_dir(str(source_node), maxlevels=0, quiet=True)
119 glob_path = os.path.join(source_node.path, '*.py')
120 py_and_pycs = glob.glob(glob_path) + glob.glob(glob_path + 'c')
121 for file_name in py_and_pycs:
122 target = env.Entry('.'+os.sep+filename, dnode)
123 targets.extend(apply(PythonInstallBuilder, (env, target, filename), kw))
124 # add *.py and *.pyo files from a directory to tgt list
125 elif isinstance(src, SCons.Node.FS.Dir):
126 to_compile = []
127 py_files = glob.glob(src.path + os.sep + '*.py')
128 for py_file in py_files:
129 to_compile.append(py_file)
130 target_path = '.' + os.sep + py_file
131
132 # add '.py' file to tgt list
133 py_src = env.fs.Entry(py_file)
134 py_tgt = env.fs.Entry(target_path, dnode)
135 tgt.extend(apply(PIB, (env, py_tgt, py_src), kw))
136
137 # add '.pyo' file to tgt list
138 pyo_src = env.fs.Entry(py_file + CPYTHON_TARGETSUFFIX)
139 pyo_tgt = env.fs.Entry(target_path + CPYTHON_TARGETSUFFIX, dnode)
140 tgt.extend(apply(PIB, (env, pyo_tgt, pyo_src), kw))
141 act = SCons.Action.CommandAction('@$CPYTHON_PYCOM %s' % (' '.join(to_compile)))
142 act([], [], env)
143 # add single '.py' and '.pyc' or '.pyo' file to tgt list
144 else:
145 # add '.py' file to tgt list
146 target = env.fs.Entry('.'+os.sep+src.path, dnode)
147 tgt.extend(apply(PIB, (env, target, src), kw))
148
149 # .pyc or .pyo source and target files
150 pyco_src = env.fs.Entry(src.path + CPYTHON_TARGETSUFFIX)
151 pyco_tgt = env.fs.Entry(target.path + CPYTHON_TARGETSUFFIX)
152
153 if compile_pyc:
154 py_compile.compile(src.path)
155 else:
156 act = SCons.Action.CommandAction('@$CPYTHON_PYCOM %s' % (src.path))
157 act([], [], env)
158
159 # add '.pyc' or '.pyo' file to tgt list
160 tgt.extend(apply(PIB, (env, pyco_tgt, pyco_src), kw))
161
162 return tgt
163
164 def generate(env):
165 try:
166 env['INSTALL']
167 except KeyError:
168 env['INSTALL'] = copyFunc
169
170 global InstallPythonBuilder
171 InstallPythonBuilder = createPythonBuilder(env)
172
173 env['PYTHON_OPTIMIZE'] = False # generate '.pyc' files by default
174 env['PYTHON_OPTIMIZE_FLAGS'] = '-O'
175 env['PYTHON_COMPILE_CMD'] = "-m py_compile $SOURCES"
176 env['PYTHON_PYCOM'] = '$PYTHON ${PYTHON_OPTIMIZE_FLAGS if ' \
177 'PYTHON_OPTIMIZE} $CPYTHON_COMPILE_CMD'
178 env['PYTHON_PYCOMSTR'] = 'Install file: "$SOURCE" as "$TARGET"'
179 env['PYTHON_SUFFIX'] = '.py' # extension for Python source files
180
181 try:
182 env.Append(BUILDERS={'InstallPython': InstallPythonBuilder})
183 except AttributeError:
184 # Looks like we use a pre-0.98 version of SCons...
185 from SCons.Script.SConscript import SConsEnvironment
186 SConsEnvironment.InstallPython = InstallPythonBuilder
187
188 def exists(env):
189 return 1