1import os 2import re 3import sys 4 5try: 6 from Cython.Distutils import build_ext 7except ImportError: 8 from setuptools.command.build_ext import build_ext 9 10from distutils.extension import Extension 11from distutils.sysconfig import get_config_vars, get_python_lib, get_python_version 12from pkg_resources import Distribution 13 14 15if sys.platform == 'darwin': 16 config_vars = get_config_vars() 17 config_vars['LDSHARED'] = config_vars['LDSHARED'].replace('-bundle', '') 18 config_vars['SHLIB_EXT'] = '.so' 19 20 21def is_pip_install(): 22 if "_" in os.environ and os.environ["_"].endswith("pip"): 23 return True 24 if "pip-egg-info" in sys.argv: 25 return True 26 if re.search("/pip-.*-build/", __file__): 27 return True 28 return False 29 30 31class CyExtension(Extension): 32 def __init__(self, *args, **kwargs): 33 self._init_func = kwargs.pop("init_func", None) 34 self._prebuild_func = kwargs.pop("prebuild_func", None) 35 Extension.__init__(self, *args, **kwargs) 36 37 def extend_includes(self, includes): 38 self.include_dirs.extend(includes) 39 40 def extend_macros(self, macros): 41 self.define_macros.extend(macros) 42 43 def extend_extra_objects(self, objs): 44 self.extra_objects.extend(objs) 45 46 47class cy_build_ext(build_ext): 48 49 def _get_egg_name(self): 50 ei_cmd = self.get_finalized_command("egg_info") 51 return Distribution( 52 None, None, ei_cmd.egg_name, ei_cmd.egg_version, get_python_version(), 53 self.distribution.has_ext_modules() and self.plat_name).egg_name() 54 55 def build_extension(self, ext): 56 57 if isinstance(ext, CyExtension) and ext._init_func: 58 ext._init_func(ext) 59 60 if not self.inplace: 61 ext.library_dirs.append(os.path.join(self.build_lib, "pysam")) 62 63 if sys.platform == 'darwin': 64 # The idea is to give shared libraries an install name of the form 65 # `@rpath/<library-name.so>`, and to set the rpath equal to 66 # @loader_path. This will allow Python packages to find the library 67 # in the expected place, while still giving enough flexibility to 68 # external applications to link against the library. 69 relative_module_path = ext.name.replace(".", os.sep) + get_config_vars()["SO"] 70 library_path = os.path.join( 71 "@rpath", os.path.basename(relative_module_path) 72 ) 73 74 if not ext.extra_link_args: 75 ext.extra_link_args = [] 76 ext.extra_link_args += ['-dynamiclib', 77 '-rpath', '@loader_path', 78 '-Wl,-headerpad_max_install_names', 79 '-Wl,-install_name,%s' % library_path, 80 '-Wl,-x'] 81 else: 82 if not ext.extra_link_args: 83 ext.extra_link_args = [] 84 85 ext.extra_link_args += ['-Wl,-rpath,$ORIGIN'] 86 87 if isinstance(ext, CyExtension) and ext._prebuild_func: 88 ext._prebuild_func(ext, self.force) 89 90 build_ext.build_extension(self, ext) 91