OLD | NEW |
(Empty) | |
| 1 """SCons.Tool.pyext |
| 2 |
| 3 Tool-specific initialization for python extensions builder. |
| 4 |
| 5 AUTHORS: |
| 6 - David Cournapeau |
| 7 - Dag Sverre Seljebotn |
| 8 |
| 9 """ |
| 10 |
| 11 # |
| 12 # __COPYRIGHT__ |
| 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" |
| 35 |
| 36 import sys |
| 37 |
| 38 import SCons |
| 39 from SCons.Tool import SourceFileScanner, ProgramScanner |
| 40 |
| 41 # Create common python builders |
| 42 |
| 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. |
| 46 |
| 47 If it is already there, we return the existing one. |
| 48 """ |
| 49 |
| 50 try: |
| 51 pyobj = env['BUILDERS']['PythonObject'] |
| 52 except KeyError: |
| 53 pyobj = SCons.Builder.Builder(action = {}, |
| 54 emitter = {}, |
| 55 prefix = '$PYEXTOBJPREFIX', |
| 56 suffix = '$PYEXTOBJSUFFIX', |
| 57 src_builder = ['CFile', 'CXXFile'], |
| 58 source_scanner = SourceFileScanner, |
| 59 single_source = 1) |
| 60 env['BUILDERS']['PythonObject'] = pyobj |
| 61 |
| 62 return pyobj |
| 63 |
| 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. |
| 67 |
| 68 If it is already there, we return the existing one. |
| 69 """ |
| 70 |
| 71 try: |
| 72 pyext = env['BUILDERS']['PythonExtension'] |
| 73 except KeyError: |
| 74 import SCons.Action |
| 75 import SCons.Defaults |
| 76 action = SCons.Action.Action("$PYEXTLINKCOM", "$PYEXTLINKCOMSTR") |
| 77 action_list = [ SCons.Defaults.SharedCheck, |
| 78 action] |
| 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 |
| 87 |
| 88 return pyext |
| 89 |
| 90 def pyext_coms(platform): |
| 91 """Return PYEXTCCCOM, PYEXTCXXCOM and PYEXTLINKCOM for the given |
| 92 platform.""" |
| 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")}' |
| 103 else: |
| 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" |
| 112 |
| 113 if platform == 'darwin': |
| 114 pyext_linkcom += ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' |
| 115 |
| 116 return pyext_cccom, pyext_cxxcom, pyext_linkcom |
| 117 |
| 118 def set_basic_vars(env): |
| 119 # Set construction variables which are independant on whether we are using |
| 120 # distutils or not. |
| 121 env['PYEXTCPPPATH'] = SCons.Util.CLVar('$PYEXTINCPATH') |
| 122 |
| 123 env['_PYEXTCPPINCFLAGS'] = '$( ${_concat(INCPREFIX, PYEXTCPPPATH, '\ |
| 124 'INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' |
| 125 env['PYEXTOBJSUFFIX'] = '$SHOBJSUFFIX' |
| 126 env['PYEXTOBJPREFIX'] = '$SHOBJPREFIX' |
| 127 |
| 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) |
| 136 |
| 137 env['PYEXTLINKFLAGSEND'] = SCons.Util.CLVar('$LINKFLAGSEND') |
| 138 |
| 139 env['PYEXTCCCOM'] = pycc |
| 140 env['PYEXTCXXCOM'] = pycxx |
| 141 env['PYEXTLINKCOM'] = pylink |
| 142 |
| 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', |
| 152 'PYEXTPREFIX' : ''} |
| 153 |
| 154 if sys.platform == 'darwin': |
| 155 def_cfg['PYEXTSUFFIX'] = '.so' |
| 156 |
| 157 for k, v in def_cfg.items(): |
| 158 ifnotset(env, k, v) |
| 159 |
| 160 ifnotset(env, 'PYEXT_ALLOW_UNDEFINED', |
| 161 SCons.Util.CLVar('$ALLOW_UNDEFINED')) |
| 162 ifnotset(env, 'PYEXTLINKFLAGS', SCons.Util.CLVar('$LDMODULEFLAGS')) |
| 163 |
| 164 env.AppendUnique(PYEXTLINKFLAGS = env['PYEXT_ALLOW_UNDEFINED']) |
| 165 |
| 166 def ifnotset(env, name, value): |
| 167 if not env.has_key(name): |
| 168 env[name] = value |
| 169 |
| 170 def set_configuration(env, use_distutils): |
| 171 """Set construction variables which are platform dependants. |
| 172 |
| 173 If use_distutils == True, use distutils configuration. Otherwise, use |
| 174 'sensible' default. |
| 175 |
| 176 Any variable already defined is untouched.""" |
| 177 |
| 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 |
| 180 # the shell. |
| 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)} |
| 188 |
| 189 from distutils import sysconfig |
| 190 |
| 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()) |
| 194 |
| 195 if use_distutils: |
| 196 for k, (v, should_split) in dist_cfg.items(): |
| 197 val = eval(v) |
| 198 if should_split: |
| 199 val = val.split() |
| 200 ifnotset(env, k, val) |
| 201 else: |
| 202 _set_configuration_nodistutils(env) |
| 203 |
| 204 def generate(env): |
| 205 """Add Builders and construction variables for python extensions to an |
| 206 Environment.""" |
| 207 |
| 208 if not env.has_key('PYEXT_USE_DISTUTILS'): |
| 209 env['PYEXT_USE_DISTUTILS'] = False |
| 210 |
| 211 # This sets all constructions variables used for pyext builders. |
| 212 set_basic_vars(env) |
| 213 |
| 214 set_configuration(env, env['PYEXT_USE_DISTUTILS']) |
| 215 |
| 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) |
| 221 |
| 222 action = SCons.Action.Action("$PYEXTCXXCOM", "$PYEXTCXXCOMSTR") |
| 223 pyobj.add_emitter('$CXXFILESUFFIX', SCons.Defaults.SharedObjectEmitter) |
| 224 pyobj.add_action('$CXXFILESUFFIX', action) |
| 225 |
| 226 # Create the PythonExtension builder |
| 227 createPythonExtensionBuilder(env) |
| 228 |
| 229 def exists(env): |
| 230 try: |
| 231 # This is not quite right: if someone defines all variables by himself, |
| 232 # it would work without distutils |
| 233 from distutils import sysconfig |
| 234 return True |
| 235 except ImportError: |
| 236 return False |
OLD | NEW |