3 Tool-specific initialization for python extensions builder.
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:
22 # The above copyright notice and this permission notice shall be included
23 # in all copies or substantial portions of the Software.
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.
34 __revision__
= "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
39 from SCons
.Tool
import SourceFileScanner
, ProgramScanner
41 # Create common python builders
43 def createPythonObjectBuilder(env
):
44 """This is a utility function that creates the PythonObject Builder in an
45 Environment if it is not there already.
47 If it is already there, we return the existing one.
51 pyobj
= env
['BUILDERS']['PythonObject']
53 pyobj
= SCons
.Builder
.Builder(action
= {},
55 prefix
= '$PYEXTOBJPREFIX',
56 suffix
= '$PYEXTOBJSUFFIX',
57 src_builder
= ['CFile', 'CXXFile'],
58 source_scanner
= SourceFileScanner
,
60 env
['BUILDERS']['PythonObject'] = pyobj
64 def createPythonExtensionBuilder(env
):
65 """This is a utility function that creates the PythonExtension Builder in
66 an Environment if it is not there already.
68 If it is already there, we return the existing one.
72 pyext
= env
['BUILDERS']['PythonExtension']
76 action
= SCons
.Action
.Action("$PYEXTLINKCOM", "$PYEXTLINKCOMSTR")
77 action_list
= [ SCons
.Defaults
.SharedCheck
,
79 pyext
= SCons
.Builder
.Builder(action
= action_list
,
80 emitter
= "$SHLIBEMITTER",
81 prefix
= '$PYEXTPREFIX',
82 suffix
= '$PYEXTSUFFIX',
83 target_scanner
= ProgramScanner
,
84 src_suffix
= '$PYEXTOBJSUFFIX',
85 src_builder
= 'PythonObject')
86 env
['BUILDERS']['PythonExtension'] = pyext
90 def pyext_coms(platform
):
91 """Return PYEXTCCCOM, PYEXTCXXCOM and PYEXTLINKCOM for the given
93 if platform
== 'win32':
94 pyext_cccom
= "$PYEXTCC /Fo$TARGET /c $PYEXTCCSHARED "\
95 "$PYEXTCFLAGS $PYEXTCCFLAGS $_CCCOMCOM "\
96 "$_PYEXTCPPINCFLAGS $SOURCES"
97 pyext_cxxcom
= "$PYEXTCXX /Fo$TARGET /c $PYEXTCSHARED "\
98 "$PYEXTCXXFLAGS $PYEXTCCFLAGS $_CCCOMCOM "\
99 "$_PYEXTCPPINCFLAGS $SOURCES"
100 pyext_linkcom
= '${TEMPFILE("$PYEXTLINK $PYEXTLINKFLAGS '\
101 '/OUT:$TARGET.windows $( $_LIBDIRFLAGS $) '\
102 '$_LIBFLAGS $_PYEXTRUNTIME $SOURCES.windows")}'
104 pyext_cccom
= "$PYEXTCC -o $TARGET -c $PYEXTCCSHARED "\
105 "$PYEXTCFLAGS $PYEXTCCFLAGS $_CCCOMCOM "\
106 "$_PYEXTCPPINCFLAGS $SOURCES"
107 pyext_cxxcom
= "$PYEXTCXX -o $TARGET -c $PYEXTCSHARED "\
108 "$PYEXTCXXFLAGS $PYEXTCCFLAGS $_CCCOMCOM "\
109 "$_PYEXTCPPINCFLAGS $SOURCES"
110 pyext_linkcom
= "$PYEXTLINK -o $TARGET $PYEXTLINKFLAGS "\
111 "$SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_PYEXTRUNTIME"
113 if platform
== 'darwin':
114 pyext_linkcom
+= ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
116 return pyext_cccom
, pyext_cxxcom
, pyext_linkcom
118 def set_basic_vars(env
):
119 # Set construction variables which are independant on whether we are using
121 env
['PYEXTCPPPATH'] = SCons
.Util
.CLVar('$PYEXTINCPATH')
123 env
['_PYEXTCPPINCFLAGS'] = '$( ${_concat(INCPREFIX, PYEXTCPPPATH, '\
124 'INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
125 env
['PYEXTOBJSUFFIX'] = '$SHOBJSUFFIX'
126 env
['PYEXTOBJPREFIX'] = '$SHOBJPREFIX'
128 env
['PYEXTRUNTIME'] = SCons
.Util
.CLVar("")
129 # XXX: this should be handled with different flags
130 env
['_PYEXTRUNTIME'] = '$( ${_concat(LIBLINKPREFIX, PYEXTRUNTIME, '\
131 'LIBLINKSUFFIX, __env__)} $)'
132 # XXX: This won't work in all cases (using mingw, for example). To make
133 # this work, we need to know whether PYEXTCC accepts /c and /Fo or -c -o.
134 # This is difficult with the current way tools work in scons.
135 pycc
, pycxx
, pylink
= pyext_coms(sys
.platform
)
137 env
['PYEXTLINKFLAGSEND'] = SCons
.Util
.CLVar('$LINKFLAGSEND')
139 env
['PYEXTCCCOM'] = pycc
140 env
['PYEXTCXXCOM'] = pycxx
141 env
['PYEXTLINKCOM'] = pylink
143 def _set_configuration_nodistutils(env
):
144 # Set env variables to sensible values when not using distutils
145 def_cfg
= {'PYEXTCC' : '$SHCC',
146 'PYEXTCFLAGS' : '$SHCFLAGS',
147 'PYEXTCCFLAGS' : '$SHCCFLAGS',
148 'PYEXTCXX' : '$SHCXX',
149 'PYEXTCXXFLAGS' : '$SHCXXFLAGS',
150 'PYEXTLINK' : '$LDMODULE',
151 'PYEXTSUFFIX' : '$LDMODULESUFFIX',
154 if sys
.platform
== 'darwin':
155 def_cfg
['PYEXTSUFFIX'] = '.so'
157 for k
, v
in def_cfg
.items():
160 ifnotset(env
, 'PYEXT_ALLOW_UNDEFINED',
161 SCons
.Util
.CLVar('$ALLOW_UNDEFINED'))
162 ifnotset(env
, 'PYEXTLINKFLAGS', SCons
.Util
.CLVar('$LDMODULEFLAGS'))
164 env
.AppendUnique(PYEXTLINKFLAGS
= env
['PYEXT_ALLOW_UNDEFINED'])
166 def ifnotset(env
, name
, value
):
167 if not env
.has_key(name
):
170 def set_configuration(env
, use_distutils
):
171 """Set construction variables which are platform dependants.
173 If use_distutils == True, use distutils configuration. Otherwise, use
176 Any variable already defined is untouched."""
178 # We define commands as strings so that we can either execute them using
179 # eval (same python for scons and distutils) or by executing them through
181 dist_cfg
= {'PYEXTCC': ("sysconfig.get_config_var('CC')", False),
182 'PYEXTCFLAGS': ("sysconfig.get_config_var('CFLAGS')", True),
183 'PYEXTCCSHARED': ("sysconfig.get_config_var('CCSHARED')", False),
184 'PYEXTLINKFLAGS': ("sysconfig.get_config_var('LDFLAGS')", True),
185 'PYEXTLINK': ("sysconfig.get_config_var('LDSHARED')", False),
186 'PYEXTINCPATH': ("sysconfig.get_python_inc()", False),
187 'PYEXTSUFFIX': ("sysconfig.get_config_var('SO')", False)}
189 from distutils
import sysconfig
191 # We set the python path even when not using distutils, because we rarely
192 # want to change this, even if not using distutils
193 ifnotset(env
, 'PYEXTINCPATH', sysconfig
.get_python_inc())
196 for k
, (v
, should_split
) in dist_cfg
.items():
200 ifnotset(env
, k
, val
)
202 _set_configuration_nodistutils(env
)
205 """Add Builders and construction variables for python extensions to an
208 if not env
.has_key('PYEXT_USE_DISTUTILS'):
209 env
['PYEXT_USE_DISTUTILS'] = False
211 # This sets all constructions variables used for pyext builders.
214 set_configuration(env
, env
['PYEXT_USE_DISTUTILS'])
216 # Create the PythonObject builder
217 pyobj
= createPythonObjectBuilder(env
)
218 action
= SCons
.Action
.Action("$PYEXTCCCOM", "$PYEXTCCCOMSTR")
219 pyobj
.add_emitter('.c', SCons
.Defaults
.SharedObjectEmitter
)
220 pyobj
.add_action('.c', action
)
222 action
= SCons
.Action
.Action("$PYEXTCXXCOM", "$PYEXTCXXCOMSTR")
223 pyobj
.add_emitter('$CXXFILESUFFIX', SCons
.Defaults
.SharedObjectEmitter
)
224 pyobj
.add_action('$CXXFILESUFFIX', action
)
226 # Create the PythonExtension builder
227 createPythonExtensionBuilder(env
)
231 # This is not quite right: if someone defines all variables by himself,
232 # it would work without distutils
233 from distutils
import sysconfig