Path: blob/master/venv/Lib/site-packages/setuptools/command/build_ext.py
811 views
import os1import sys2import itertools3from distutils.command.build_ext import build_ext as _du_build_ext4from distutils.file_util import copy_file5from distutils.ccompiler import new_compiler6from distutils.sysconfig import customize_compiler, get_config_var7from distutils.errors import DistutilsError8from distutils import log910from setuptools.extension import Library11from setuptools.extern import six1213if six.PY2:14import imp1516EXTENSION_SUFFIXES = [17s for s, _, tp in imp.get_suffixes() if tp == imp.C_EXTENSION]18else:19from importlib.machinery import EXTENSION_SUFFIXES2021try:22# Attempt to use Cython for building extensions, if available23from Cython.Distutils.build_ext import build_ext as _build_ext24# Additionally, assert that the compiler module will load25# also. Ref #1229.26__import__('Cython.Compiler.Main')27except ImportError:28_build_ext = _du_build_ext2930# make sure _config_vars is initialized31get_config_var("LDSHARED")32from distutils.sysconfig import _config_vars as _CONFIG_VARS # noqa333435def _customize_compiler_for_shlib(compiler):36if sys.platform == "darwin":37# building .dylib requires additional compiler flags on OSX; here we38# temporarily substitute the pyconfig.h variables so that distutils'39# 'customize_compiler' uses them before we build the shared libraries.40tmp = _CONFIG_VARS.copy()41try:42# XXX Help! I don't have any idea whether these are right...43_CONFIG_VARS['LDSHARED'] = (44"gcc -Wl,-x -dynamiclib -undefined dynamic_lookup")45_CONFIG_VARS['CCSHARED'] = " -dynamiclib"46_CONFIG_VARS['SO'] = ".dylib"47customize_compiler(compiler)48finally:49_CONFIG_VARS.clear()50_CONFIG_VARS.update(tmp)51else:52customize_compiler(compiler)535455have_rtld = False56use_stubs = False57libtype = 'shared'5859if sys.platform == "darwin":60use_stubs = True61elif os.name != 'nt':62try:63import dl64use_stubs = have_rtld = hasattr(dl, 'RTLD_NOW')65except ImportError:66pass676869def if_dl(s):70return s if have_rtld else ''717273def get_abi3_suffix():74"""Return the file extension for an abi3-compliant Extension()"""75for suffix in EXTENSION_SUFFIXES:76if '.abi3' in suffix: # Unix77return suffix78elif suffix == '.pyd': # Windows79return suffix808182class build_ext(_build_ext):83def run(self):84"""Build extensions in build directory, then copy if --inplace"""85old_inplace, self.inplace = self.inplace, 086_build_ext.run(self)87self.inplace = old_inplace88if old_inplace:89self.copy_extensions_to_source()9091def copy_extensions_to_source(self):92build_py = self.get_finalized_command('build_py')93for ext in self.extensions:94fullname = self.get_ext_fullname(ext.name)95filename = self.get_ext_filename(fullname)96modpath = fullname.split('.')97package = '.'.join(modpath[:-1])98package_dir = build_py.get_package_dir(package)99dest_filename = os.path.join(package_dir,100os.path.basename(filename))101src_filename = os.path.join(self.build_lib, filename)102103# Always copy, even if source is older than destination, to ensure104# that the right extensions for the current Python/platform are105# used.106copy_file(107src_filename, dest_filename, verbose=self.verbose,108dry_run=self.dry_run109)110if ext._needs_stub:111self.write_stub(package_dir or os.curdir, ext, True)112113def get_ext_filename(self, fullname):114filename = _build_ext.get_ext_filename(self, fullname)115if fullname in self.ext_map:116ext = self.ext_map[fullname]117use_abi3 = (118not six.PY2119and getattr(ext, 'py_limited_api')120and get_abi3_suffix()121)122if use_abi3:123so_ext = get_config_var('EXT_SUFFIX')124filename = filename[:-len(so_ext)]125filename = filename + get_abi3_suffix()126if isinstance(ext, Library):127fn, ext = os.path.splitext(filename)128return self.shlib_compiler.library_filename(fn, libtype)129elif use_stubs and ext._links_to_dynamic:130d, fn = os.path.split(filename)131return os.path.join(d, 'dl-' + fn)132return filename133134def initialize_options(self):135_build_ext.initialize_options(self)136self.shlib_compiler = None137self.shlibs = []138self.ext_map = {}139140def finalize_options(self):141_build_ext.finalize_options(self)142self.extensions = self.extensions or []143self.check_extensions_list(self.extensions)144self.shlibs = [ext for ext in self.extensions145if isinstance(ext, Library)]146if self.shlibs:147self.setup_shlib_compiler()148for ext in self.extensions:149ext._full_name = self.get_ext_fullname(ext.name)150for ext in self.extensions:151fullname = ext._full_name152self.ext_map[fullname] = ext153154# distutils 3.1 will also ask for module names155# XXX what to do with conflicts?156self.ext_map[fullname.split('.')[-1]] = ext157158ltd = self.shlibs and self.links_to_dynamic(ext) or False159ns = ltd and use_stubs and not isinstance(ext, Library)160ext._links_to_dynamic = ltd161ext._needs_stub = ns162filename = ext._file_name = self.get_ext_filename(fullname)163libdir = os.path.dirname(os.path.join(self.build_lib, filename))164if ltd and libdir not in ext.library_dirs:165ext.library_dirs.append(libdir)166if ltd and use_stubs and os.curdir not in ext.runtime_library_dirs:167ext.runtime_library_dirs.append(os.curdir)168169def setup_shlib_compiler(self):170compiler = self.shlib_compiler = new_compiler(171compiler=self.compiler, dry_run=self.dry_run, force=self.force172)173_customize_compiler_for_shlib(compiler)174175if self.include_dirs is not None:176compiler.set_include_dirs(self.include_dirs)177if self.define is not None:178# 'define' option is a list of (name,value) tuples179for (name, value) in self.define:180compiler.define_macro(name, value)181if self.undef is not None:182for macro in self.undef:183compiler.undefine_macro(macro)184if self.libraries is not None:185compiler.set_libraries(self.libraries)186if self.library_dirs is not None:187compiler.set_library_dirs(self.library_dirs)188if self.rpath is not None:189compiler.set_runtime_library_dirs(self.rpath)190if self.link_objects is not None:191compiler.set_link_objects(self.link_objects)192193# hack so distutils' build_extension() builds a library instead194compiler.link_shared_object = link_shared_object.__get__(compiler)195196def get_export_symbols(self, ext):197if isinstance(ext, Library):198return ext.export_symbols199return _build_ext.get_export_symbols(self, ext)200201def build_extension(self, ext):202ext._convert_pyx_sources_to_lang()203_compiler = self.compiler204try:205if isinstance(ext, Library):206self.compiler = self.shlib_compiler207_build_ext.build_extension(self, ext)208if ext._needs_stub:209cmd = self.get_finalized_command('build_py').build_lib210self.write_stub(cmd, ext)211finally:212self.compiler = _compiler213214def links_to_dynamic(self, ext):215"""Return true if 'ext' links to a dynamic lib in the same package"""216# XXX this should check to ensure the lib is actually being built217# XXX as dynamic, and not just using a locally-found version or a218# XXX static-compiled version219libnames = dict.fromkeys([lib._full_name for lib in self.shlibs])220pkg = '.'.join(ext._full_name.split('.')[:-1] + [''])221return any(pkg + libname in libnames for libname in ext.libraries)222223def get_outputs(self):224return _build_ext.get_outputs(self) + self.__get_stubs_outputs()225226def __get_stubs_outputs(self):227# assemble the base name for each extension that needs a stub228ns_ext_bases = (229os.path.join(self.build_lib, *ext._full_name.split('.'))230for ext in self.extensions231if ext._needs_stub232)233# pair each base with the extension234pairs = itertools.product(ns_ext_bases, self.__get_output_extensions())235return list(base + fnext for base, fnext in pairs)236237def __get_output_extensions(self):238yield '.py'239yield '.pyc'240if self.get_finalized_command('build_py').optimize:241yield '.pyo'242243def write_stub(self, output_dir, ext, compile=False):244log.info("writing stub loader for %s to %s", ext._full_name,245output_dir)246stub_file = (os.path.join(output_dir, *ext._full_name.split('.')) +247'.py')248if compile and os.path.exists(stub_file):249raise DistutilsError(stub_file + " already exists! Please delete.")250if not self.dry_run:251f = open(stub_file, 'w')252f.write(253'\n'.join([254"def __bootstrap__():",255" global __bootstrap__, __file__, __loader__",256" import sys, os, pkg_resources" + if_dl(", dl"),257" from importlib.machinery import ExtensionFileLoader",258" __file__ = pkg_resources.resource_filename"259"(__name__,%r)"260% os.path.basename(ext._file_name),261" del __bootstrap__",262" if '__loader__' in globals():",263" del __loader__",264if_dl(" old_flags = sys.getdlopenflags()"),265" old_dir = os.getcwd()",266" try:",267" os.chdir(os.path.dirname(__file__))",268if_dl(" sys.setdlopenflags(dl.RTLD_NOW)"),269" ExtensionFileLoader(__name__,",270" __file__).exec_module()",271" finally:",272if_dl(" sys.setdlopenflags(old_flags)"),273" os.chdir(old_dir)",274"__bootstrap__()",275"" # terminal \n276])277)278f.close()279if compile:280from distutils.util import byte_compile281282byte_compile([stub_file], optimize=0,283force=True, dry_run=self.dry_run)284optimize = self.get_finalized_command('install_lib').optimize285if optimize > 0:286byte_compile([stub_file], optimize=optimize,287force=True, dry_run=self.dry_run)288if os.path.exists(stub_file) and not self.dry_run:289os.unlink(stub_file)290291292if use_stubs or os.name == 'nt':293# Build shared libraries294#295def link_shared_object(296self, objects, output_libname, output_dir=None, libraries=None,297library_dirs=None, runtime_library_dirs=None, export_symbols=None,298debug=0, extra_preargs=None, extra_postargs=None, build_temp=None,299target_lang=None):300self.link(301self.SHARED_LIBRARY, objects, output_libname,302output_dir, libraries, library_dirs, runtime_library_dirs,303export_symbols, debug, extra_preargs, extra_postargs,304build_temp, target_lang305)306else:307# Build static libraries everywhere else308libtype = 'static'309310def link_shared_object(311self, objects, output_libname, output_dir=None, libraries=None,312library_dirs=None, runtime_library_dirs=None, export_symbols=None,313debug=0, extra_preargs=None, extra_postargs=None, build_temp=None,314target_lang=None):315# XXX we need to either disallow these attrs on Library instances,316# or warn/abort here if set, or something...317# libraries=None, library_dirs=None, runtime_library_dirs=None,318# export_symbols=None, extra_preargs=None, extra_postargs=None,319# build_temp=None320321assert output_dir is None # distutils build_ext doesn't pass this322output_dir, filename = os.path.split(output_libname)323basename, ext = os.path.splitext(filename)324if self.library_filename("x").startswith('lib'):325# strip 'lib' prefix; this is kludgy if some platform uses326# a different prefix327basename = basename[3:]328329self.create_static_lib(330objects, basename, output_dir, debug, target_lang331)332333334