PageRenderTime 31ms CodeModel.GetById 11ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/distutils/tests/setuptools_build_ext.py

http://unladen-swallow.googlecode.com/
Python | 287 lines | 268 code | 14 blank | 5 comment | 24 complexity | ea68e74f93a2464d54dac3bca14802cb MD5 | raw file
  1from distutils.command.build_ext import build_ext as _du_build_ext
  2try:
  3    # Attempt to use Pyrex for building extensions, if available
  4    from Pyrex.Distutils.build_ext import build_ext as _build_ext
  5except ImportError:
  6    _build_ext = _du_build_ext
  7
  8import os, sys
  9from distutils.file_util import copy_file
 10
 11from distutils.tests.setuptools_extension import Library
 12
 13from distutils.ccompiler import new_compiler
 14from distutils.sysconfig import customize_compiler, get_config_var
 15get_config_var("LDSHARED")  # make sure _config_vars is initialized
 16from distutils.sysconfig import _config_vars
 17from distutils import log
 18from distutils.errors import *
 19
 20have_rtld = False
 21use_stubs = False
 22libtype = 'shared'
 23
 24if sys.platform == "darwin":
 25    use_stubs = True
 26elif os.name != 'nt':
 27    try:
 28        from dl import RTLD_NOW
 29        have_rtld = True
 30        use_stubs = True
 31    except ImportError:
 32        pass
 33
 34def if_dl(s):
 35    if have_rtld:
 36        return s
 37    return ''
 38
 39
 40
 41
 42
 43
 44class build_ext(_build_ext):
 45    def run(self):
 46        """Build extensions in build directory, then copy if --inplace"""
 47        old_inplace, self.inplace = self.inplace, 0
 48        _build_ext.run(self)
 49        self.inplace = old_inplace
 50        if old_inplace:
 51            self.copy_extensions_to_source()
 52
 53    def copy_extensions_to_source(self):
 54        build_py = self.get_finalized_command('build_py')
 55        for ext in self.extensions:
 56            fullname = self.get_ext_fullname(ext.name)
 57            filename = self.get_ext_filename(fullname)
 58            modpath = fullname.split('.')
 59            package = '.'.join(modpath[:-1])
 60            package_dir = build_py.get_package_dir(package)
 61            dest_filename = os.path.join(package_dir,os.path.basename(filename))
 62            src_filename = os.path.join(self.build_lib,filename)
 63
 64            # Always copy, even if source is older than destination, to ensure
 65            # that the right extensions for the current Python/platform are
 66            # used.
 67            copy_file(
 68                src_filename, dest_filename, verbose=self.verbose,
 69                dry_run=self.dry_run
 70            )
 71            if ext._needs_stub:
 72                self.write_stub(package_dir or os.curdir, ext, True)
 73
 74
 75    if _build_ext is not _du_build_ext and not hasattr(_build_ext,'pyrex_sources'):
 76        # Workaround for problems using some Pyrex versions w/SWIG and/or 2.4
 77        def swig_sources(self, sources, *otherargs):
 78            # first do any Pyrex processing
 79            sources = _build_ext.swig_sources(self, sources) or sources
 80            # Then do any actual SWIG stuff on the remainder
 81            return _du_build_ext.swig_sources(self, sources, *otherargs)
 82
 83
 84
 85    def get_ext_filename(self, fullname):
 86        filename = _build_ext.get_ext_filename(self,fullname)
 87        ext = self.ext_map[fullname]
 88        if isinstance(ext,Library):
 89            fn, ext = os.path.splitext(filename)
 90            return self.shlib_compiler.library_filename(fn,libtype)
 91        elif use_stubs and ext._links_to_dynamic:
 92            d,fn = os.path.split(filename)
 93            return os.path.join(d,'dl-'+fn)
 94        else:
 95            return filename
 96
 97    def initialize_options(self):
 98        _build_ext.initialize_options(self)
 99        self.shlib_compiler = None
100        self.shlibs = []
101        self.ext_map = {}
102
103    def finalize_options(self):
104        _build_ext.finalize_options(self)
105        self.extensions = self.extensions or []
106        self.check_extensions_list(self.extensions)
107        self.shlibs = [ext for ext in self.extensions
108                        if isinstance(ext,Library)]
109        if self.shlibs:
110            self.setup_shlib_compiler()
111        for ext in self.extensions:
112            ext._full_name = self.get_ext_fullname(ext.name)
113        for ext in self.extensions:
114            fullname = ext._full_name
115            self.ext_map[fullname] = ext
116            ltd = ext._links_to_dynamic = \
117                self.shlibs and self.links_to_dynamic(ext) or False
118            ext._needs_stub = ltd and use_stubs and not isinstance(ext,Library)
119            filename = ext._file_name = self.get_ext_filename(fullname)
120            libdir = os.path.dirname(os.path.join(self.build_lib,filename))
121            if ltd and libdir not in ext.library_dirs:
122                ext.library_dirs.append(libdir)
123            if ltd and use_stubs and os.curdir not in ext.runtime_library_dirs:
124                ext.runtime_library_dirs.append(os.curdir)
125
126    def setup_shlib_compiler(self):
127        compiler = self.shlib_compiler = new_compiler(
128            compiler=self.compiler, dry_run=self.dry_run, force=self.force
129        )
130        if sys.platform == "darwin":
131            tmp = _config_vars.copy()
132            try:
133                # XXX Help!  I don't have any idea whether these are right...
134                _config_vars['LDSHARED'] = "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup"
135                _config_vars['CCSHARED'] = " -dynamiclib"
136                _config_vars['SO'] = ".dylib"
137                customize_compiler(compiler)
138            finally:
139                _config_vars.clear()
140                _config_vars.update(tmp)
141        else:
142            customize_compiler(compiler)
143
144        if self.include_dirs is not None:
145            compiler.set_include_dirs(self.include_dirs)
146        if self.define is not None:
147            # 'define' option is a list of (name,value) tuples
148            for (name,value) in self.define:
149                compiler.define_macro(name, value)
150        if self.undef is not None:
151            for macro in self.undef:
152                compiler.undefine_macro(macro)
153        if self.libraries is not None:
154            compiler.set_libraries(self.libraries)
155        if self.library_dirs is not None:
156            compiler.set_library_dirs(self.library_dirs)
157        if self.rpath is not None:
158            compiler.set_runtime_library_dirs(self.rpath)
159        if self.link_objects is not None:
160            compiler.set_link_objects(self.link_objects)
161
162        # hack so distutils' build_extension() builds a library instead
163        compiler.link_shared_object = link_shared_object.__get__(compiler)
164
165
166
167    def get_export_symbols(self, ext):
168        if isinstance(ext,Library):
169            return ext.export_symbols
170        return _build_ext.get_export_symbols(self,ext)
171
172    def build_extension(self, ext):
173        _compiler = self.compiler
174        try:
175            if isinstance(ext,Library):
176                self.compiler = self.shlib_compiler
177            _build_ext.build_extension(self,ext)
178            if ext._needs_stub:
179                self.write_stub(
180                    self.get_finalized_command('build_py').build_lib, ext
181                )
182        finally:
183            self.compiler = _compiler
184
185    def links_to_dynamic(self, ext):
186        """Return true if 'ext' links to a dynamic lib in the same package"""
187        # XXX this should check to ensure the lib is actually being built
188        # XXX as dynamic, and not just using a locally-found version or a
189        # XXX static-compiled version
190        libnames = dict.fromkeys([lib._full_name for lib in self.shlibs])
191        pkg = '.'.join(ext._full_name.split('.')[:-1]+[''])
192        for libname in ext.libraries:
193            if pkg+libname in libnames: return True
194        return False
195
196    def get_outputs(self):
197        outputs = _build_ext.get_outputs(self)
198        optimize = self.get_finalized_command('build_py').optimize
199        for ext in self.extensions:
200            if ext._needs_stub:
201                base = os.path.join(self.build_lib, *ext._full_name.split('.'))
202                outputs.append(base+'.py')
203                outputs.append(base+'.pyc')
204                if optimize:
205                    outputs.append(base+'.pyo')
206        return outputs
207
208    def write_stub(self, output_dir, ext, compile=False):
209        log.info("writing stub loader for %s to %s",ext._full_name, output_dir)
210        stub_file = os.path.join(output_dir, *ext._full_name.split('.'))+'.py'
211        if compile and os.path.exists(stub_file):
212            raise DistutilsError(stub_file+" already exists! Please delete.")
213        if not self.dry_run:
214            f = open(stub_file,'w')
215            f.write('\n'.join([
216                "def __bootstrap__():",
217                "   global __bootstrap__, __file__, __loader__",
218                "   import sys, os, pkg_resources, imp"+if_dl(", dl"),
219                "   __file__ = pkg_resources.resource_filename(__name__,%r)"
220                   % os.path.basename(ext._file_name),
221                "   del __bootstrap__",
222                "   if '__loader__' in globals():",
223                "       del __loader__",
224                if_dl("   old_flags = sys.getdlopenflags()"),
225                "   old_dir = os.getcwd()",
226                "   try:",
227                "     os.chdir(os.path.dirname(__file__))",
228                if_dl("     sys.setdlopenflags(dl.RTLD_NOW)"),
229                "     imp.load_dynamic(__name__,__file__)",
230                "   finally:",
231                if_dl("     sys.setdlopenflags(old_flags)"),
232                "     os.chdir(old_dir)",
233                "__bootstrap__()",
234                "" # terminal \n
235            ]))
236            f.close()
237        if compile:
238            from distutils.util import byte_compile
239            byte_compile([stub_file], optimize=0,
240                         force=True, dry_run=self.dry_run)
241            optimize = self.get_finalized_command('install_lib').optimize
242            if optimize > 0:
243                byte_compile([stub_file], optimize=optimize,
244                             force=True, dry_run=self.dry_run)
245            if os.path.exists(stub_file) and not self.dry_run:
246                os.unlink(stub_file)
247
248
249if use_stubs or os.name=='nt':
250    # Build shared libraries
251    #
252    def link_shared_object(self, objects, output_libname, output_dir=None,
253        libraries=None, library_dirs=None, runtime_library_dirs=None,
254        export_symbols=None, debug=0, extra_preargs=None,
255        extra_postargs=None, build_temp=None, target_lang=None
256    ):  self.link(
257            self.SHARED_LIBRARY, objects, output_libname,
258            output_dir, libraries, library_dirs, runtime_library_dirs,
259            export_symbols, debug, extra_preargs, extra_postargs,
260            build_temp, target_lang
261        )
262else:
263    # Build static libraries everywhere else
264    libtype = 'static'
265
266    def link_shared_object(self, objects, output_libname, output_dir=None,
267        libraries=None, library_dirs=None, runtime_library_dirs=None,
268        export_symbols=None, debug=0, extra_preargs=None,
269        extra_postargs=None, build_temp=None, target_lang=None
270    ):
271        # XXX we need to either disallow these attrs on Library instances,
272        #     or warn/abort here if set, or something...
273        #libraries=None, library_dirs=None, runtime_library_dirs=None,
274        #export_symbols=None, extra_preargs=None, extra_postargs=None,
275        #build_temp=None
276
277        assert output_dir is None   # distutils build_ext doesn't pass this
278        output_dir,filename = os.path.split(output_libname)
279        basename, ext = os.path.splitext(filename)
280        if self.library_filename("x").startswith('lib'):
281            # strip 'lib' prefix; this is kludgy if some platform uses
282            # a different prefix
283            basename = basename[3:]
284
285        self.create_static_lib(
286            objects, basename, output_dir, debug, target_lang
287        )