]>
jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_ext.py
1 """distutils.command.build_ext
3 Implements the Distutils 'build_ext' command, for building extension
4 modules (currently limited to C extensions, should accommodate C++
11 from ..core
import Command
12 from ..errors
import (
18 DistutilsPlatformError
,
20 from ..sysconfig
import customize_compiler
, get_python_version
21 from ..sysconfig
import get_config_h_filename
22 from ..dep_util
import newer_group
23 from ..extension
import Extension
24 from ..util
import get_platform
25 from distutils
._log
import log
26 from . import py37compat
28 from site
import USER_BASE
30 # An extension name is just a dot-separated list of Python NAMEs (ie.
31 # the same as a fully-qualified module name).
32 extension_name_re
= re
.compile(r
'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$')
36 from ..ccompiler
import show_compilers
41 class build_ext(Command
):
42 description
= "build C/C++ extensions (compile/link to build directory)"
44 # XXX thoughts on how to deal with complex command-line options like
45 # these, i.e. how to make it so fancy_getopt can suck them off the
46 # command line and make it look like setup.py defined the appropriate
47 # lists of tuples of what-have-you.
48 # - each command needs a callback to process its command-line options
49 # - Command.__init__() needs access to its share of the whole
50 # command line (must ultimately come from
51 # Distribution.parse_command_line())
52 # - it then calls the current command class' option-parsing
53 # callback to deal with weird options like -D, which have to
54 # parse the option text and churn out some custom data
56 # - that data structure (in this case, a list of 2-tuples)
57 # will then be present in the command object by the time
58 # we get to finalize_options() (i.e. the constructor
59 # takes care of both command-line and client options
60 # in between initialize_options() and finalize_options())
62 sep_by
= " (separated by '%s')" % os
.pathsep
64 ('build-lib=', 'b', "directory for compiled extension modules"),
65 ('build-temp=', 't', "directory for temporary files (build by-products)"),
69 "platform name to cross-compile for, if supported "
70 "(default: %s)" % get_platform(),
75 "ignore build-lib and put compiled extensions into the source "
76 + "directory alongside your pure Python modules",
81 "list of directories to search for header files" + sep_by
,
83 ('define=', 'D', "C preprocessor macros to define"),
84 ('undef=', 'U', "C preprocessor macros to undefine"),
85 ('libraries=', 'l', "external C libraries to link with"),
89 "directories to search for external C libraries" + sep_by
,
91 ('rpath=', 'R', "directories to search for shared C libraries at runtime"),
92 ('link-objects=', 'O', "extra explicit link objects to include in the link"),
93 ('debug', 'g', "compile/link with debugging information"),
94 ('force', 'f', "forcibly build everything (ignore file timestamps)"),
95 ('compiler=', 'c', "specify the compiler type"),
96 ('parallel=', 'j', "number of parallel build jobs"),
97 ('swig-cpp', None, "make SWIG create C++ files (default is C)"),
98 ('swig-opts=', None, "list of SWIG command line options"),
99 ('swig=', None, "path to the SWIG executable"),
100 ('user', None, "add user include, library and rpath"),
103 boolean_options
= ['inplace', 'debug', 'force', 'swig-cpp', 'user']
106 ('help-compiler', None, "list available compilers", show_compilers
),
109 def initialize_options(self
):
110 self
.extensions
= None
111 self
.build_lib
= None
112 self
.plat_name
= None
113 self
.build_temp
= None
117 self
.include_dirs
= None
120 self
.libraries
= None
121 self
.library_dirs
= None
123 self
.link_objects
= None
129 self
.swig_opts
= None
133 def finalize_options(self
): # noqa: C901
134 from distutils
import sysconfig
136 self
.set_undefined_options(
138 ('build_lib', 'build_lib'),
139 ('build_temp', 'build_temp'),
140 ('compiler', 'compiler'),
143 ('parallel', 'parallel'),
144 ('plat_name', 'plat_name'),
147 if self
.package
is None:
148 self
.package
= self
.distribution
.ext_package
150 self
.extensions
= self
.distribution
.ext_modules
152 # Make sure Python's include directories (for Python.h, pyconfig.h,
153 # etc.) are in the include search path.
154 py_include
= sysconfig
.get_python_inc()
155 plat_py_include
= sysconfig
.get_python_inc(plat_specific
=1)
156 if self
.include_dirs
is None:
157 self
.include_dirs
= self
.distribution
.include_dirs
or []
158 if isinstance(self
.include_dirs
, str):
159 self
.include_dirs
= self
.include_dirs
.split(os
.pathsep
)
161 # If in a virtualenv, add its include directory
163 if sys
.exec_prefix
!= sys
.base_exec_prefix
:
164 self
.include_dirs
.append(os
.path
.join(sys
.exec_prefix
, 'include'))
166 # Put the Python "system" include dir at the end, so that
167 # any local include dirs take precedence.
168 self
.include_dirs
.extend(py_include
.split(os
.path
.pathsep
))
169 if plat_py_include
!= py_include
:
170 self
.include_dirs
.extend(plat_py_include
.split(os
.path
.pathsep
))
172 self
.ensure_string_list('libraries')
173 self
.ensure_string_list('link_objects')
175 # Life is easier if we're not forever checking for None, so
176 # simplify these options to empty lists if unset
177 if self
.libraries
is None:
179 if self
.library_dirs
is None:
180 self
.library_dirs
= []
181 elif isinstance(self
.library_dirs
, str):
182 self
.library_dirs
= self
.library_dirs
.split(os
.pathsep
)
184 if self
.rpath
is None:
186 elif isinstance(self
.rpath
, str):
187 self
.rpath
= self
.rpath
.split(os
.pathsep
)
189 # for extensions under windows use different directories
190 # for Release and Debug builds.
191 # also Python's library directory must be appended to library_dirs
193 # the 'libs' directory is for binary installs - we assume that
194 # must be the *native* platform. But we don't really support
195 # cross-compiling via a binary install anyway, so we let it go.
196 self
.library_dirs
.append(os
.path
.join(sys
.exec_prefix
, 'libs'))
197 if sys
.base_exec_prefix
!= sys
.prefix
: # Issue 16116
198 self
.library_dirs
.append(os
.path
.join(sys
.base_exec_prefix
, 'libs'))
200 self
.build_temp
= os
.path
.join(self
.build_temp
, "Debug")
202 self
.build_temp
= os
.path
.join(self
.build_temp
, "Release")
204 # Append the source distribution include and library directories,
205 # this allows distutils on windows to work in the source tree
206 self
.include_dirs
.append(os
.path
.dirname(get_config_h_filename()))
207 self
.library_dirs
.append(sys
.base_exec_prefix
)
209 # Use the .lib files for the correct architecture
210 if self
.plat_name
== 'win32':
214 suffix
= self
.plat_name
[4:]
215 new_lib
= os
.path
.join(sys
.exec_prefix
, 'PCbuild')
217 new_lib
= os
.path
.join(new_lib
, suffix
)
218 self
.library_dirs
.append(new_lib
)
220 # For extensions under Cygwin, Python's library directory must be
221 # appended to library_dirs
222 if sys
.platform
[:6] == 'cygwin':
223 if not sysconfig
.python_build
:
224 # building third party extensions
225 self
.library_dirs
.append(
227 sys
.prefix
, "lib", "python" + get_python_version(), "config"
231 # building python standard extensions
232 self
.library_dirs
.append('.')
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 not sysconfig
.python_build
:
239 # building third party extensions
240 self
.library_dirs
.append(sysconfig
.get_config_var('LIBDIR'))
242 # building python standard extensions
243 self
.library_dirs
.append('.')
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.
251 defines
= self
.define
.split(',')
252 self
.define
= [(symbol
, '1') for symbol
in defines
]
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.
258 self
.undef
= self
.undef
.split(',')
260 if self
.swig_opts
is None:
263 self
.swig_opts
= self
.swig_opts
.split(' ')
265 # Finally add the user include and library directories if requested
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
)
275 if isinstance(self
.parallel
, str):
277 self
.parallel
= int(self
.parallel
)
279 raise DistutilsOptionError("parallel should be an integer")
281 def run(self
): # noqa: C901
282 from ..ccompiler
import new_compiler
284 # 'self.extensions', as supplied by setup.py, is a list of
285 # Extension instances. See the documentation for Extension (in
286 # distutils.extension) for details.
288 # For backwards compatibility with Distutils 0.8.2 and earlier, we
289 # also allow the 'extensions' list to be a list of tuples:
290 # (ext_name, build_info)
291 # where build_info is a dictionary containing everything that
292 # Extension instances do except the name, with a few things being
293 # differently named. We convert these 2-tuples to Extension
294 # instances as needed.
296 if not self
.extensions
:
299 # If we were asked to build any C/C++ libraries, make sure that the
300 # directory where we put them is in the library search path for
301 # linking extensions.
302 if self
.distribution
.has_c_libraries():
303 build_clib
= self
.get_finalized_command('build_clib')
304 self
.libraries
.extend(build_clib
.get_library_names() or [])
305 self
.library_dirs
.append(build_clib
.build_clib
)
307 # Setup the CCompiler object that we'll use to do all the
308 # compiling and linking
309 self
.compiler
= new_compiler(
310 compiler
=self
.compiler
,
311 verbose
=self
.verbose
,
312 dry_run
=self
.dry_run
,
315 customize_compiler(self
.compiler
)
316 # If we are cross-compiling, init the compiler now (if we are not
317 # cross-compiling, init would not hurt, but people may rely on
318 # late initialization of compiler even if they shouldn't...)
319 if os
.name
== 'nt' and self
.plat_name
!= get_platform():
320 self
.compiler
.initialize(self
.plat_name
)
322 # And make sure that any compile/link-related options (which might
323 # come from the command-line or from the setup script) are set in
324 # that CCompiler object -- that way, they automatically apply to
325 # all compiling and linking done here.
326 if self
.include_dirs
is not None:
327 self
.compiler
.set_include_dirs(self
.include_dirs
)
328 if self
.define
is not None:
329 # 'define' option is a list of (name,value) tuples
330 for name
, value
in self
.define
:
331 self
.compiler
.define_macro(name
, value
)
332 if self
.undef
is not None:
333 for macro
in self
.undef
:
334 self
.compiler
.undefine_macro(macro
)
335 if self
.libraries
is not None:
336 self
.compiler
.set_libraries(self
.libraries
)
337 if self
.library_dirs
is not None:
338 self
.compiler
.set_library_dirs(self
.library_dirs
)
339 if self
.rpath
is not None:
340 self
.compiler
.set_runtime_library_dirs(self
.rpath
)
341 if self
.link_objects
is not None:
342 self
.compiler
.set_link_objects(self
.link_objects
)
344 # Now actually compile and link everything.
345 self
.build_extensions()
347 def check_extensions_list(self
, extensions
): # noqa: C901
348 """Ensure that the list of extensions (presumably provided as a
349 command option 'extensions') is valid, i.e. it is a list of
350 Extension objects. We also support the old-style list of 2-tuples,
351 where the tuples are (ext_name, build_info), which are converted to
352 Extension instances here.
354 Raise DistutilsSetupError if the structure is invalid anywhere;
355 just returns otherwise.
357 if not isinstance(extensions
, list):
358 raise DistutilsSetupError(
359 "'ext_modules' option must be a list of Extension instances"
362 for i
, ext
in enumerate(extensions
):
363 if isinstance(ext
, Extension
):
364 continue # OK! (assume type-checking done
365 # by Extension constructor)
367 if not isinstance(ext
, tuple) or len(ext
) != 2:
368 raise DistutilsSetupError(
369 "each element of 'ext_modules' option must be an "
370 "Extension instance or 2-tuple"
373 ext_name
, build_info
= ext
376 "old-style (ext_name, build_info) tuple found in "
377 "ext_modules for extension '%s' "
378 "-- please convert to Extension instance",
382 if not (isinstance(ext_name
, str) and extension_name_re
.match(ext_name
)):
383 raise DistutilsSetupError(
384 "first element of each tuple in 'ext_modules' "
385 "must be the extension name (a string)"
388 if not isinstance(build_info
, dict):
389 raise DistutilsSetupError(
390 "second element of each tuple in 'ext_modules' "
391 "must be a dictionary (build info)"
394 # OK, the (ext_name, build_info) dict is type-safe: convert it
395 # to an Extension instance.
396 ext
= Extension(ext_name
, build_info
['sources'])
398 # Easy stuff: one-to-one mapping from dict elements to
399 # instance attributes.
405 'extra_compile_args',
408 val
= build_info
.get(key
)
410 setattr(ext
, key
, val
)
412 # Medium-easy stuff: same syntax/semantics, different names.
413 ext
.runtime_library_dirs
= build_info
.get('rpath')
414 if 'def_file' in build_info
:
416 "'def_file' element of build info dict " "no longer supported"
419 # Non-trivial stuff: 'macros' split into 'define_macros'
420 # and 'undef_macros'.
421 macros
= build_info
.get('macros')
423 ext
.define_macros
= []
424 ext
.undef_macros
= []
426 if not (isinstance(macro
, tuple) and len(macro
) in (1, 2)):
427 raise DistutilsSetupError(
428 "'macros' element of build info dict "
429 "must be 1- or 2-tuple"
432 ext
.undef_macros
.append(macro
[0])
433 elif len(macro
) == 2:
434 ext
.define_macros
.append(macro
)
438 def get_source_files(self
):
439 self
.check_extensions_list(self
.extensions
)
442 # Wouldn't it be neat if we knew the names of header files too...
443 for ext
in self
.extensions
:
444 filenames
.extend(ext
.sources
)
447 def get_outputs(self
):
448 # Sanity check the 'extensions' list -- can't assume this is being
449 # done in the same run as a 'build_extensions()' call (in fact, we
450 # can probably assume that it *isn't*!).
451 self
.check_extensions_list(self
.extensions
)
453 # And build the list of output (built) filenames. Note that this
454 # ignores the 'inplace' flag, and assumes everything goes in the
457 for ext
in self
.extensions
:
458 outputs
.append(self
.get_ext_fullpath(ext
.name
))
461 def build_extensions(self
):
462 # First, sanity-check the 'extensions' list
463 self
.check_extensions_list(self
.extensions
)
465 self
._build
_extensions
_parallel
()
467 self
._build
_extensions
_serial
()
469 def _build_extensions_parallel(self
):
470 workers
= self
.parallel
471 if self
.parallel
is True:
472 workers
= os
.cpu_count() # may return None
474 from concurrent
.futures
import ThreadPoolExecutor
479 self
._build
_extensions
_serial
()
482 with ThreadPoolExecutor(max_workers
=workers
) as executor
:
484 executor
.submit(self
.build_extension
, ext
) for ext
in self
.extensions
486 for ext
, fut
in zip(self
.extensions
, futures
):
487 with self
._filter
_build
_errors
(ext
):
490 def _build_extensions_serial(self
):
491 for ext
in self
.extensions
:
492 with self
._filter
_build
_errors
(ext
):
493 self
.build_extension(ext
)
495 @contextlib.contextmanager
496 def _filter_build_errors(self
, ext
):
499 except (CCompilerError
, DistutilsError
, CompileError
) as e
:
502 self
.warn('building extension "{}" failed: {}'.format(ext
.name
, e
))
504 def build_extension(self
, ext
):
505 sources
= ext
.sources
506 if sources
is None or not isinstance(sources
, (list, tuple)):
507 raise DistutilsSetupError(
508 "in 'ext_modules' option (extension '%s'), "
509 "'sources' must be present and must be "
510 "a list of source filenames" % ext
.name
512 # sort to make the resulting .so file build reproducible
513 sources
= sorted(sources
)
515 ext_path
= self
.get_ext_fullpath(ext
.name
)
516 depends
= sources
+ ext
.depends
517 if not (self
.force
or newer_group(depends
, ext_path
, 'newer')):
518 log
.debug("skipping '%s' extension (up-to-date)", ext
.name
)
521 log
.info("building '%s' extension", ext
.name
)
523 # First, scan the sources for SWIG definition files (.i), run
524 # SWIG on 'em to create .c files, and modify the sources list
526 sources
= self
.swig_sources(sources
, ext
)
528 # Next, compile the source code to object files.
530 # XXX not honouring 'define_macros' or 'undef_macros' -- the
531 # CCompiler API needs to change to accommodate this, and I
532 # want to do one thing at a time!
534 # Two possible sources for extra compiler arguments:
535 # - 'extra_compile_args' in Extension object
536 # - CFLAGS environment variable (not particularly
537 # elegant, but people seem to expect it and I
539 # The environment variable should take precedence, and
540 # any sensible compiler will give precedence to later
541 # command line args. Hence we combine them in order:
542 extra_args
= ext
.extra_compile_args
or []
544 macros
= ext
.define_macros
[:]
545 for undef
in ext
.undef_macros
:
546 macros
.append((undef
,))
548 objects
= self
.compiler
.compile(
550 output_dir
=self
.build_temp
,
552 include_dirs
=ext
.include_dirs
,
554 extra_postargs
=extra_args
,
558 # XXX outdated variable, kept here in case third-part code
560 self
._built
_objects
= objects
[:]
562 # Now link the object files together into a "shared object" --
563 # of course, first we have to figure out all the other things
564 # that go into the mix.
565 if ext
.extra_objects
:
566 objects
.extend(ext
.extra_objects
)
567 extra_args
= ext
.extra_link_args
or []
569 # Detect target language, if not provided
570 language
= ext
.language
or self
.compiler
.detect_language(sources
)
572 self
.compiler
.link_shared_object(
575 libraries
=self
.get_libraries(ext
),
576 library_dirs
=ext
.library_dirs
,
577 runtime_library_dirs
=ext
.runtime_library_dirs
,
578 extra_postargs
=extra_args
,
579 export_symbols
=self
.get_export_symbols(ext
),
581 build_temp
=self
.build_temp
,
582 target_lang
=language
,
585 def swig_sources(self
, sources
, extension
):
586 """Walk the list of source files in 'sources', looking for SWIG
587 interface (.i) files. Run SWIG on all that are found, and
588 return a modified 'sources' list with SWIG source files replaced
589 by the generated C (or C++) files.
595 # XXX this drops generated C/C++ files into the source tree, which
596 # is fine for developers who want to distribute the generated
597 # source -- but there should be an option to put SWIG output in
601 log
.warning("--swig-cpp is deprecated - use --swig-opts=-c++")
605 or ('-c++' in self
.swig_opts
)
606 or ('-c++' in extension
.swig_opts
)
612 for source
in sources
:
613 (base
, ext
) = os
.path
.splitext(source
)
614 if ext
== ".i": # SWIG interface file
615 new_sources
.append(base
+ '_wrap' + target_ext
)
616 swig_sources
.append(source
)
617 swig_targets
[source
] = new_sources
[-1]
619 new_sources
.append(source
)
624 swig
= self
.swig
or self
.find_swig()
625 swig_cmd
= [swig
, "-python"]
626 swig_cmd
.extend(self
.swig_opts
)
628 swig_cmd
.append("-c++")
630 # Do not override commandline arguments
631 if not self
.swig_opts
:
632 for o
in extension
.swig_opts
:
635 for source
in swig_sources
:
636 target
= swig_targets
[source
]
637 log
.info("swigging %s to %s", source
, target
)
638 self
.spawn(swig_cmd
+ ["-o", target
, source
])
643 """Return the name of the SWIG executable. On Unix, this is
644 just "swig" -- it should be in the PATH. Tries a bit harder on
647 if os
.name
== "posix":
649 elif os
.name
== "nt":
650 # Look for SWIG in its standard installation directory on
651 # Windows (or so I presume!). If we find it there, great;
652 # if not, act like Unix and assume it's in the PATH.
653 for vers
in ("1.3", "1.2", "1.1"):
654 fn
= os
.path
.join("c:\\swig%s" % vers
, "swig.exe")
655 if os
.path
.isfile(fn
):
660 raise DistutilsPlatformError(
661 "I don't know how to find (much less run) SWIG "
662 "on platform '%s'" % os
.name
665 # -- Name generators -----------------------------------------------
666 # (extension names, filenames, whatever)
667 def get_ext_fullpath(self
, ext_name
):
668 """Returns the path of the filename for a given extension.
670 The file is located in `build_lib` or directly in the package
673 fullname
= self
.get_ext_fullname(ext_name
)
674 modpath
= fullname
.split('.')
675 filename
= self
.get_ext_filename(modpath
[-1])
678 # no further work needed
680 # build_dir/package/path/filename
681 filename
= os
.path
.join(*modpath
[:-1] + [filename
])
682 return os
.path
.join(self
.build_lib
, filename
)
684 # the inplace option requires to find the package directory
685 # using the build_py command for that
686 package
= '.'.join(modpath
[0:-1])
687 build_py
= self
.get_finalized_command('build_py')
688 package_dir
= os
.path
.abspath(build_py
.get_package_dir(package
))
691 # package_dir/filename
692 return os
.path
.join(package_dir
, filename
)
694 def get_ext_fullname(self
, ext_name
):
695 """Returns the fullname of a given extension name.
697 Adds the `package.` prefix"""
698 if self
.package
is None:
701 return self
.package
+ '.' + ext_name
703 def get_ext_filename(self
, ext_name
):
704 r
"""Convert the name of an extension (eg. "foo.bar") into the name
705 of the file from which it will be loaded (eg. "foo/bar.so", or
708 from ..sysconfig
import get_config_var
710 ext_path
= ext_name
.split('.')
711 ext_suffix
= get_config_var('EXT_SUFFIX')
712 return os
.path
.join(*ext_path
) + ext_suffix
714 def get_export_symbols(self
, ext
):
715 """Return the list of symbols that a shared extension has to
716 export. This either uses 'ext.export_symbols' or, if it's not
717 provided, "PyInit_" + module_name. Only relevant on Windows, where
718 the .pyd file (DLL) must export the module "PyInit_" function.
720 name
= ext
.name
.split('.')[-1]
722 # Unicode module name support as defined in PEP-489
723 # https://peps.python.org/pep-0489/#export-hook-name
725 except UnicodeEncodeError:
726 suffix
= 'U_' + name
.encode('punycode').replace(b
'-', b
'_').decode('ascii')
730 initfunc_name
= "PyInit" + suffix
731 if initfunc_name
not in ext
.export_symbols
:
732 ext
.export_symbols
.append(initfunc_name
)
733 return ext
.export_symbols
735 def get_libraries(self
, ext
): # noqa: C901
736 """Return the list of libraries to link against when building a
737 shared extension. On most platforms, this is just 'ext.libraries';
738 on Windows, we add the Python library (eg. python20.dll).
740 # The python library is always needed on Windows. For MSVC, this
741 # is redundant, since the library is mentioned in a pragma in
742 # pyconfig.h that MSVC groks. The other Windows compilers all seem
743 # to need it mentioned explicitly, though, so that's what we do.
744 # Append '_d' to the python import library on debug builds.
745 if sys
.platform
== "win32":
746 from .._msvccompiler
import MSVCCompiler
748 if not isinstance(self
.compiler
, MSVCCompiler
):
749 template
= "python%d%d"
751 template
= template
+ '_d'
752 pythonlib
= template
% (
753 sys
.hexversion
>> 24,
754 (sys
.hexversion
>> 16) & 0xFF,
756 # don't extend ext.libraries, it may be shared with other
757 # extensions, it is a reference to the original list
758 return ext
.libraries
+ [pythonlib
]
760 # On Android only the main executable and LD_PRELOADs are considered
761 # to be RTLD_GLOBAL, all the dependencies of the main executable
762 # remain RTLD_LOCAL and so the shared libraries must be linked with
763 # libpython when python is built with a shared python library (issue
765 # On Cygwin (and if required, other POSIX-like platforms based on
766 # Windows like MinGW) it is simply necessary that all symbols in
767 # shared libraries are resolved at link time.
768 from ..sysconfig
import get_config_var
770 link_libpython
= False
771 if get_config_var('Py_ENABLE_SHARED'):
772 # A native build on an Android device or on Cygwin
773 if hasattr(sys
, 'getandroidapilevel'):
774 link_libpython
= True
775 elif sys
.platform
== 'cygwin':
776 link_libpython
= True
777 elif '_PYTHON_HOST_PLATFORM' in os
.environ
:
778 # We are cross-compiling for one of the relevant platforms
779 if get_config_var('ANDROID_API_LEVEL') != 0:
780 link_libpython
= True
781 elif get_config_var('MACHDEP') == 'cygwin':
782 link_libpython
= True
785 ldversion
= get_config_var('LDVERSION')
786 return ext
.libraries
+ ['python' + ldversion
]
788 return ext
.libraries
+ py37compat
.pythonlib()