]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/setuptools/command/build_ext.py
4 from importlib
.machinery
import EXTENSION_SUFFIXES
5 from importlib
.util
import cache_from_source
as _compiled_file_name
6 from typing
import Dict
, Iterator
, List
, Tuple
8 from distutils
.command
.build_ext
import build_ext
as _du_build_ext
9 from distutils
.ccompiler
import new_compiler
10 from distutils
.sysconfig
import customize_compiler
, get_config_var
11 from distutils
import log
13 from setuptools
.errors
import BaseError
14 from setuptools
.extension
import Extension
, Library
17 # Attempt to use Cython for building extensions, if available
18 from Cython
.Distutils
.build_ext
import build_ext
as _build_ext
19 # Additionally, assert that the compiler module will load
21 __import__('Cython.Compiler.Main')
23 _build_ext
= _du_build_ext
25 # make sure _config_vars is initialized
26 get_config_var("LDSHARED")
27 from distutils
.sysconfig
import _config_vars
as _CONFIG_VARS
# noqa
30 def _customize_compiler_for_shlib(compiler
):
31 if sys
.platform
== "darwin":
32 # building .dylib requires additional compiler flags on OSX; here we
33 # temporarily substitute the pyconfig.h variables so that distutils'
34 # 'customize_compiler' uses them before we build the shared libraries.
35 tmp
= _CONFIG_VARS
.copy()
37 # XXX Help! I don't have any idea whether these are right...
38 _CONFIG_VARS
['LDSHARED'] = (
39 "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup")
40 _CONFIG_VARS
['CCSHARED'] = " -dynamiclib"
41 _CONFIG_VARS
['SO'] = ".dylib"
42 customize_compiler(compiler
)
45 _CONFIG_VARS
.update(tmp
)
47 customize_compiler(compiler
)
54 if sys
.platform
== "darwin":
59 use_stubs
= have_rtld
= hasattr(dl
, 'RTLD_NOW')
65 return s
if have_rtld
else ''
68 def get_abi3_suffix():
69 """Return the file extension for an abi3-compliant Extension()"""
70 for suffix
in EXTENSION_SUFFIXES
:
71 if '.abi3' in suffix
: # Unix
73 elif suffix
== '.pyd': # Windows
77 class build_ext(_build_ext
):
78 editable_mode
: bool = False
82 """Build extensions in build directory, then copy if --inplace"""
83 old_inplace
, self
.inplace
= self
.inplace
, 0
85 self
.inplace
= old_inplace
87 self
.copy_extensions_to_source()
89 def _get_inplace_equivalent(self
, build_py
, ext
: Extension
) -> Tuple
[str, str]:
90 fullname
= self
.get_ext_fullname(ext
.name
)
91 filename
= self
.get_ext_filename(fullname
)
92 modpath
= fullname
.split('.')
93 package
= '.'.join(modpath
[:-1])
94 package_dir
= build_py
.get_package_dir(package
)
95 inplace_file
= os
.path
.join(package_dir
, os
.path
.basename(filename
))
96 regular_file
= os
.path
.join(self
.build_lib
, filename
)
97 return (inplace_file
, regular_file
)
99 def copy_extensions_to_source(self
):
100 build_py
= self
.get_finalized_command('build_py')
101 for ext
in self
.extensions
:
102 inplace_file
, regular_file
= self
._get
_inplace
_equivalent
(build_py
, ext
)
104 # Always copy, even if source is older than destination, to ensure
105 # that the right extensions for the current Python/platform are
107 if os
.path
.exists(regular_file
) or not ext
.optional
:
108 self
.copy_file(regular_file
, inplace_file
, level
=self
.verbose
)
111 inplace_stub
= self
._get
_equivalent
_stub
(ext
, inplace_file
)
112 self
._write
_stub
_file
(inplace_stub
, ext
, compile=True)
113 # Always compile stub and remove the original (leave the cache behind)
114 # (this behaviour was observed in previous iterations of the code)
116 def _get_equivalent_stub(self
, ext
: Extension
, output_file
: str) -> str:
117 dir_
= os
.path
.dirname(output_file
)
118 _
, _
, name
= ext
.name
.rpartition(".")
119 return f
"{os.path.join(dir_, name)}.py"
121 def _get_output_mapping(self
) -> Iterator
[Tuple
[str, str]]:
125 build_py
= self
.get_finalized_command('build_py')
126 opt
= self
.get_finalized_command('install_lib').optimize
or ""
128 for ext
in self
.extensions
:
129 inplace_file
, regular_file
= self
._get
_inplace
_equivalent
(build_py
, ext
)
130 yield (regular_file
, inplace_file
)
133 # This version of `build_ext` always builds artifacts in another dir,
134 # when "inplace=True" is given it just copies them back.
135 # This is done in the `copy_extensions_to_source` function, which
136 # always compile stub files via `_compile_and_remove_stub`.
137 # At the end of the process, a `.pyc` stub file is created without the
138 # corresponding `.py`.
140 inplace_stub
= self
._get
_equivalent
_stub
(ext
, inplace_file
)
141 regular_stub
= self
._get
_equivalent
_stub
(ext
, regular_file
)
142 inplace_cache
= _compiled_file_name(inplace_stub
, optimization
=opt
)
143 output_cache
= _compiled_file_name(regular_stub
, optimization
=opt
)
144 yield (output_cache
, inplace_cache
)
146 def get_ext_filename(self
, fullname
):
147 so_ext
= os
.getenv('SETUPTOOLS_EXT_SUFFIX')
149 filename
= os
.path
.join(*fullname
.split('.')) + so_ext
151 filename
= _build_ext
.get_ext_filename(self
, fullname
)
152 so_ext
= get_config_var('EXT_SUFFIX')
154 if fullname
in self
.ext_map
:
155 ext
= self
.ext_map
[fullname
]
156 use_abi3
= getattr(ext
, 'py_limited_api') and get_abi3_suffix()
158 filename
= filename
[:-len(so_ext
)]
159 so_ext
= get_abi3_suffix()
160 filename
= filename
+ so_ext
161 if isinstance(ext
, Library
):
162 fn
, ext
= os
.path
.splitext(filename
)
163 return self
.shlib_compiler
.library_filename(fn
, libtype
)
164 elif use_stubs
and ext
._links
_to
_dynamic
:
165 d
, fn
= os
.path
.split(filename
)
166 return os
.path
.join(d
, 'dl-' + fn
)
169 def initialize_options(self
):
170 _build_ext
.initialize_options(self
)
171 self
.shlib_compiler
= None
174 self
.editable_mode
= False
176 def finalize_options(self
):
177 _build_ext
.finalize_options(self
)
178 self
.extensions
= self
.extensions
or []
179 self
.check_extensions_list(self
.extensions
)
180 self
.shlibs
= [ext
for ext
in self
.extensions
181 if isinstance(ext
, Library
)]
183 self
.setup_shlib_compiler()
184 for ext
in self
.extensions
:
185 ext
._full
_name
= self
.get_ext_fullname(ext
.name
)
186 for ext
in self
.extensions
:
187 fullname
= ext
._full
_name
188 self
.ext_map
[fullname
] = ext
190 # distutils 3.1 will also ask for module names
191 # XXX what to do with conflicts?
192 self
.ext_map
[fullname
.split('.')[-1]] = ext
194 ltd
= self
.shlibs
and self
.links_to_dynamic(ext
) or False
195 ns
= ltd
and use_stubs
and not isinstance(ext
, Library
)
196 ext
._links
_to
_dynamic
= ltd
198 filename
= ext
._file
_name
= self
.get_ext_filename(fullname
)
199 libdir
= os
.path
.dirname(os
.path
.join(self
.build_lib
, filename
))
200 if ltd
and libdir
not in ext
.library_dirs
:
201 ext
.library_dirs
.append(libdir
)
202 if ltd
and use_stubs
and os
.curdir
not in ext
.runtime_library_dirs
:
203 ext
.runtime_library_dirs
.append(os
.curdir
)
205 if self
.editable_mode
:
208 def setup_shlib_compiler(self
):
209 compiler
= self
.shlib_compiler
= new_compiler(
210 compiler
=self
.compiler
, dry_run
=self
.dry_run
, force
=self
.force
212 _customize_compiler_for_shlib(compiler
)
214 if self
.include_dirs
is not None:
215 compiler
.set_include_dirs(self
.include_dirs
)
216 if self
.define
is not None:
217 # 'define' option is a list of (name,value) tuples
218 for (name
, value
) in self
.define
:
219 compiler
.define_macro(name
, value
)
220 if self
.undef
is not None:
221 for macro
in self
.undef
:
222 compiler
.undefine_macro(macro
)
223 if self
.libraries
is not None:
224 compiler
.set_libraries(self
.libraries
)
225 if self
.library_dirs
is not None:
226 compiler
.set_library_dirs(self
.library_dirs
)
227 if self
.rpath
is not None:
228 compiler
.set_runtime_library_dirs(self
.rpath
)
229 if self
.link_objects
is not None:
230 compiler
.set_link_objects(self
.link_objects
)
232 # hack so distutils' build_extension() builds a library instead
233 compiler
.link_shared_object
= link_shared_object
.__get
__(compiler
)
235 def get_export_symbols(self
, ext
):
236 if isinstance(ext
, Library
):
237 return ext
.export_symbols
238 return _build_ext
.get_export_symbols(self
, ext
)
240 def build_extension(self
, ext
):
241 ext
._convert
_pyx
_sources
_to
_lang
()
242 _compiler
= self
.compiler
244 if isinstance(ext
, Library
):
245 self
.compiler
= self
.shlib_compiler
246 _build_ext
.build_extension(self
, ext
)
248 build_lib
= self
.get_finalized_command('build_py').build_lib
249 self
.write_stub(build_lib
, ext
)
251 self
.compiler
= _compiler
253 def links_to_dynamic(self
, ext
):
254 """Return true if 'ext' links to a dynamic lib in the same package"""
255 # XXX this should check to ensure the lib is actually being built
256 # XXX as dynamic, and not just using a locally-found version or a
257 # XXX static-compiled version
258 libnames
= dict.fromkeys([lib
._full
_name
for lib
in self
.shlibs
])
259 pkg
= '.'.join(ext
._full
_name
.split('.')[:-1] + [''])
260 return any(pkg
+ libname
in libnames
for libname
in ext
.libraries
)
262 def get_outputs(self
) -> List
[str]:
264 return list(self
.get_output_mapping().keys())
265 return sorted(_build_ext
.get_outputs(self
) + self
.__get
_stubs
_outputs
())
267 def get_output_mapping(self
) -> Dict
[str, str]:
268 """See :class:`setuptools.commands.build.SubCommand`"""
269 mapping
= self
._get
_output
_mapping
()
270 return dict(sorted(mapping
, key
=lambda x
: x
[0]))
272 def __get_stubs_outputs(self
):
273 # assemble the base name for each extension that needs a stub
275 os
.path
.join(self
.build_lib
, *ext
._full
_name
.split('.'))
276 for ext
in self
.extensions
279 # pair each base with the extension
280 pairs
= itertools
.product(ns_ext_bases
, self
.__get
_output
_extensions
())
281 return list(base
+ fnext
for base
, fnext
in pairs
)
283 def __get_output_extensions(self
):
286 if self
.get_finalized_command('build_py').optimize
:
289 def write_stub(self
, output_dir
, ext
, compile=False):
290 stub_file
= os
.path
.join(output_dir
, *ext
._full
_name
.split('.')) + '.py'
291 self
._write
_stub
_file
(stub_file
, ext
, compile)
293 def _write_stub_file(self
, stub_file
: str, ext
: Extension
, compile=False):
294 log
.info("writing stub loader for %s to %s", ext
._full
_name
, stub_file
)
295 if compile and os
.path
.exists(stub_file
):
296 raise BaseError(stub_file
+ " already exists! Please delete.")
298 f
= open(stub_file
, 'w')
301 "def __bootstrap__():",
302 " global __bootstrap__, __file__, __loader__",
303 " import sys, os, pkg_resources, importlib.util" +
305 " __file__ = pkg_resources.resource_filename"
307 % os
.path
.basename(ext
._file
_name
),
308 " del __bootstrap__",
309 " if '__loader__' in globals():",
311 if_dl(" old_flags = sys.getdlopenflags()"),
312 " old_dir = os.getcwd()",
314 " os.chdir(os.path.dirname(__file__))",
315 if_dl(" sys.setdlopenflags(dl.RTLD_NOW)"),
316 " spec = importlib.util.spec_from_file_location(",
317 " __name__, __file__)",
318 " mod = importlib.util.module_from_spec(spec)",
319 " spec.loader.exec_module(mod)",
321 if_dl(" sys.setdlopenflags(old_flags)"),
322 " os.chdir(old_dir)",
329 self
._compile
_and
_remove
_stub
(stub_file
)
331 def _compile_and_remove_stub(self
, stub_file
: str):
332 from distutils
.util
import byte_compile
334 byte_compile([stub_file
], optimize
=0,
335 force
=True, dry_run
=self
.dry_run
)
336 optimize
= self
.get_finalized_command('install_lib').optimize
338 byte_compile([stub_file
], optimize
=optimize
,
339 force
=True, dry_run
=self
.dry_run
)
340 if os
.path
.exists(stub_file
) and not self
.dry_run
:
344 if use_stubs
or os
.name
== 'nt':
345 # Build shared libraries
347 def link_shared_object(
348 self
, objects
, output_libname
, output_dir
=None, libraries
=None,
349 library_dirs
=None, runtime_library_dirs
=None, export_symbols
=None,
350 debug
=0, extra_preargs
=None, extra_postargs
=None, build_temp
=None,
353 self
.SHARED_LIBRARY
, objects
, output_libname
,
354 output_dir
, libraries
, library_dirs
, runtime_library_dirs
,
355 export_symbols
, debug
, extra_preargs
, extra_postargs
,
356 build_temp
, target_lang
359 # Build static libraries everywhere else
362 def link_shared_object(
363 self
, objects
, output_libname
, output_dir
=None, libraries
=None,
364 library_dirs
=None, runtime_library_dirs
=None, export_symbols
=None,
365 debug
=0, extra_preargs
=None, extra_postargs
=None, build_temp
=None,
367 # XXX we need to either disallow these attrs on Library instances,
368 # or warn/abort here if set, or something...
369 # libraries=None, library_dirs=None, runtime_library_dirs=None,
370 # export_symbols=None, extra_preargs=None, extra_postargs=None,
373 assert output_dir
is None # distutils build_ext doesn't pass this
374 output_dir
, filename
= os
.path
.split(output_libname
)
375 basename
, ext
= os
.path
.splitext(filename
)
376 if self
.library_filename("x").startswith('lib'):
377 # strip 'lib' prefix; this is kludgy if some platform uses
379 basename
= basename
[3:]
381 self
.create_static_lib(
382 objects
, basename
, output_dir
, debug
, target_lang