Statistics
| Branch: | Revision:

root / env / lib / python2.7 / site-packages / distribute-0.6.19-py2.7.egg / setuptools / command / build_ext.py @ 1a305335

History | View | Annotate | Download (11.4 KB)

1
from distutils.command.build_ext import build_ext as _du_build_ext
2
try:
3
    # Attempt to use Pyrex for building extensions, if available
4
    from Pyrex.Distutils.build_ext import build_ext as _build_ext
5
except ImportError:
6
    _build_ext = _du_build_ext
7

    
8
import os, sys
9
from distutils.file_util import copy_file
10
from setuptools.extension import Library
11
from distutils.ccompiler import new_compiler
12
from distutils.sysconfig import customize_compiler, get_config_var
13
get_config_var("LDSHARED")  # make sure _config_vars is initialized
14
from distutils.sysconfig import _config_vars
15
from distutils import log
16
from distutils.errors import *
17

    
18
have_rtld = False
19
use_stubs = False
20
libtype = 'shared'
21

    
22
if sys.platform == "darwin":
23
    use_stubs = True
24
elif os.name != 'nt':
25
    try:
26
        from dl import RTLD_NOW
27
        have_rtld = True
28
        use_stubs = True
29
    except ImportError:
30
        pass
31

    
32
def if_dl(s):
33
    if have_rtld:
34
        return s
35
    return ''
36

    
37

    
38

    
39

    
40

    
41

    
42
class build_ext(_build_ext):
43
    def run(self):
44
        """Build extensions in build directory, then copy if --inplace"""
45
        old_inplace, self.inplace = self.inplace, 0
46
        _build_ext.run(self)
47
        self.inplace = old_inplace
48
        if old_inplace:
49
            self.copy_extensions_to_source()
50

    
51
    def copy_extensions_to_source(self):
52
        build_py = self.get_finalized_command('build_py')
53
        for ext in self.extensions:
54
            fullname = self.get_ext_fullname(ext.name)
55
            filename = self.get_ext_filename(fullname)
56
            modpath = fullname.split('.')
57
            package = '.'.join(modpath[:-1])
58
            package_dir = build_py.get_package_dir(package)
59
            dest_filename = os.path.join(package_dir,os.path.basename(filename))
60
            src_filename = os.path.join(self.build_lib,filename)
61

    
62
            # Always copy, even if source is older than destination, to ensure
63
            # that the right extensions for the current Python/platform are
64
            # used.
65
            copy_file(
66
                src_filename, dest_filename, verbose=self.verbose,
67
                dry_run=self.dry_run
68
            )
69
            if ext._needs_stub:
70
                self.write_stub(package_dir or os.curdir, ext, True)
71

    
72

    
73
    if _build_ext is not _du_build_ext and not hasattr(_build_ext,'pyrex_sources'):
74
        # Workaround for problems using some Pyrex versions w/SWIG and/or 2.4
75
        def swig_sources(self, sources, *otherargs):
76
            # first do any Pyrex processing
77
            sources = _build_ext.swig_sources(self, sources) or sources
78
            # Then do any actual SWIG stuff on the remainder
79
            return _du_build_ext.swig_sources(self, sources, *otherargs)
80

    
81

    
82

    
83
    def get_ext_filename(self, fullname):
84
        filename = _build_ext.get_ext_filename(self,fullname)
85
        if fullname not in self.ext_map:
86
            return filename
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

    
117
            # distutils 3.1 will also ask for module names
118
            # XXX what to do with conflicts?
119
            self.ext_map[fullname.split('.')[-1]] = ext
120

    
121
            ltd = ext._links_to_dynamic = \
122
                self.shlibs and self.links_to_dynamic(ext) or False
123
            ext._needs_stub = ltd and use_stubs and not isinstance(ext,Library)
124
            filename = ext._file_name = self.get_ext_filename(fullname)
125
            libdir = os.path.dirname(os.path.join(self.build_lib,filename))
126
            if ltd and libdir not in ext.library_dirs:
127
                ext.library_dirs.append(libdir)
128
            if ltd and use_stubs and os.curdir not in ext.runtime_library_dirs:
129
                ext.runtime_library_dirs.append(os.curdir)
130

    
131
    def setup_shlib_compiler(self):
132
        compiler = self.shlib_compiler = new_compiler(
133
            compiler=self.compiler, dry_run=self.dry_run, force=self.force
134
        )
135
        if sys.platform == "darwin":
136
            tmp = _config_vars.copy()
137
            try:
138
                # XXX Help!  I don't have any idea whether these are right...
139
                _config_vars['LDSHARED'] = "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup"
140
                _config_vars['CCSHARED'] = " -dynamiclib"
141
                _config_vars['SO'] = ".dylib"
142
                customize_compiler(compiler)
143
            finally:
144
                _config_vars.clear()
145
                _config_vars.update(tmp)
146
        else:
147
            customize_compiler(compiler)
148

    
149
        if self.include_dirs is not None:
150
            compiler.set_include_dirs(self.include_dirs)
151
        if self.define is not None:
152
            # 'define' option is a list of (name,value) tuples
153
            for (name,value) in self.define:
154
                compiler.define_macro(name, value)
155
        if self.undef is not None:
156
            for macro in self.undef:
157
                compiler.undefine_macro(macro)
158
        if self.libraries is not None:
159
            compiler.set_libraries(self.libraries)
160
        if self.library_dirs is not None:
161
            compiler.set_library_dirs(self.library_dirs)
162
        if self.rpath is not None:
163
            compiler.set_runtime_library_dirs(self.rpath)
164
        if self.link_objects is not None:
165
            compiler.set_link_objects(self.link_objects)
166

    
167
        # hack so distutils' build_extension() builds a library instead
168
        compiler.link_shared_object = link_shared_object.__get__(compiler)
169

    
170

    
171

    
172
    def get_export_symbols(self, ext):
173
        if isinstance(ext,Library):
174
            return ext.export_symbols
175
        return _build_ext.get_export_symbols(self,ext)
176

    
177
    def build_extension(self, ext):
178
        _compiler = self.compiler
179
        try:
180
            if isinstance(ext,Library):
181
                self.compiler = self.shlib_compiler
182
            _build_ext.build_extension(self,ext)
183
            if ext._needs_stub:
184
                self.write_stub(
185
                    self.get_finalized_command('build_py').build_lib, ext
186
                )
187
        finally:
188
            self.compiler = _compiler
189

    
190
    def links_to_dynamic(self, ext):
191
        """Return true if 'ext' links to a dynamic lib in the same package"""
192
        # XXX this should check to ensure the lib is actually being built
193
        # XXX as dynamic, and not just using a locally-found version or a
194
        # XXX static-compiled version
195
        libnames = dict.fromkeys([lib._full_name for lib in self.shlibs])
196
        pkg = '.'.join(ext._full_name.split('.')[:-1]+[''])
197
        for libname in ext.libraries:
198
            if pkg+libname in libnames: return True
199
        return False
200

    
201
    def get_outputs(self):
202
        outputs = _build_ext.get_outputs(self)
203
        optimize = self.get_finalized_command('build_py').optimize
204
        for ext in self.extensions:
205
            if ext._needs_stub:
206
                base = os.path.join(self.build_lib, *ext._full_name.split('.'))
207
                outputs.append(base+'.py')
208
                outputs.append(base+'.pyc')
209
                if optimize:
210
                    outputs.append(base+'.pyo')
211
        return outputs
212

    
213
    def write_stub(self, output_dir, ext, compile=False):
214
        log.info("writing stub loader for %s to %s",ext._full_name, output_dir)
215
        stub_file = os.path.join(output_dir, *ext._full_name.split('.'))+'.py'
216
        if compile and os.path.exists(stub_file):
217
            raise DistutilsError(stub_file+" already exists! Please delete.")
218
        if not self.dry_run:
219
            f = open(stub_file,'w')
220
            f.write('\n'.join([
221
                "def __bootstrap__():",
222
                "   global __bootstrap__, __file__, __loader__",
223
                "   import sys, os, pkg_resources, imp"+if_dl(", dl"),
224
                "   __file__ = pkg_resources.resource_filename(__name__,%r)"
225
                   % os.path.basename(ext._file_name),
226
                "   del __bootstrap__",
227
                "   if '__loader__' in globals():",
228
                "       del __loader__",
229
                if_dl("   old_flags = sys.getdlopenflags()"),
230
                "   old_dir = os.getcwd()",
231
                "   try:",
232
                "     os.chdir(os.path.dirname(__file__))",
233
                if_dl("     sys.setdlopenflags(dl.RTLD_NOW)"),
234
                "     imp.load_dynamic(__name__,__file__)",
235
                "   finally:",
236
                if_dl("     sys.setdlopenflags(old_flags)"),
237
                "     os.chdir(old_dir)",
238
                "__bootstrap__()",
239
                "" # terminal \n
240
            ]))
241
            f.close()
242
        if compile:
243
            from distutils.util import byte_compile
244
            byte_compile([stub_file], optimize=0,
245
                         force=True, dry_run=self.dry_run)
246
            optimize = self.get_finalized_command('install_lib').optimize
247
            if optimize > 0:
248
                byte_compile([stub_file], optimize=optimize,
249
                             force=True, dry_run=self.dry_run)
250
            if os.path.exists(stub_file) and not self.dry_run:
251
                os.unlink(stub_file)
252

    
253

    
254
if use_stubs or os.name=='nt':
255
    # Build shared libraries
256
    #
257
    def link_shared_object(self, objects, output_libname, output_dir=None,
258
        libraries=None, library_dirs=None, runtime_library_dirs=None,
259
        export_symbols=None, debug=0, extra_preargs=None,
260
        extra_postargs=None, build_temp=None, target_lang=None
261
    ):  self.link(
262
            self.SHARED_LIBRARY, objects, output_libname,
263
            output_dir, libraries, library_dirs, runtime_library_dirs,
264
            export_symbols, debug, extra_preargs, extra_postargs,
265
            build_temp, target_lang
266
        )
267
else:
268
    # Build static libraries everywhere else
269
    libtype = 'static'
270

    
271
    def link_shared_object(self, objects, output_libname, output_dir=None,
272
        libraries=None, library_dirs=None, runtime_library_dirs=None,
273
        export_symbols=None, debug=0, extra_preargs=None,
274
        extra_postargs=None, build_temp=None, target_lang=None
275
    ):
276
        # XXX we need to either disallow these attrs on Library instances,
277
        #     or warn/abort here if set, or something...
278
        #libraries=None, library_dirs=None, runtime_library_dirs=None,
279
        #export_symbols=None, extra_preargs=None, extra_postargs=None,
280
        #build_temp=None
281

    
282
        assert output_dir is None   # distutils build_ext doesn't pass this
283
        output_dir,filename = os.path.split(output_libname)
284
        basename, ext = os.path.splitext(filename)
285
        if self.library_filename("x").startswith('lib'):
286
            # strip 'lib' prefix; this is kludgy if some platform uses
287
            # a different prefix
288
            basename = basename[3:]
289

    
290
        self.create_static_lib(
291
            objects, basename, output_dir, debug, target_lang
292
        )
293

    
294