1 | """distutils.command.build_ext
|
---|
2 |
|
---|
3 | Implements the Distutils 'build_ext' command, for building extension
|
---|
4 | modules (currently limited to C extensions, should accommodate C++
|
---|
5 | extensions ASAP)."""
|
---|
6 |
|
---|
7 | # This module should be kept compatible with Python 2.1.
|
---|
8 |
|
---|
9 | __revision__ = "$Id$"
|
---|
10 |
|
---|
11 | import sys, os, string, re
|
---|
12 | from types import *
|
---|
13 | from site import USER_BASE, USER_SITE
|
---|
14 | from distutils.core import Command
|
---|
15 | from distutils.errors import *
|
---|
16 | from distutils.sysconfig import customize_compiler, get_python_version
|
---|
17 | from distutils.dep_util import newer_group
|
---|
18 | from distutils.extension import Extension
|
---|
19 | from distutils.util import get_platform
|
---|
20 | from distutils import log
|
---|
21 |
|
---|
22 | if os.name == 'nt':
|
---|
23 | from distutils.msvccompiler import get_build_version
|
---|
24 | MSVC_VERSION = int(get_build_version())
|
---|
25 |
|
---|
26 | # An extension name is just a dot-separated list of Python NAMEs (ie.
|
---|
27 | # the same as a fully-qualified module name).
|
---|
28 | extension_name_re = re.compile \
|
---|
29 | (r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$')
|
---|
30 |
|
---|
31 |
|
---|
32 | def show_compilers ():
|
---|
33 | from distutils.ccompiler import show_compilers
|
---|
34 | show_compilers()
|
---|
35 |
|
---|
36 |
|
---|
37 | class build_ext (Command):
|
---|
38 |
|
---|
39 | description = "build C/C++ extensions (compile/link to build directory)"
|
---|
40 |
|
---|
41 | # XXX thoughts on how to deal with complex command-line options like
|
---|
42 | # these, i.e. how to make it so fancy_getopt can suck them off the
|
---|
43 | # command line and make it look like setup.py defined the appropriate
|
---|
44 | # lists of tuples of what-have-you.
|
---|
45 | # - each command needs a callback to process its command-line options
|
---|
46 | # - Command.__init__() needs access to its share of the whole
|
---|
47 | # command line (must ultimately come from
|
---|
48 | # Distribution.parse_command_line())
|
---|
49 | # - it then calls the current command class' option-parsing
|
---|
50 | # callback to deal with weird options like -D, which have to
|
---|
51 | # parse the option text and churn out some custom data
|
---|
52 | # structure
|
---|
53 | # - that data structure (in this case, a list of 2-tuples)
|
---|
54 | # will then be present in the command object by the time
|
---|
55 | # we get to finalize_options() (i.e. the constructor
|
---|
56 | # takes care of both command-line and client options
|
---|
57 | # in between initialize_options() and finalize_options())
|
---|
58 |
|
---|
59 | sep_by = " (separated by '%s')" % os.pathsep
|
---|
60 | user_options = [
|
---|
61 | ('build-lib=', 'b',
|
---|
62 | "directory for compiled extension modules"),
|
---|
63 | ('build-temp=', 't',
|
---|
64 | "directory for temporary files (build by-products)"),
|
---|
65 | ('plat-name=', 'p',
|
---|
66 | "platform name to cross-compile for, if supported "
|
---|
67 | "(default: %s)" % get_platform()),
|
---|
68 | ('inplace', 'i',
|
---|
69 | "ignore build-lib and put compiled extensions into the source " +
|
---|
70 | "directory alongside your pure Python modules"),
|
---|
71 | ('include-dirs=', 'I',
|
---|
72 | "list of directories to search for header files" + sep_by),
|
---|
73 | ('define=', 'D',
|
---|
74 | "C preprocessor macros to define"),
|
---|
75 | ('undef=', 'U',
|
---|
76 | "C preprocessor macros to undefine"),
|
---|
77 | ('libraries=', 'l',
|
---|
78 | "external C libraries to link with"),
|
---|
79 | ('library-dirs=', 'L',
|
---|
80 | "directories to search for external C libraries" + sep_by),
|
---|
81 | ('rpath=', 'R',
|
---|
82 | "directories to search for shared C libraries at runtime"),
|
---|
83 | ('link-objects=', 'O',
|
---|
84 | "extra explicit link objects to include in the link"),
|
---|
85 | ('debug', 'g',
|
---|
86 | "compile/link with debugging information"),
|
---|
87 | ('force', 'f',
|
---|
88 | "forcibly build everything (ignore file timestamps)"),
|
---|
89 | ('compiler=', 'c',
|
---|
90 | "specify the compiler type"),
|
---|
91 | ('swig-cpp', None,
|
---|
92 | "make SWIG create C++ files (default is C)"),
|
---|
93 | ('swig-opts=', None,
|
---|
94 | "list of SWIG command line options"),
|
---|
95 | ('swig=', None,
|
---|
96 | "path to the SWIG executable"),
|
---|
97 | ('user', None,
|
---|
98 | "add user include, library and rpath"),
|
---|
99 | ]
|
---|
100 |
|
---|
101 | boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user']
|
---|
102 |
|
---|
103 | help_options = [
|
---|
104 | ('help-compiler', None,
|
---|
105 | "list available compilers", show_compilers),
|
---|
106 | ]
|
---|
107 |
|
---|
108 | def initialize_options (self):
|
---|
109 | self.extensions = None
|
---|
110 | self.build_lib = None
|
---|
111 | self.plat_name = None
|
---|
112 | self.build_temp = None
|
---|
113 | self.inplace = 0
|
---|
114 | self.package = None
|
---|
115 |
|
---|
116 | self.include_dirs = None
|
---|
117 | self.define = None
|
---|
118 | self.undef = None
|
---|
119 | self.libraries = None
|
---|
120 | self.library_dirs = None
|
---|
121 | self.rpath = None
|
---|
122 | self.link_objects = None
|
---|
123 | self.debug = None
|
---|
124 | self.force = None
|
---|
125 | self.compiler = None
|
---|
126 | self.swig = None
|
---|
127 | self.swig_cpp = None
|
---|
128 | self.swig_opts = None
|
---|
129 | self.user = None
|
---|
130 |
|
---|
131 | def finalize_options(self):
|
---|
132 | from distutils import sysconfig
|
---|
133 |
|
---|
134 | self.set_undefined_options('build',
|
---|
135 | ('build_lib', 'build_lib'),
|
---|
136 | ('build_temp', 'build_temp'),
|
---|
137 | ('compiler', 'compiler'),
|
---|
138 | ('debug', 'debug'),
|
---|
139 | ('force', 'force'),
|
---|
140 | ('plat_name', 'plat_name'),
|
---|
141 | )
|
---|
142 |
|
---|
143 | if self.package is None:
|
---|
144 | self.package = self.distribution.ext_package
|
---|
145 |
|
---|
146 | self.extensions = self.distribution.ext_modules
|
---|
147 |
|
---|
148 | # Make sure Python's include directories (for Python.h, pyconfig.h,
|
---|
149 | # etc.) are in the include search path.
|
---|
150 | py_include = sysconfig.get_python_inc()
|
---|
151 | plat_py_include = sysconfig.get_python_inc(plat_specific=1)
|
---|
152 | if self.include_dirs is None:
|
---|
153 | self.include_dirs = self.distribution.include_dirs or []
|
---|
154 | if isinstance(self.include_dirs, str):
|
---|
155 | self.include_dirs = self.include_dirs.split(os.pathsep)
|
---|
156 |
|
---|
157 | # Put the Python "system" include dir at the end, so that
|
---|
158 | # any local include dirs take precedence.
|
---|
159 | self.include_dirs.append(py_include)
|
---|
160 | if plat_py_include != py_include:
|
---|
161 | self.include_dirs.append(plat_py_include)
|
---|
162 |
|
---|
163 | self.ensure_string_list('libraries')
|
---|
164 |
|
---|
165 | # Life is easier if we're not forever checking for None, so
|
---|
166 | # simplify these options to empty lists if unset
|
---|
167 | if self.libraries is None:
|
---|
168 | self.libraries = []
|
---|
169 | if self.library_dirs is None:
|
---|
170 | self.library_dirs = []
|
---|
171 | elif type(self.library_dirs) is StringType:
|
---|
172 | self.library_dirs = string.split(self.library_dirs, os.pathsep)
|
---|
173 |
|
---|
174 | if self.rpath is None:
|
---|
175 | self.rpath = []
|
---|
176 | elif type(self.rpath) is StringType:
|
---|
177 | self.rpath = string.split(self.rpath, os.pathsep)
|
---|
178 |
|
---|
179 | # for extensions under windows use different directories
|
---|
180 | # for Release and Debug builds.
|
---|
181 | # also Python's library directory must be appended to library_dirs
|
---|
182 | if os.name == 'nt':
|
---|
183 | # the 'libs' directory is for binary installs - we assume that
|
---|
184 | # must be the *native* platform. But we don't really support
|
---|
185 | # cross-compiling via a binary install anyway, so we let it go.
|
---|
186 | self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
|
---|
187 | if self.debug:
|
---|
188 | self.build_temp = os.path.join(self.build_temp, "Debug")
|
---|
189 | else:
|
---|
190 | self.build_temp = os.path.join(self.build_temp, "Release")
|
---|
191 |
|
---|
192 | # Append the source distribution include and library directories,
|
---|
193 | # this allows distutils on windows to work in the source tree
|
---|
194 | self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
|
---|
195 | if MSVC_VERSION == 9:
|
---|
196 | # Use the .lib files for the correct architecture
|
---|
197 | if self.plat_name == 'win32':
|
---|
198 | suffix = ''
|
---|
199 | else:
|
---|
200 | # win-amd64 or win-ia64
|
---|
201 | suffix = self.plat_name[4:]
|
---|
202 | new_lib = os.path.join(sys.exec_prefix, 'PCbuild')
|
---|
203 | if suffix:
|
---|
204 | new_lib = os.path.join(new_lib, suffix)
|
---|
205 | self.library_dirs.append(new_lib)
|
---|
206 |
|
---|
207 | elif MSVC_VERSION == 8:
|
---|
208 | self.library_dirs.append(os.path.join(sys.exec_prefix,
|
---|
209 | 'PC', 'VS8.0'))
|
---|
210 | elif MSVC_VERSION == 7:
|
---|
211 | self.library_dirs.append(os.path.join(sys.exec_prefix,
|
---|
212 | 'PC', 'VS7.1'))
|
---|
213 | else:
|
---|
214 | self.library_dirs.append(os.path.join(sys.exec_prefix,
|
---|
215 | 'PC', 'VC6'))
|
---|
216 |
|
---|
217 | # OS/2 (EMX) doesn't support Debug vs Release builds, but has the
|
---|
218 | # import libraries in its "Config" subdirectory
|
---|
219 | if os.name == 'os2':
|
---|
220 | self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config'))
|
---|
221 |
|
---|
222 | # for extensions under Cygwin and AtheOS Python's library directory must be
|
---|
223 | # appended to library_dirs
|
---|
224 | if sys.platform[:6] == 'cygwin' or sys.platform[:6] == 'atheos':
|
---|
225 | if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
|
---|
226 | # building third party extensions
|
---|
227 | self.library_dirs.append(os.path.join(sys.prefix, "lib",
|
---|
228 | "python" + get_python_version(),
|
---|
229 | "config"))
|
---|
230 | else:
|
---|
231 | # building python standard extensions
|
---|
232 | self.library_dirs.append('.')
|
---|
233 |
|
---|
234 | # For building extensions with a shared Python library,
|
---|
235 | # Python's library directory must be appended to library_dirs
|
---|
236 | # See Issues: #1600860, #4366
|
---|
237 | if (sysconfig.get_config_var('Py_ENABLE_SHARED')):
|
---|
238 | if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
|
---|
239 | # building third party extensions
|
---|
240 | self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
|
---|
241 | else:
|
---|
242 | # building python standard extensions
|
---|
243 | self.library_dirs.append('.')
|
---|
244 |
|
---|
245 | # The argument parsing will result in self.define being a string, but
|
---|
246 | # it has to be a list of 2-tuples. All the preprocessor symbols
|
---|
247 | # specified by the 'define' option will be set to '1'. Multiple
|
---|
248 | # symbols can be separated with commas.
|
---|
249 |
|
---|
250 | if self.define:
|
---|
251 | defines = self.define.split(',')
|
---|
252 | self.define = map(lambda symbol: (symbol, '1'), defines)
|
---|
253 |
|
---|
254 | # The option for macros to undefine is also a string from the
|
---|
255 | # option parsing, but has to be a list. Multiple symbols can also
|
---|
256 | # be separated with commas here.
|
---|
257 | if self.undef:
|
---|
258 | self.undef = self.undef.split(',')
|
---|
259 |
|
---|
260 | if self.swig_opts is None:
|
---|
261 | self.swig_opts = []
|
---|
262 | else:
|
---|
263 | self.swig_opts = self.swig_opts.split(' ')
|
---|
264 |
|
---|
265 | # Finally add the user include and library directories if requested
|
---|
266 | if self.user:
|
---|
267 | user_include = os.path.join(USER_BASE, "include")
|
---|
268 | user_lib = os.path.join(USER_BASE, "lib")
|
---|
269 | if os.path.isdir(user_include):
|
---|
270 | self.include_dirs.append(user_include)
|
---|
271 | if os.path.isdir(user_lib):
|
---|
272 | self.library_dirs.append(user_lib)
|
---|
273 | self.rpath.append(user_lib)
|
---|
274 |
|
---|
275 | def run(self):
|
---|
276 | from distutils.ccompiler import new_compiler
|
---|
277 |
|
---|
278 | # 'self.extensions', as supplied by setup.py, is a list of
|
---|
279 | # Extension instances. See the documentation for Extension (in
|
---|
280 | # distutils.extension) for details.
|
---|
281 | #
|
---|
282 | # For backwards compatibility with Distutils 0.8.2 and earlier, we
|
---|
283 | # also allow the 'extensions' list to be a list of tuples:
|
---|
284 | # (ext_name, build_info)
|
---|
285 | # where build_info is a dictionary containing everything that
|
---|
286 | # Extension instances do except the name, with a few things being
|
---|
287 | # differently named. We convert these 2-tuples to Extension
|
---|
288 | # instances as needed.
|
---|
289 |
|
---|
290 | if not self.extensions:
|
---|
291 | return
|
---|
292 |
|
---|
293 | # If we were asked to build any C/C++ libraries, make sure that the
|
---|
294 | # directory where we put them is in the library search path for
|
---|
295 | # linking extensions.
|
---|
296 | if self.distribution.has_c_libraries():
|
---|
297 | build_clib = self.get_finalized_command('build_clib')
|
---|
298 | self.libraries.extend(build_clib.get_library_names() or [])
|
---|
299 | self.library_dirs.append(build_clib.build_clib)
|
---|
300 |
|
---|
301 | # Setup the CCompiler object that we'll use to do all the
|
---|
302 | # compiling and linking
|
---|
303 | self.compiler = new_compiler(compiler=self.compiler,
|
---|
304 | verbose=self.verbose,
|
---|
305 | dry_run=self.dry_run,
|
---|
306 | force=self.force)
|
---|
307 | customize_compiler(self.compiler)
|
---|
308 | # If we are cross-compiling, init the compiler now (if we are not
|
---|
309 | # cross-compiling, init would not hurt, but people may rely on
|
---|
310 | # late initialization of compiler even if they shouldn't...)
|
---|
311 | if os.name == 'nt' and self.plat_name != get_platform():
|
---|
312 | self.compiler.initialize(self.plat_name)
|
---|
313 |
|
---|
314 | # And make sure that any compile/link-related options (which might
|
---|
315 | # come from the command-line or from the setup script) are set in
|
---|
316 | # that CCompiler object -- that way, they automatically apply to
|
---|
317 | # all compiling and linking done here.
|
---|
318 | if self.include_dirs is not None:
|
---|
319 | self.compiler.set_include_dirs(self.include_dirs)
|
---|
320 | if self.define is not None:
|
---|
321 | # 'define' option is a list of (name,value) tuples
|
---|
322 | for (name, value) in self.define:
|
---|
323 | self.compiler.define_macro(name, value)
|
---|
324 | if self.undef is not None:
|
---|
325 | for macro in self.undef:
|
---|
326 | self.compiler.undefine_macro(macro)
|
---|
327 | if self.libraries is not None:
|
---|
328 | self.compiler.set_libraries(self.libraries)
|
---|
329 | if self.library_dirs is not None:
|
---|
330 | self.compiler.set_library_dirs(self.library_dirs)
|
---|
331 | if self.rpath is not None:
|
---|
332 | self.compiler.set_runtime_library_dirs(self.rpath)
|
---|
333 | if self.link_objects is not None:
|
---|
334 | self.compiler.set_link_objects(self.link_objects)
|
---|
335 |
|
---|
336 | # Now actually compile and link everything.
|
---|
337 | self.build_extensions()
|
---|
338 |
|
---|
339 | def check_extensions_list(self, extensions):
|
---|
340 | """Ensure that the list of extensions (presumably provided as a
|
---|
341 | command option 'extensions') is valid, i.e. it is a list of
|
---|
342 | Extension objects. We also support the old-style list of 2-tuples,
|
---|
343 | where the tuples are (ext_name, build_info), which are converted to
|
---|
344 | Extension instances here.
|
---|
345 |
|
---|
346 | Raise DistutilsSetupError if the structure is invalid anywhere;
|
---|
347 | just returns otherwise.
|
---|
348 | """
|
---|
349 | if not isinstance(extensions, list):
|
---|
350 | raise DistutilsSetupError, \
|
---|
351 | "'ext_modules' option must be a list of Extension instances"
|
---|
352 |
|
---|
353 | for i, ext in enumerate(extensions):
|
---|
354 | if isinstance(ext, Extension):
|
---|
355 | continue # OK! (assume type-checking done
|
---|
356 | # by Extension constructor)
|
---|
357 |
|
---|
358 | if not isinstance(ext, tuple) or len(ext) != 2:
|
---|
359 | raise DistutilsSetupError, \
|
---|
360 | ("each element of 'ext_modules' option must be an "
|
---|
361 | "Extension instance or 2-tuple")
|
---|
362 |
|
---|
363 | ext_name, build_info = ext
|
---|
364 |
|
---|
365 | log.warn(("old-style (ext_name, build_info) tuple found in "
|
---|
366 | "ext_modules for extension '%s'"
|
---|
367 | "-- please convert to Extension instance" % ext_name))
|
---|
368 |
|
---|
369 | if not (isinstance(ext_name, str) and
|
---|
370 | extension_name_re.match(ext_name)):
|
---|
371 | raise DistutilsSetupError, \
|
---|
372 | ("first element of each tuple in 'ext_modules' "
|
---|
373 | "must be the extension name (a string)")
|
---|
374 |
|
---|
375 | if not isinstance(build_info, dict):
|
---|
376 | raise DistutilsSetupError, \
|
---|
377 | ("second element of each tuple in 'ext_modules' "
|
---|
378 | "must be a dictionary (build info)")
|
---|
379 |
|
---|
380 | # OK, the (ext_name, build_info) dict is type-safe: convert it
|
---|
381 | # to an Extension instance.
|
---|
382 | ext = Extension(ext_name, build_info['sources'])
|
---|
383 |
|
---|
384 | # Easy stuff: one-to-one mapping from dict elements to
|
---|
385 | # instance attributes.
|
---|
386 | for key in ('include_dirs', 'library_dirs', 'libraries',
|
---|
387 | 'extra_objects', 'extra_compile_args',
|
---|
388 | 'extra_link_args'):
|
---|
389 | val = build_info.get(key)
|
---|
390 | if val is not None:
|
---|
391 | setattr(ext, key, val)
|
---|
392 |
|
---|
393 | # Medium-easy stuff: same syntax/semantics, different names.
|
---|
394 | ext.runtime_library_dirs = build_info.get('rpath')
|
---|
395 | if 'def_file' in build_info:
|
---|
396 | log.warn("'def_file' element of build info dict "
|
---|
397 | "no longer supported")
|
---|
398 |
|
---|
399 | # Non-trivial stuff: 'macros' split into 'define_macros'
|
---|
400 | # and 'undef_macros'.
|
---|
401 | macros = build_info.get('macros')
|
---|
402 | if macros:
|
---|
403 | ext.define_macros = []
|
---|
404 | ext.undef_macros = []
|
---|
405 | for macro in macros:
|
---|
406 | if not (isinstance(macro, tuple) and len(macro) in (1, 2)):
|
---|
407 | raise DistutilsSetupError, \
|
---|
408 | ("'macros' element of build info dict "
|
---|
409 | "must be 1- or 2-tuple")
|
---|
410 | if len(macro) == 1:
|
---|
411 | ext.undef_macros.append(macro[0])
|
---|
412 | elif len(macro) == 2:
|
---|
413 | ext.define_macros.append(macro)
|
---|
414 |
|
---|
415 | extensions[i] = ext
|
---|
416 |
|
---|
417 | def get_source_files(self):
|
---|
418 | self.check_extensions_list(self.extensions)
|
---|
419 | filenames = []
|
---|
420 |
|
---|
421 | # Wouldn't it be neat if we knew the names of header files too...
|
---|
422 | for ext in self.extensions:
|
---|
423 | filenames.extend(ext.sources)
|
---|
424 |
|
---|
425 | return filenames
|
---|
426 |
|
---|
427 | def get_outputs(self):
|
---|
428 | # Sanity check the 'extensions' list -- can't assume this is being
|
---|
429 | # done in the same run as a 'build_extensions()' call (in fact, we
|
---|
430 | # can probably assume that it *isn't*!).
|
---|
431 | self.check_extensions_list(self.extensions)
|
---|
432 |
|
---|
433 | # And build the list of output (built) filenames. Note that this
|
---|
434 | # ignores the 'inplace' flag, and assumes everything goes in the
|
---|
435 | # "build" tree.
|
---|
436 | outputs = []
|
---|
437 | for ext in self.extensions:
|
---|
438 | outputs.append(self.get_ext_fullpath(ext.name))
|
---|
439 | return outputs
|
---|
440 |
|
---|
441 | def build_extensions(self):
|
---|
442 | # First, sanity-check the 'extensions' list
|
---|
443 | self.check_extensions_list(self.extensions)
|
---|
444 |
|
---|
445 | for ext in self.extensions:
|
---|
446 | self.build_extension(ext)
|
---|
447 |
|
---|
448 | def build_extension(self, ext):
|
---|
449 | sources = ext.sources
|
---|
450 | if sources is None or type(sources) not in (ListType, TupleType):
|
---|
451 | raise DistutilsSetupError, \
|
---|
452 | ("in 'ext_modules' option (extension '%s'), " +
|
---|
453 | "'sources' must be present and must be " +
|
---|
454 | "a list of source filenames") % ext.name
|
---|
455 | sources = list(sources)
|
---|
456 |
|
---|
457 | ext_path = self.get_ext_fullpath(ext.name)
|
---|
458 | depends = sources + ext.depends
|
---|
459 | if not (self.force or newer_group(depends, ext_path, 'newer')):
|
---|
460 | log.debug("skipping '%s' extension (up-to-date)", ext.name)
|
---|
461 | return
|
---|
462 | else:
|
---|
463 | log.info("building '%s' extension", ext.name)
|
---|
464 |
|
---|
465 | # First, scan the sources for SWIG definition files (.i), run
|
---|
466 | # SWIG on 'em to create .c files, and modify the sources list
|
---|
467 | # accordingly.
|
---|
468 | sources = self.swig_sources(sources, ext)
|
---|
469 |
|
---|
470 | # Next, compile the source code to object files.
|
---|
471 |
|
---|
472 | # XXX not honouring 'define_macros' or 'undef_macros' -- the
|
---|
473 | # CCompiler API needs to change to accommodate this, and I
|
---|
474 | # want to do one thing at a time!
|
---|
475 |
|
---|
476 | # Two possible sources for extra compiler arguments:
|
---|
477 | # - 'extra_compile_args' in Extension object
|
---|
478 | # - CFLAGS environment variable (not particularly
|
---|
479 | # elegant, but people seem to expect it and I
|
---|
480 | # guess it's useful)
|
---|
481 | # The environment variable should take precedence, and
|
---|
482 | # any sensible compiler will give precedence to later
|
---|
483 | # command line args. Hence we combine them in order:
|
---|
484 | extra_args = ext.extra_compile_args or []
|
---|
485 |
|
---|
486 | macros = ext.define_macros[:]
|
---|
487 | for undef in ext.undef_macros:
|
---|
488 | macros.append((undef,))
|
---|
489 |
|
---|
490 | objects = self.compiler.compile(sources,
|
---|
491 | output_dir=self.build_temp,
|
---|
492 | macros=macros,
|
---|
493 | include_dirs=ext.include_dirs,
|
---|
494 | debug=self.debug,
|
---|
495 | extra_postargs=extra_args,
|
---|
496 | depends=ext.depends)
|
---|
497 |
|
---|
498 | # XXX -- this is a Vile HACK!
|
---|
499 | #
|
---|
500 | # The setup.py script for Python on Unix needs to be able to
|
---|
501 | # get this list so it can perform all the clean up needed to
|
---|
502 | # avoid keeping object files around when cleaning out a failed
|
---|
503 | # build of an extension module. Since Distutils does not
|
---|
504 | # track dependencies, we have to get rid of intermediates to
|
---|
505 | # ensure all the intermediates will be properly re-built.
|
---|
506 | #
|
---|
507 | self._built_objects = objects[:]
|
---|
508 |
|
---|
509 | # Now link the object files together into a "shared object" --
|
---|
510 | # of course, first we have to figure out all the other things
|
---|
511 | # that go into the mix.
|
---|
512 | if ext.extra_objects:
|
---|
513 | objects.extend(ext.extra_objects)
|
---|
514 | extra_args = ext.extra_link_args or []
|
---|
515 |
|
---|
516 | # Detect target language, if not provided
|
---|
517 | language = ext.language or self.compiler.detect_language(sources)
|
---|
518 |
|
---|
519 | self.compiler.link_shared_object(
|
---|
520 | objects, ext_path,
|
---|
521 | libraries=self.get_libraries(ext),
|
---|
522 | library_dirs=ext.library_dirs,
|
---|
523 | runtime_library_dirs=ext.runtime_library_dirs,
|
---|
524 | extra_postargs=extra_args,
|
---|
525 | export_symbols=self.get_export_symbols(ext),
|
---|
526 | debug=self.debug,
|
---|
527 | build_temp=self.build_temp,
|
---|
528 | target_lang=language)
|
---|
529 |
|
---|
530 |
|
---|
531 | def swig_sources (self, sources, extension):
|
---|
532 |
|
---|
533 | """Walk the list of source files in 'sources', looking for SWIG
|
---|
534 | interface (.i) files. Run SWIG on all that are found, and
|
---|
535 | return a modified 'sources' list with SWIG source files replaced
|
---|
536 | by the generated C (or C++) files.
|
---|
537 | """
|
---|
538 |
|
---|
539 | new_sources = []
|
---|
540 | swig_sources = []
|
---|
541 | swig_targets = {}
|
---|
542 |
|
---|
543 | # XXX this drops generated C/C++ files into the source tree, which
|
---|
544 | # is fine for developers who want to distribute the generated
|
---|
545 | # source -- but there should be an option to put SWIG output in
|
---|
546 | # the temp dir.
|
---|
547 |
|
---|
548 | if self.swig_cpp:
|
---|
549 | log.warn("--swig-cpp is deprecated - use --swig-opts=-c++")
|
---|
550 |
|
---|
551 | if self.swig_cpp or ('-c++' in self.swig_opts) or \
|
---|
552 | ('-c++' in extension.swig_opts):
|
---|
553 | target_ext = '.cpp'
|
---|
554 | else:
|
---|
555 | target_ext = '.c'
|
---|
556 |
|
---|
557 | for source in sources:
|
---|
558 | (base, ext) = os.path.splitext(source)
|
---|
559 | if ext == ".i": # SWIG interface file
|
---|
560 | new_sources.append(base + '_wrap' + target_ext)
|
---|
561 | swig_sources.append(source)
|
---|
562 | swig_targets[source] = new_sources[-1]
|
---|
563 | else:
|
---|
564 | new_sources.append(source)
|
---|
565 |
|
---|
566 | if not swig_sources:
|
---|
567 | return new_sources
|
---|
568 |
|
---|
569 | swig = self.swig or self.find_swig()
|
---|
570 | swig_cmd = [swig, "-python"]
|
---|
571 | swig_cmd.extend(self.swig_opts)
|
---|
572 | if self.swig_cpp:
|
---|
573 | swig_cmd.append("-c++")
|
---|
574 |
|
---|
575 | # Do not override commandline arguments
|
---|
576 | if not self.swig_opts:
|
---|
577 | for o in extension.swig_opts:
|
---|
578 | swig_cmd.append(o)
|
---|
579 |
|
---|
580 | for source in swig_sources:
|
---|
581 | target = swig_targets[source]
|
---|
582 | log.info("swigging %s to %s", source, target)
|
---|
583 | self.spawn(swig_cmd + ["-o", target, source])
|
---|
584 |
|
---|
585 | return new_sources
|
---|
586 |
|
---|
587 | # swig_sources ()
|
---|
588 |
|
---|
589 | def find_swig (self):
|
---|
590 | """Return the name of the SWIG executable. On Unix, this is
|
---|
591 | just "swig" -- it should be in the PATH. Tries a bit harder on
|
---|
592 | Windows.
|
---|
593 | """
|
---|
594 |
|
---|
595 | if os.name == "posix":
|
---|
596 | return "swig"
|
---|
597 | elif os.name == "nt":
|
---|
598 |
|
---|
599 | # Look for SWIG in its standard installation directory on
|
---|
600 | # Windows (or so I presume!). If we find it there, great;
|
---|
601 | # if not, act like Unix and assume it's in the PATH.
|
---|
602 | for vers in ("1.3", "1.2", "1.1"):
|
---|
603 | fn = os.path.join("c:\\swig%s" % vers, "swig.exe")
|
---|
604 | if os.path.isfile(fn):
|
---|
605 | return fn
|
---|
606 | else:
|
---|
607 | return "swig.exe"
|
---|
608 |
|
---|
609 | elif os.name == "os2":
|
---|
610 | # assume swig available in the PATH.
|
---|
611 | return "swig.exe"
|
---|
612 |
|
---|
613 | else:
|
---|
614 | raise DistutilsPlatformError, \
|
---|
615 | ("I don't know how to find (much less run) SWIG "
|
---|
616 | "on platform '%s'") % os.name
|
---|
617 |
|
---|
618 | # find_swig ()
|
---|
619 |
|
---|
620 | # -- Name generators -----------------------------------------------
|
---|
621 | # (extension names, filenames, whatever)
|
---|
622 | def get_ext_fullpath(self, ext_name):
|
---|
623 | """Returns the path of the filename for a given extension.
|
---|
624 |
|
---|
625 | The file is located in `build_lib` or directly in the package
|
---|
626 | (inplace option).
|
---|
627 | """
|
---|
628 | # makes sure the extension name is only using dots
|
---|
629 | all_dots = string.maketrans('/'+os.sep, '..')
|
---|
630 | ext_name = ext_name.translate(all_dots)
|
---|
631 |
|
---|
632 | fullname = self.get_ext_fullname(ext_name)
|
---|
633 | modpath = fullname.split('.')
|
---|
634 | filename = self.get_ext_filename(ext_name)
|
---|
635 | filename = os.path.split(filename)[-1]
|
---|
636 |
|
---|
637 | if not self.inplace:
|
---|
638 | # no further work needed
|
---|
639 | # returning :
|
---|
640 | # build_dir/package/path/filename
|
---|
641 | filename = os.path.join(*modpath[:-1]+[filename])
|
---|
642 | return os.path.join(self.build_lib, filename)
|
---|
643 |
|
---|
644 | # the inplace option requires to find the package directory
|
---|
645 | # using the build_py command for that
|
---|
646 | package = '.'.join(modpath[0:-1])
|
---|
647 | build_py = self.get_finalized_command('build_py')
|
---|
648 | package_dir = os.path.abspath(build_py.get_package_dir(package))
|
---|
649 |
|
---|
650 | # returning
|
---|
651 | # package_dir/filename
|
---|
652 | return os.path.join(package_dir, filename)
|
---|
653 |
|
---|
654 | def get_ext_fullname(self, ext_name):
|
---|
655 | """Returns the fullname of a given extension name.
|
---|
656 |
|
---|
657 | Adds the `package.` prefix"""
|
---|
658 | if self.package is None:
|
---|
659 | return ext_name
|
---|
660 | else:
|
---|
661 | return self.package + '.' + ext_name
|
---|
662 |
|
---|
663 | def get_ext_filename(self, ext_name):
|
---|
664 | r"""Convert the name of an extension (eg. "foo.bar") into the name
|
---|
665 | of the file from which it will be loaded (eg. "foo/bar.so", or
|
---|
666 | "foo\bar.pyd").
|
---|
667 | """
|
---|
668 | from distutils.sysconfig import get_config_var
|
---|
669 | ext_path = string.split(ext_name, '.')
|
---|
670 | # OS/2 has an 8 character module (extension) limit :-(
|
---|
671 | # YD build 8.3 moved to emxcompiler.py
|
---|
672 | #if os.name == "os2":
|
---|
673 | # ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8]
|
---|
674 | # extensions in debug_mode are named 'module_d.pyd' under windows
|
---|
675 | so_ext = get_config_var('SO')
|
---|
676 | if os.name == 'nt' and self.debug:
|
---|
677 | return os.path.join(*ext_path) + '_d' + so_ext
|
---|
678 | return os.path.join(*ext_path) + so_ext
|
---|
679 |
|
---|
680 | def get_export_symbols (self, ext):
|
---|
681 | """Return the list of symbols that a shared extension has to
|
---|
682 | export. This either uses 'ext.export_symbols' or, if it's not
|
---|
683 | provided, "init" + module_name. Only relevant on Windows, where
|
---|
684 | the .pyd file (DLL) must export the module "init" function.
|
---|
685 | """
|
---|
686 | initfunc_name = "init" + ext.name.split('.')[-1]
|
---|
687 | if initfunc_name not in ext.export_symbols:
|
---|
688 | ext.export_symbols.append(initfunc_name)
|
---|
689 | return ext.export_symbols
|
---|
690 |
|
---|
691 | def get_libraries (self, ext):
|
---|
692 | """Return the list of libraries to link against when building a
|
---|
693 | shared extension. On most platforms, this is just 'ext.libraries';
|
---|
694 | on Windows and OS/2, we add the Python library (eg. python20.dll).
|
---|
695 | """
|
---|
696 | # The python library is always needed on Windows. For MSVC, this
|
---|
697 | # is redundant, since the library is mentioned in a pragma in
|
---|
698 | # pyconfig.h that MSVC groks. The other Windows compilers all seem
|
---|
699 | # to need it mentioned explicitly, though, so that's what we do.
|
---|
700 | # Append '_d' to the python import library on debug builds.
|
---|
701 | if sys.platform == "win32":
|
---|
702 | from distutils.msvccompiler import MSVCCompiler
|
---|
703 | if not isinstance(self.compiler, MSVCCompiler):
|
---|
704 | template = "python%d%d"
|
---|
705 | if self.debug:
|
---|
706 | template = template + '_d'
|
---|
707 | pythonlib = (template %
|
---|
708 | (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
|
---|
709 | # don't extend ext.libraries, it may be shared with other
|
---|
710 | # extensions, it is a reference to the original list
|
---|
711 | return ext.libraries + [pythonlib]
|
---|
712 | else:
|
---|
713 | return ext.libraries
|
---|
714 | elif sys.platform == "os2emx":
|
---|
715 | # EMX/GCC requires the python library explicitly, and I
|
---|
716 | # believe VACPP does as well (though not confirmed) - AIM Apr01
|
---|
717 | template = "python%d%d"
|
---|
718 | # debug versions of the main DLL aren't supported, at least
|
---|
719 | # not at this time - AIM Apr01
|
---|
720 | #if self.debug:
|
---|
721 | # template = template + '_d'
|
---|
722 | pythonlib = (template %
|
---|
723 | (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
|
---|
724 | # don't extend ext.libraries, it may be shared with other
|
---|
725 | # extensions, it is a reference to the original list
|
---|
726 | return ext.libraries + [pythonlib]
|
---|
727 | elif sys.platform[:6] == "cygwin":
|
---|
728 | template = "python%d.%d"
|
---|
729 | pythonlib = (template %
|
---|
730 | (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
|
---|
731 | # don't extend ext.libraries, it may be shared with other
|
---|
732 | # extensions, it is a reference to the original list
|
---|
733 | return ext.libraries + [pythonlib]
|
---|
734 | elif sys.platform[:6] == "atheos":
|
---|
735 | from distutils import sysconfig
|
---|
736 |
|
---|
737 | template = "python%d.%d"
|
---|
738 | pythonlib = (template %
|
---|
739 | (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
|
---|
740 | # Get SHLIBS from Makefile
|
---|
741 | extra = []
|
---|
742 | for lib in sysconfig.get_config_var('SHLIBS').split():
|
---|
743 | if lib.startswith('-l'):
|
---|
744 | extra.append(lib[2:])
|
---|
745 | else:
|
---|
746 | extra.append(lib)
|
---|
747 | # don't extend ext.libraries, it may be shared with other
|
---|
748 | # extensions, it is a reference to the original list
|
---|
749 | return ext.libraries + [pythonlib, "m"] + extra
|
---|
750 |
|
---|
751 | elif sys.platform == 'darwin':
|
---|
752 | # Don't use the default code below
|
---|
753 | return ext.libraries
|
---|
754 | elif sys.platform[:3] == 'aix':
|
---|
755 | # Don't use the default code below
|
---|
756 | return ext.libraries
|
---|
757 | else:
|
---|
758 | from distutils import sysconfig
|
---|
759 | if sysconfig.get_config_var('Py_ENABLE_SHARED'):
|
---|
760 | template = "python%d.%d"
|
---|
761 | pythonlib = (template %
|
---|
762 | (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
|
---|
763 | return ext.libraries + [pythonlib]
|
---|
764 | else:
|
---|
765 | return ext.libraries
|
---|
766 |
|
---|
767 | # class build_ext
|
---|