setup.py revision ffd5d886c2eb95c04e37736058994b263b2ab424
1# Autodetecting setup.py script for building the Python extensions
2#
3
4__version__ = "$Revision$"
5
6import sys, os, imp, re, optparse
7from glob import glob
8from platform import machine as platform_machine
9
10from distutils import log
11from distutils import sysconfig
12from distutils import text_file
13from distutils.errors import *
14from distutils.core import Extension, setup
15from distutils.command.build_ext import build_ext
16from distutils.command.install import install
17from distutils.command.install_lib import install_lib
18
19# Were we compiled --with-pydebug or with #define Py_DEBUG?
20COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
21
22# This global variable is used to hold the list of modules to be disabled.
23disabled_module_list = []
24
25def add_dir_to_list(dirlist, dir):
26    """Add the directory 'dir' to the list 'dirlist' (at the front) if
27    1) 'dir' is not already in 'dirlist'
28    2) 'dir' actually exists, and is a directory."""
29    if dir is not None and os.path.isdir(dir) and dir not in dirlist:
30        dirlist.insert(0, dir)
31
32def find_file(filename, std_dirs, paths):
33    """Searches for the directory where a given file is located,
34    and returns a possibly-empty list of additional directories, or None
35    if the file couldn't be found at all.
36
37    'filename' is the name of a file, such as readline.h or libcrypto.a.
38    'std_dirs' is the list of standard system directories; if the
39        file is found in one of them, no additional directives are needed.
40    'paths' is a list of additional locations to check; if the file is
41        found in one of them, the resulting list will contain the directory.
42    """
43
44    # Check the standard locations
45    for dir in std_dirs:
46        f = os.path.join(dir, filename)
47        if os.path.exists(f): return []
48
49    # Check the additional directories
50    for dir in paths:
51        f = os.path.join(dir, filename)
52        if os.path.exists(f):
53            return [dir]
54
55    # Not found anywhere
56    return None
57
58def find_library_file(compiler, libname, std_dirs, paths):
59    result = compiler.find_library_file(std_dirs + paths, libname)
60    if result is None:
61        return None
62
63    # Check whether the found file is in one of the standard directories
64    dirname = os.path.dirname(result)
65    for p in std_dirs:
66        # Ensure path doesn't end with path separator
67        p = p.rstrip(os.sep)
68        if p == dirname:
69            return [ ]
70
71    # Otherwise, it must have been in one of the additional directories,
72    # so we have to figure out which one.
73    for p in paths:
74        # Ensure path doesn't end with path separator
75        p = p.rstrip(os.sep)
76        if p == dirname:
77            return [p]
78    else:
79        assert False, "Internal error: Path not found in std_dirs or paths"
80
81def module_enabled(extlist, modname):
82    """Returns whether the module 'modname' is present in the list
83    of extensions 'extlist'."""
84    extlist = [ext for ext in extlist if ext.name == modname]
85    return len(extlist)
86
87def find_module_file(module, dirlist):
88    """Find a module in a set of possible folders. If it is not found
89    return the unadorned filename"""
90    list = find_file(module, [], dirlist)
91    if not list:
92        return module
93    if len(list) > 1:
94        log.info("WARNING: multiple copies of %s found"%module)
95    return os.path.join(list[0], module)
96
97class PyBuildExt(build_ext):
98
99    def __init__(self, dist):
100        build_ext.__init__(self, dist)
101        self.failed = []
102
103    def build_extensions(self):
104
105        # Detect which modules should be compiled
106        missing = self.detect_modules()
107
108        # Remove modules that are present on the disabled list
109        extensions = [ext for ext in self.extensions
110                      if ext.name not in disabled_module_list]
111        # move ctypes to the end, it depends on other modules
112        ext_map = dict((ext.name, i) for i, ext in enumerate(extensions))
113        if "_ctypes" in ext_map:
114            ctypes = extensions.pop(ext_map["_ctypes"])
115            extensions.append(ctypes)
116        self.extensions = extensions
117
118        # Fix up the autodetected modules, prefixing all the source files
119        # with Modules/ and adding Python's include directory to the path.
120        (srcdir,) = sysconfig.get_config_vars('srcdir')
121        if not srcdir:
122            # Maybe running on Windows but not using CYGWIN?
123            raise ValueError("No source directory; cannot proceed.")
124        srcdir = os.path.abspath(srcdir)
125        moddirlist = [os.path.join(srcdir, 'Modules')]
126
127        # Platform-dependent module source and include directories
128        incdirlist = []
129        platform = self.get_platform()
130        if platform in ('darwin', 'mac') and ("--disable-toolbox-glue" not in
131            sysconfig.get_config_var("CONFIG_ARGS")):
132            # Mac OS X also includes some mac-specific modules
133            macmoddir = os.path.join(srcdir, 'Mac/Modules')
134            moddirlist.append(macmoddir)
135            incdirlist.append(os.path.join(srcdir, 'Mac/Include'))
136
137        # Fix up the paths for scripts, too
138        self.distribution.scripts = [os.path.join(srcdir, filename)
139                                     for filename in self.distribution.scripts]
140
141        # Python header files
142        headers = [sysconfig.get_config_h_filename()]
143        headers += glob(os.path.join(sysconfig.get_python_inc(), "*.h"))
144        for ext in self.extensions[:]:
145            ext.sources = [ find_module_file(filename, moddirlist)
146                            for filename in ext.sources ]
147            if ext.depends is not None:
148                ext.depends = [find_module_file(filename, moddirlist)
149                               for filename in ext.depends]
150            else:
151                ext.depends = []
152            # re-compile extensions if a header file has been changed
153            ext.depends.extend(headers)
154
155            # platform specific include directories
156            ext.include_dirs.extend(incdirlist)
157
158            # If a module has already been built statically,
159            # don't build it here
160            if ext.name in sys.builtin_module_names:
161                self.extensions.remove(ext)
162
163        if platform != 'mac':
164            # Parse Modules/Setup and Modules/Setup.local to figure out which
165            # modules are turned on in the file.
166            remove_modules = []
167            for filename in ('Modules/Setup', 'Modules/Setup.local'):
168                input = text_file.TextFile(filename, join_lines=1)
169                while 1:
170                    line = input.readline()
171                    if not line: break
172                    line = line.split()
173                    remove_modules.append(line[0])
174                input.close()
175
176            for ext in self.extensions[:]:
177                if ext.name in remove_modules:
178                    self.extensions.remove(ext)
179
180        # When you run "make CC=altcc" or something similar, you really want
181        # those environment variables passed into the setup.py phase.  Here's
182        # a small set of useful ones.
183        compiler = os.environ.get('CC')
184        args = {}
185        # unfortunately, distutils doesn't let us provide separate C and C++
186        # compilers
187        if compiler is not None:
188            (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS')
189            args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags
190        self.compiler_obj.set_executables(**args)
191
192        build_ext.build_extensions(self)
193
194        longest = max([len(e.name) for e in self.extensions])
195        if self.failed:
196            longest = max(longest, max([len(name) for name in self.failed]))
197
198        def print_three_column(lst):
199            lst.sort(key=str.lower)
200            # guarantee zip() doesn't drop anything
201            while len(lst) % 3:
202                lst.append("")
203            for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]):
204                print "%-*s   %-*s   %-*s" % (longest, e, longest, f,
205                                              longest, g)
206
207        if missing:
208            print
209            print ("Python build finished, but the necessary bits to build "
210                   "these modules were not found:")
211            print_three_column(missing)
212            print ("To find the necessary bits, look in setup.py in"
213                   " detect_modules() for the module's name.")
214            print
215
216        if self.failed:
217            failed = self.failed[:]
218            print
219            print "Failed to build these modules:"
220            print_three_column(failed)
221            print
222
223    def build_extension(self, ext):
224
225        if ext.name == '_ctypes':
226            if not self.configure_ctypes(ext):
227                return
228
229        try:
230            build_ext.build_extension(self, ext)
231        except (CCompilerError, DistutilsError), why:
232            self.announce('WARNING: building of extension "%s" failed: %s' %
233                          (ext.name, sys.exc_info()[1]))
234            self.failed.append(ext.name)
235            return
236        # Workaround for Mac OS X: The Carbon-based modules cannot be
237        # reliably imported into a command-line Python
238        if 'Carbon' in ext.extra_link_args:
239            self.announce(
240                'WARNING: skipping import check for Carbon-based "%s"' %
241                ext.name)
242            return
243
244        if self.get_platform() == 'darwin' and (
245                sys.maxint > 2**32 and '-arch' in ext.extra_link_args):
246            # Don't bother doing an import check when an extension was
247            # build with an explicit '-arch' flag on OSX. That's currently
248            # only used to build 32-bit only extensions in a 4-way
249            # universal build and loading 32-bit code into a 64-bit
250            # process will fail.
251            self.announce(
252                'WARNING: skipping import check for "%s"' %
253                ext.name)
254            return
255
256        # Workaround for Cygwin: Cygwin currently has fork issues when many
257        # modules have been imported
258        if self.get_platform() == 'cygwin':
259            self.announce('WARNING: skipping import check for Cygwin-based "%s"'
260                % ext.name)
261            return
262        ext_filename = os.path.join(
263            self.build_lib,
264            self.get_ext_filename(self.get_ext_fullname(ext.name)))
265        try:
266            imp.load_dynamic(ext.name, ext_filename)
267        except ImportError, why:
268            self.failed.append(ext.name)
269            self.announce('*** WARNING: renaming "%s" since importing it'
270                          ' failed: %s' % (ext.name, why), level=3)
271            assert not self.inplace
272            basename, tail = os.path.splitext(ext_filename)
273            newname = basename + "_failed" + tail
274            if os.path.exists(newname):
275                os.remove(newname)
276            os.rename(ext_filename, newname)
277
278            # XXX -- This relies on a Vile HACK in
279            # distutils.command.build_ext.build_extension().  The
280            # _built_objects attribute is stored there strictly for
281            # use here.
282            # If there is a failure, _built_objects may not be there,
283            # so catch the AttributeError and move on.
284            try:
285                for filename in self._built_objects:
286                    os.remove(filename)
287            except AttributeError:
288                self.announce('unable to remove files (ignored)')
289        except:
290            exc_type, why, tb = sys.exc_info()
291            self.announce('*** WARNING: importing extension "%s" '
292                          'failed with %s: %s' % (ext.name, exc_type, why),
293                          level=3)
294            self.failed.append(ext.name)
295
296    def get_platform(self):
297        # Get value of sys.platform
298        for platform in ['cygwin', 'beos', 'darwin', 'atheos', 'osf1']:
299            if sys.platform.startswith(platform):
300                return platform
301        return sys.platform
302
303    def detect_modules(self):
304        # Ensure that /usr/local is always used
305        add_dir_to_list(self.compiler_obj.library_dirs, '/usr/local/lib')
306        add_dir_to_list(self.compiler_obj.include_dirs, '/usr/local/include')
307
308        # Add paths specified in the environment variables LDFLAGS and
309        # CPPFLAGS for header and library files.
310        # We must get the values from the Makefile and not the environment
311        # directly since an inconsistently reproducible issue comes up where
312        # the environment variable is not set even though the value were passed
313        # into configure and stored in the Makefile (issue found on OS X 10.3).
314        for env_var, arg_name, dir_list in (
315                ('LDFLAGS', '-R', self.compiler_obj.runtime_library_dirs),
316                ('LDFLAGS', '-L', self.compiler_obj.library_dirs),
317                ('CPPFLAGS', '-I', self.compiler_obj.include_dirs)):
318            env_val = sysconfig.get_config_var(env_var)
319            if env_val:
320                # To prevent optparse from raising an exception about any
321                # options in env_val that it doesn't know about we strip out
322                # all double dashes and any dashes followed by a character
323                # that is not for the option we are dealing with.
324                #
325                # Please note that order of the regex is important!  We must
326                # strip out double-dashes first so that we don't end up with
327                # substituting "--Long" to "-Long" and thus lead to "ong" being
328                # used for a library directory.
329                env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1],
330                                 ' ', env_val)
331                parser = optparse.OptionParser()
332                # Make sure that allowing args interspersed with options is
333                # allowed
334                parser.allow_interspersed_args = True
335                parser.error = lambda msg: None
336                parser.add_option(arg_name, dest="dirs", action="append")
337                options = parser.parse_args(env_val.split())[0]
338                if options.dirs:
339                    for directory in reversed(options.dirs):
340                        add_dir_to_list(dir_list, directory)
341
342        if os.path.normpath(sys.prefix) != '/usr':
343            add_dir_to_list(self.compiler_obj.library_dirs,
344                            sysconfig.get_config_var("LIBDIR"))
345            add_dir_to_list(self.compiler_obj.include_dirs,
346                            sysconfig.get_config_var("INCLUDEDIR"))
347
348        try:
349            have_unicode = unicode
350        except NameError:
351            have_unicode = 0
352
353        # lib_dirs and inc_dirs are used to search for files;
354        # if a file is found in one of those directories, it can
355        # be assumed that no additional -I,-L directives are needed.
356        lib_dirs = self.compiler_obj.library_dirs + [
357            '/lib64', '/usr/lib64',
358            '/lib', '/usr/lib',
359            ]
360        inc_dirs = self.compiler_obj.include_dirs + ['/usr/include']
361        exts = []
362        missing = []
363
364        config_h = sysconfig.get_config_h_filename()
365        config_h_vars = sysconfig.parse_config_h(open(config_h))
366
367        platform = self.get_platform()
368        srcdir = sysconfig.get_config_var('srcdir')
369
370        # Check for AtheOS which has libraries in non-standard locations
371        if platform == 'atheos':
372            lib_dirs += ['/system/libs', '/atheos/autolnk/lib']
373            lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep)
374            inc_dirs += ['/system/include', '/atheos/autolnk/include']
375            inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep)
376
377        # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
378        if platform in ['osf1', 'unixware7', 'openunix8']:
379            lib_dirs += ['/usr/ccs/lib']
380
381        if platform == 'darwin':
382            # This should work on any unixy platform ;-)
383            # If the user has bothered specifying additional -I and -L flags
384            # in OPT and LDFLAGS we might as well use them here.
385            #   NOTE: using shlex.split would technically be more correct, but
386            # also gives a bootstrap problem. Let's hope nobody uses directories
387            # with whitespace in the name to store libraries.
388            cflags, ldflags = sysconfig.get_config_vars(
389                    'CFLAGS', 'LDFLAGS')
390            for item in cflags.split():
391                if item.startswith('-I'):
392                    inc_dirs.append(item[2:])
393
394            for item in ldflags.split():
395                if item.startswith('-L'):
396                    lib_dirs.append(item[2:])
397
398        # Check for MacOS X, which doesn't need libm.a at all
399        math_libs = ['m']
400        if platform in ['darwin', 'beos', 'mac']:
401            math_libs = []
402
403        # XXX Omitted modules: gl, pure, dl, SGI-specific modules
404
405        #
406        # The following modules are all pretty straightforward, and compile
407        # on pretty much any POSIXish platform.
408        #
409
410        # Some modules that are normally always on:
411        exts.append( Extension('_weakref', ['_weakref.c']) )
412
413        # array objects
414        exts.append( Extension('array', ['arraymodule.c']) )
415        # complex math library functions
416        exts.append( Extension('cmath', ['cmathmodule.c', '_math.c'],
417                               depends=['_math.h'],
418                               libraries=math_libs) )
419        # math library functions, e.g. sin()
420        exts.append( Extension('math',  ['mathmodule.c', '_math.c'],
421                               depends=['_math.h'],
422                               libraries=math_libs) )
423        # fast string operations implemented in C
424        exts.append( Extension('strop', ['stropmodule.c']) )
425        # time operations and variables
426        exts.append( Extension('time', ['timemodule.c'],
427                               libraries=math_libs) )
428        exts.append( Extension('datetime', ['datetimemodule.c', 'timemodule.c'],
429                               libraries=math_libs) )
430        # fast iterator tools implemented in C
431        exts.append( Extension("itertools", ["itertoolsmodule.c"]) )
432        # code that will be builtins in the future, but conflict with the
433        #  current builtins
434        exts.append( Extension('future_builtins', ['future_builtins.c']) )
435        # random number generator implemented in C
436        exts.append( Extension("_random", ["_randommodule.c"]) )
437        # high-performance collections
438        exts.append( Extension("_collections", ["_collectionsmodule.c"]) )
439        # bisect
440        exts.append( Extension("_bisect", ["_bisectmodule.c"]) )
441        # heapq
442        exts.append( Extension("_heapq", ["_heapqmodule.c"]) )
443        # operator.add() and similar goodies
444        exts.append( Extension('operator', ['operator.c']) )
445        # Python 3.1 _io library
446        exts.append( Extension("_io",
447            ["_io/bufferedio.c", "_io/bytesio.c", "_io/fileio.c",
448             "_io/iobase.c", "_io/_iomodule.c", "_io/stringio.c", "_io/textio.c"],
449             depends=["_io/_iomodule.h"], include_dirs=["Modules/_io"]))
450        # _functools
451        exts.append( Extension("_functools", ["_functoolsmodule.c"]) )
452        # _json speedups
453        exts.append( Extension("_json", ["_json.c"]) )
454        # Python C API test module
455        exts.append( Extension('_testcapi', ['_testcapimodule.c'],
456                               depends=['testcapi_long.h']) )
457        # profilers (_lsprof is for cProfile.py)
458        exts.append( Extension('_hotshot', ['_hotshot.c']) )
459        exts.append( Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c']) )
460        # static Unicode character database
461        if have_unicode:
462            exts.append( Extension('unicodedata', ['unicodedata.c']) )
463        else:
464            missing.append('unicodedata')
465        # access to ISO C locale support
466        data = open('pyconfig.h').read()
467        m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data)
468        if m is not None:
469            locale_libs = ['intl']
470        else:
471            locale_libs = []
472        if platform == 'darwin':
473            locale_extra_link_args = ['-framework', 'CoreFoundation']
474        else:
475            locale_extra_link_args = []
476
477
478        exts.append( Extension('_locale', ['_localemodule.c'],
479                               libraries=locale_libs,
480                               extra_link_args=locale_extra_link_args) )
481
482        # Modules with some UNIX dependencies -- on by default:
483        # (If you have a really backward UNIX, select and socket may not be
484        # supported...)
485
486        # fcntl(2) and ioctl(2)
487        exts.append( Extension('fcntl', ['fcntlmodule.c']) )
488        if platform not in ['mac']:
489            # pwd(3)
490            exts.append( Extension('pwd', ['pwdmodule.c']) )
491            # grp(3)
492            exts.append( Extension('grp', ['grpmodule.c']) )
493            # spwd, shadow passwords
494            if (config_h_vars.get('HAVE_GETSPNAM', False) or
495                    config_h_vars.get('HAVE_GETSPENT', False)):
496                exts.append( Extension('spwd', ['spwdmodule.c']) )
497            else:
498                missing.append('spwd')
499        else:
500            missing.extend(['pwd', 'grp', 'spwd'])
501
502        # select(2); not on ancient System V
503        exts.append( Extension('select', ['selectmodule.c']) )
504
505        # Fred Drake's interface to the Python parser
506        exts.append( Extension('parser', ['parsermodule.c']) )
507
508        # cStringIO and cPickle
509        exts.append( Extension('cStringIO', ['cStringIO.c']) )
510        exts.append( Extension('cPickle', ['cPickle.c']) )
511
512        # Memory-mapped files (also works on Win32).
513        if platform not in ['atheos', 'mac']:
514            exts.append( Extension('mmap', ['mmapmodule.c']) )
515        else:
516            missing.append('mmap')
517
518        # Lance Ellinghaus's syslog module
519        if platform not in ['mac']:
520            # syslog daemon interface
521            exts.append( Extension('syslog', ['syslogmodule.c']) )
522        else:
523            missing.append('syslog')
524
525        # George Neville-Neil's timing module:
526        # Deprecated in PEP 4 http://www.python.org/peps/pep-0004.html
527        # http://mail.python.org/pipermail/python-dev/2006-January/060023.html
528        #exts.append( Extension('timing', ['timingmodule.c']) )
529
530        #
531        # Here ends the simple stuff.  From here on, modules need certain
532        # libraries, are platform-specific, or present other surprises.
533        #
534
535        # Multimedia modules
536        # These don't work for 64-bit platforms!!!
537        # These represent audio samples or images as strings:
538
539        # Operations on audio samples
540        # According to #993173, this one should actually work fine on
541        # 64-bit platforms.
542        exts.append( Extension('audioop', ['audioop.c']) )
543
544        # Disabled on 64-bit platforms
545        if sys.maxint != 9223372036854775807L:
546            # Operations on images
547            exts.append( Extension('imageop', ['imageop.c']) )
548        else:
549            missing.extend(['imageop'])
550
551        # readline
552        do_readline = self.compiler_obj.find_library_file(lib_dirs, 'readline')
553        if platform == 'darwin':
554            os_release = int(os.uname()[2].split('.')[0])
555            if os_release < 9:
556                # MacOSX 10.4 has a broken readline. Don't try to build
557                # the readline module unless the user has installed a fixed
558                # readline package
559                if find_file('readline/rlconf.h', inc_dirs, []) is None:
560                    do_readline = False
561        if do_readline:
562            if platform == 'darwin' and os_release < 9:
563                # In every directory on the search path search for a dynamic
564                # library and then a static library, instead of first looking
565                # for dynamic libraries on the entiry path.
566                # This way a staticly linked custom readline gets picked up
567                # before the (broken) dynamic library in /usr/lib.
568                readline_extra_link_args = ('-Wl,-search_paths_first',)
569            else:
570                readline_extra_link_args = ()
571
572            readline_libs = ['readline']
573            if self.compiler_obj.find_library_file(lib_dirs,
574                                                   'ncursesw'):
575                readline_libs.append('ncursesw')
576            elif self.compiler_obj.find_library_file(lib_dirs,
577                                                     'ncurses'):
578                readline_libs.append('ncurses')
579            elif self.compiler_obj.find_library_file(lib_dirs, 'curses'):
580                readline_libs.append('curses')
581            elif self.compiler_obj.find_library_file(lib_dirs +
582                                                     ['/usr/lib/termcap'],
583                                                     'termcap'):
584                readline_libs.append('termcap')
585            exts.append( Extension('readline', ['readline.c'],
586                                   library_dirs=['/usr/lib/termcap'],
587                                   extra_link_args=readline_extra_link_args,
588                                   libraries=readline_libs) )
589        else:
590            missing.append('readline')
591
592        if platform not in ['mac']:
593            # crypt module.
594
595            if self.compiler_obj.find_library_file(lib_dirs, 'crypt'):
596                libs = ['crypt']
597            else:
598                libs = []
599            exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) )
600        else:
601            missing.append('crypt')
602
603        # CSV files
604        exts.append( Extension('_csv', ['_csv.c']) )
605
606        # socket(2)
607        exts.append( Extension('_socket', ['socketmodule.c'],
608                               depends = ['socketmodule.h']) )
609        # Detect SSL support for the socket module (via _ssl)
610        search_for_ssl_incs_in = [
611                              '/usr/local/ssl/include',
612                              '/usr/contrib/ssl/include/'
613                             ]
614        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
615                             search_for_ssl_incs_in
616                             )
617        if ssl_incs is not None:
618            krb5_h = find_file('krb5.h', inc_dirs,
619                               ['/usr/kerberos/include'])
620            if krb5_h:
621                ssl_incs += krb5_h
622        ssl_libs = find_library_file(self.compiler_obj, 'ssl',lib_dirs,
623                                     ['/usr/local/ssl/lib',
624                                      '/usr/contrib/ssl/lib/'
625                                     ] )
626
627        if (ssl_incs is not None and
628            ssl_libs is not None):
629            exts.append( Extension('_ssl', ['_ssl.c'],
630                                   include_dirs = ssl_incs,
631                                   library_dirs = ssl_libs,
632                                   libraries = ['ssl', 'crypto'],
633                                   depends = ['socketmodule.h']), )
634        else:
635            missing.append('_ssl')
636
637        # find out which version of OpenSSL we have
638        openssl_ver = 0
639        openssl_ver_re = re.compile(
640            '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' )
641        for ssl_inc_dir in inc_dirs + search_for_ssl_incs_in:
642            name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h')
643            if os.path.isfile(name):
644                try:
645                    incfile = open(name, 'r')
646                    for line in incfile:
647                        m = openssl_ver_re.match(line)
648                        if m:
649                            openssl_ver = eval(m.group(1))
650                            break
651                except IOError:
652                    pass
653
654            # first version found is what we'll use (as the compiler should)
655            if openssl_ver:
656                break
657
658        #print 'openssl_ver = 0x%08x' % openssl_ver
659        min_openssl_ver = 0x00907000
660        have_any_openssl = ssl_incs is not None and ssl_libs is not None
661        have_usable_openssl = (have_any_openssl and
662                               openssl_ver >= min_openssl_ver)
663
664        if have_any_openssl:
665            if have_usable_openssl:
666                # The _hashlib module wraps optimized implementations
667                # of hash functions from the OpenSSL library.
668                exts.append( Extension('_hashlib', ['_hashopenssl.c'],
669                                       include_dirs = ssl_incs,
670                                       library_dirs = ssl_libs,
671                                       libraries = ['ssl', 'crypto']) )
672            else:
673                print ("warning: openssl 0x%08x is too old for _hashlib" %
674                       openssl_ver)
675                missing.append('_hashlib')
676        if COMPILED_WITH_PYDEBUG or not have_usable_openssl:
677            # The _sha module implements the SHA1 hash algorithm.
678            exts.append( Extension('_sha', ['shamodule.c']) )
679            # The _md5 module implements the RSA Data Security, Inc. MD5
680            # Message-Digest Algorithm, described in RFC 1321.  The
681            # necessary files md5.c and md5.h are included here.
682            exts.append( Extension('_md5',
683                            sources = ['md5module.c', 'md5.c'],
684                            depends = ['md5.h']) )
685
686        min_sha2_openssl_ver = 0x00908000
687        if COMPILED_WITH_PYDEBUG or openssl_ver < min_sha2_openssl_ver:
688            # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash
689            exts.append( Extension('_sha256', ['sha256module.c']) )
690            exts.append( Extension('_sha512', ['sha512module.c']) )
691
692        # Modules that provide persistent dictionary-like semantics.  You will
693        # probably want to arrange for at least one of them to be available on
694        # your machine, though none are defined by default because of library
695        # dependencies.  The Python module anydbm.py provides an
696        # implementation independent wrapper for these; dumbdbm.py provides
697        # similar functionality (but slower of course) implemented in Python.
698
699        # Sleepycat^WOracle Berkeley DB interface.
700        #  http://www.oracle.com/database/berkeley-db/db/index.html
701        #
702        # This requires the Sleepycat^WOracle DB code. The supported versions
703        # are set below.  Visit the URL above to download
704        # a release.  Most open source OSes come with one or more
705        # versions of BerkeleyDB already installed.
706
707        max_db_ver = (4, 7)
708        min_db_ver = (3, 3)
709        db_setup_debug = False   # verbose debug prints from this script?
710
711        def allow_db_ver(db_ver):
712            """Returns a boolean if the given BerkeleyDB version is acceptable.
713
714            Args:
715              db_ver: A tuple of the version to verify.
716            """
717            if not (min_db_ver <= db_ver <= max_db_ver):
718                return False
719            # Use this function to filter out known bad configurations.
720            if (4, 6) == db_ver[:2]:
721                # BerkeleyDB 4.6.x is not stable on many architectures.
722                arch = platform_machine()
723                if arch not in ('i386', 'i486', 'i586', 'i686',
724                                'x86_64', 'ia64'):
725                    return False
726            return True
727
728        def gen_db_minor_ver_nums(major):
729            if major == 4:
730                for x in range(max_db_ver[1]+1):
731                    if allow_db_ver((4, x)):
732                        yield x
733            elif major == 3:
734                for x in (3,):
735                    if allow_db_ver((3, x)):
736                        yield x
737            else:
738                raise ValueError("unknown major BerkeleyDB version", major)
739
740        # construct a list of paths to look for the header file in on
741        # top of the normal inc_dirs.
742        db_inc_paths = [
743            '/usr/include/db4',
744            '/usr/local/include/db4',
745            '/opt/sfw/include/db4',
746            '/usr/include/db3',
747            '/usr/local/include/db3',
748            '/opt/sfw/include/db3',
749            # Fink defaults (http://fink.sourceforge.net/)
750            '/sw/include/db4',
751            '/sw/include/db3',
752        ]
753        # 4.x minor number specific paths
754        for x in gen_db_minor_ver_nums(4):
755            db_inc_paths.append('/usr/include/db4%d' % x)
756            db_inc_paths.append('/usr/include/db4.%d' % x)
757            db_inc_paths.append('/usr/local/BerkeleyDB.4.%d/include' % x)
758            db_inc_paths.append('/usr/local/include/db4%d' % x)
759            db_inc_paths.append('/pkg/db-4.%d/include' % x)
760            db_inc_paths.append('/opt/db-4.%d/include' % x)
761            # MacPorts default (http://www.macports.org/)
762            db_inc_paths.append('/opt/local/include/db4%d' % x)
763        # 3.x minor number specific paths
764        for x in gen_db_minor_ver_nums(3):
765            db_inc_paths.append('/usr/include/db3%d' % x)
766            db_inc_paths.append('/usr/local/BerkeleyDB.3.%d/include' % x)
767            db_inc_paths.append('/usr/local/include/db3%d' % x)
768            db_inc_paths.append('/pkg/db-3.%d/include' % x)
769            db_inc_paths.append('/opt/db-3.%d/include' % x)
770
771        # Add some common subdirectories for Sleepycat DB to the list,
772        # based on the standard include directories. This way DB3/4 gets
773        # picked up when it is installed in a non-standard prefix and
774        # the user has added that prefix into inc_dirs.
775        std_variants = []
776        for dn in inc_dirs:
777            std_variants.append(os.path.join(dn, 'db3'))
778            std_variants.append(os.path.join(dn, 'db4'))
779            for x in gen_db_minor_ver_nums(4):
780                std_variants.append(os.path.join(dn, "db4%d"%x))
781                std_variants.append(os.path.join(dn, "db4.%d"%x))
782            for x in gen_db_minor_ver_nums(3):
783                std_variants.append(os.path.join(dn, "db3%d"%x))
784                std_variants.append(os.path.join(dn, "db3.%d"%x))
785
786        db_inc_paths = std_variants + db_inc_paths
787        db_inc_paths = [p for p in db_inc_paths if os.path.exists(p)]
788
789        db_ver_inc_map = {}
790
791        class db_found(Exception): pass
792        try:
793            # See whether there is a Sleepycat header in the standard
794            # search path.
795            for d in inc_dirs + db_inc_paths:
796                f = os.path.join(d, "db.h")
797                if db_setup_debug: print "db: looking for db.h in", f
798                if os.path.exists(f):
799                    f = open(f).read()
800                    m = re.search(r"#define\WDB_VERSION_MAJOR\W(\d+)", f)
801                    if m:
802                        db_major = int(m.group(1))
803                        m = re.search(r"#define\WDB_VERSION_MINOR\W(\d+)", f)
804                        db_minor = int(m.group(1))
805                        db_ver = (db_major, db_minor)
806
807                        # Avoid 4.6 prior to 4.6.21 due to a BerkeleyDB bug
808                        if db_ver == (4, 6):
809                            m = re.search(r"#define\WDB_VERSION_PATCH\W(\d+)", f)
810                            db_patch = int(m.group(1))
811                            if db_patch < 21:
812                                print "db.h:", db_ver, "patch", db_patch,
813                                print "being ignored (4.6.x must be >= 4.6.21)"
814                                continue
815
816                        if ( (not db_ver_inc_map.has_key(db_ver)) and
817                            allow_db_ver(db_ver) ):
818                            # save the include directory with the db.h version
819                            # (first occurrence only)
820                            db_ver_inc_map[db_ver] = d
821                            if db_setup_debug:
822                                print "db.h: found", db_ver, "in", d
823                        else:
824                            # we already found a header for this library version
825                            if db_setup_debug: print "db.h: ignoring", d
826                    else:
827                        # ignore this header, it didn't contain a version number
828                        if db_setup_debug:
829                            print "db.h: no version number version in", d
830
831            db_found_vers = db_ver_inc_map.keys()
832            db_found_vers.sort()
833
834            while db_found_vers:
835                db_ver = db_found_vers.pop()
836                db_incdir = db_ver_inc_map[db_ver]
837
838                # check lib directories parallel to the location of the header
839                db_dirs_to_check = [
840                    db_incdir.replace("include", 'lib64'),
841                    db_incdir.replace("include", 'lib'),
842                ]
843                db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check)
844
845                # Look for a version specific db-X.Y before an ambiguoius dbX
846                # XXX should we -ever- look for a dbX name?  Do any
847                # systems really not name their library by version and
848                # symlink to more general names?
849                for dblib in (('db-%d.%d' % db_ver),
850                              ('db%d%d' % db_ver),
851                              ('db%d' % db_ver[0])):
852                    dblib_file = self.compiler_obj.find_library_file(
853                                    db_dirs_to_check + lib_dirs, dblib )
854                    if dblib_file:
855                        dblib_dir = [ os.path.abspath(os.path.dirname(dblib_file)) ]
856                        raise db_found
857                    else:
858                        if db_setup_debug: print "db lib: ", dblib, "not found"
859
860        except db_found:
861            if db_setup_debug:
862                print "bsddb using BerkeleyDB lib:", db_ver, dblib
863                print "bsddb lib dir:", dblib_dir, " inc dir:", db_incdir
864            db_incs = [db_incdir]
865            dblibs = [dblib]
866            # We add the runtime_library_dirs argument because the
867            # BerkeleyDB lib we're linking against often isn't in the
868            # system dynamic library search path.  This is usually
869            # correct and most trouble free, but may cause problems in
870            # some unusual system configurations (e.g. the directory
871            # is on an NFS server that goes away).
872            exts.append(Extension('_bsddb', ['_bsddb.c'],
873                                  depends = ['bsddb.h'],
874                                  library_dirs=dblib_dir,
875                                  runtime_library_dirs=dblib_dir,
876                                  include_dirs=db_incs,
877                                  libraries=dblibs))
878        else:
879            if db_setup_debug: print "db: no appropriate library found"
880            db_incs = None
881            dblibs = []
882            dblib_dir = None
883            missing.append('_bsddb')
884
885        # The sqlite interface
886        sqlite_setup_debug = False   # verbose debug prints from this script?
887
888        # We hunt for #define SQLITE_VERSION "n.n.n"
889        # We need to find >= sqlite version 3.0.8
890        sqlite_incdir = sqlite_libdir = None
891        sqlite_inc_paths = [ '/usr/include',
892                             '/usr/include/sqlite',
893                             '/usr/include/sqlite3',
894                             '/usr/local/include',
895                             '/usr/local/include/sqlite',
896                             '/usr/local/include/sqlite3',
897                           ]
898        MIN_SQLITE_VERSION_NUMBER = (3, 0, 8)
899        MIN_SQLITE_VERSION = ".".join([str(x)
900                                    for x in MIN_SQLITE_VERSION_NUMBER])
901
902        # Scan the default include directories before the SQLite specific
903        # ones. This allows one to override the copy of sqlite on OSX,
904        # where /usr/include contains an old version of sqlite.
905        for d in inc_dirs + sqlite_inc_paths:
906            f = os.path.join(d, "sqlite3.h")
907            if os.path.exists(f):
908                if sqlite_setup_debug: print "sqlite: found %s"%f
909                incf = open(f).read()
910                m = re.search(
911                    r'\s*.*#\s*.*define\s.*SQLITE_VERSION\W*"(.*)"', incf)
912                if m:
913                    sqlite_version = m.group(1)
914                    sqlite_version_tuple = tuple([int(x)
915                                        for x in sqlite_version.split(".")])
916                    if sqlite_version_tuple >= MIN_SQLITE_VERSION_NUMBER:
917                        # we win!
918                        if sqlite_setup_debug:
919                            print "%s/sqlite3.h: version %s"%(d, sqlite_version)
920                        sqlite_incdir = d
921                        break
922                    else:
923                        if sqlite_setup_debug:
924                            print "%s: version %d is too old, need >= %s"%(d,
925                                        sqlite_version, MIN_SQLITE_VERSION)
926                elif sqlite_setup_debug:
927                    print "sqlite: %s had no SQLITE_VERSION"%(f,)
928
929        if sqlite_incdir:
930            sqlite_dirs_to_check = [
931                os.path.join(sqlite_incdir, '..', 'lib64'),
932                os.path.join(sqlite_incdir, '..', 'lib'),
933                os.path.join(sqlite_incdir, '..', '..', 'lib64'),
934                os.path.join(sqlite_incdir, '..', '..', 'lib'),
935            ]
936            sqlite_libfile = self.compiler_obj.find_library_file(
937                                sqlite_dirs_to_check + lib_dirs, 'sqlite3')
938            if sqlite_libfile:
939                sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))]
940
941        if sqlite_incdir and sqlite_libdir:
942            sqlite_srcs = ['_sqlite/cache.c',
943                '_sqlite/connection.c',
944                '_sqlite/cursor.c',
945                '_sqlite/microprotocols.c',
946                '_sqlite/module.c',
947                '_sqlite/prepare_protocol.c',
948                '_sqlite/row.c',
949                '_sqlite/statement.c',
950                '_sqlite/util.c', ]
951
952            sqlite_defines = []
953            if sys.platform != "win32":
954                sqlite_defines.append(('MODULE_NAME', '"sqlite3"'))
955            else:
956                sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"'))
957
958
959            if sys.platform == 'darwin':
960                # In every directory on the search path search for a dynamic
961                # library and then a static library, instead of first looking
962                # for dynamic libraries on the entiry path.
963                # This way a staticly linked custom sqlite gets picked up
964                # before the dynamic library in /usr/lib.
965                sqlite_extra_link_args = ('-Wl,-search_paths_first',)
966            else:
967                sqlite_extra_link_args = ()
968
969            exts.append(Extension('_sqlite3', sqlite_srcs,
970                                  define_macros=sqlite_defines,
971                                  include_dirs=["Modules/_sqlite",
972                                                sqlite_incdir],
973                                  library_dirs=sqlite_libdir,
974                                  runtime_library_dirs=sqlite_libdir,
975                                  extra_link_args=sqlite_extra_link_args,
976                                  libraries=["sqlite3",]))
977        else:
978            missing.append('_sqlite3')
979
980        # Look for Berkeley db 1.85.   Note that it is built as a different
981        # module name so it can be included even when later versions are
982        # available.  A very restrictive search is performed to avoid
983        # accidentally building this module with a later version of the
984        # underlying db library.  May BSD-ish Unixes incorporate db 1.85
985        # symbols into libc and place the include file in /usr/include.
986        #
987        # If the better bsddb library can be built (db_incs is defined)
988        # we do not build this one.  Otherwise this build will pick up
989        # the more recent berkeleydb's db.h file first in the include path
990        # when attempting to compile and it will fail.
991        f = "/usr/include/db.h"
992        if os.path.exists(f) and not db_incs:
993            data = open(f).read()
994            m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data)
995            if m is not None:
996                # bingo - old version used hash file format version 2
997                ### XXX this should be fixed to not be platform-dependent
998                ### but I don't have direct access to an osf1 platform and
999                ### seemed to be muffing the search somehow
1000                libraries = platform == "osf1" and ['db'] or None
1001                if libraries is not None:
1002                    exts.append(Extension('bsddb185', ['bsddbmodule.c'],
1003                                          libraries=libraries))
1004                else:
1005                    exts.append(Extension('bsddb185', ['bsddbmodule.c']))
1006            else:
1007                missing.append('bsddb185')
1008        else:
1009            missing.append('bsddb185')
1010
1011        dbm_order = ['gdbm']
1012        # The standard Unix dbm module:
1013        if platform not in ['cygwin']:
1014            config_args = [arg.strip("'")
1015                           for arg in sysconfig.get_config_var("CONFIG_ARGS").split()]
1016            dbm_args = [arg for arg in config_args
1017                        if arg.startswith('--with-dbmliborder=')]
1018            if dbm_args:
1019                dbm_order = [arg.split('=')[-1] for arg in dbm_args][-1].split(":")
1020            else:
1021                dbm_order = "ndbm:gdbm:bdb".split(":")
1022            dbmext = None
1023            for cand in dbm_order:
1024                if cand == "ndbm":
1025                    if find_file("ndbm.h", inc_dirs, []) is not None:
1026                        # Some systems have -lndbm, others don't
1027                        if self.compiler_obj.find_library_file(lib_dirs,
1028                                                               'ndbm'):
1029                            ndbm_libs = ['ndbm']
1030                        else:
1031                            ndbm_libs = []
1032                        print "building dbm using ndbm"
1033                        dbmext = Extension('dbm', ['dbmmodule.c'],
1034                                           define_macros=[
1035                                               ('HAVE_NDBM_H',None),
1036                                               ],
1037                                           libraries=ndbm_libs)
1038                        break
1039
1040                elif cand == "gdbm":
1041                    if self.compiler_obj.find_library_file(lib_dirs, 'gdbm'):
1042                        gdbm_libs = ['gdbm']
1043                        if self.compiler_obj.find_library_file(lib_dirs,
1044                                                               'gdbm_compat'):
1045                            gdbm_libs.append('gdbm_compat')
1046                        if find_file("gdbm/ndbm.h", inc_dirs, []) is not None:
1047                            print "building dbm using gdbm"
1048                            dbmext = Extension(
1049                                'dbm', ['dbmmodule.c'],
1050                                define_macros=[
1051                                    ('HAVE_GDBM_NDBM_H', None),
1052                                    ],
1053                                libraries = gdbm_libs)
1054                            break
1055                        if find_file("gdbm-ndbm.h", inc_dirs, []) is not None:
1056                            print "building dbm using gdbm"
1057                            dbmext = Extension(
1058                                'dbm', ['dbmmodule.c'],
1059                                define_macros=[
1060                                    ('HAVE_GDBM_DASH_NDBM_H', None),
1061                                    ],
1062                                libraries = gdbm_libs)
1063                            break
1064                elif cand == "bdb":
1065                    if db_incs is not None:
1066                        print "building dbm using bdb"
1067                        dbmext = Extension('dbm', ['dbmmodule.c'],
1068                                           library_dirs=dblib_dir,
1069                                           runtime_library_dirs=dblib_dir,
1070                                           include_dirs=db_incs,
1071                                           define_macros=[
1072                                               ('HAVE_BERKDB_H', None),
1073                                               ('DB_DBM_HSEARCH', None),
1074                                               ],
1075                                           libraries=dblibs)
1076                        break
1077            if dbmext is not None:
1078                exts.append(dbmext)
1079            else:
1080                missing.append('dbm')
1081
1082        # Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:
1083        if ('gdbm' in dbm_order and
1084            self.compiler_obj.find_library_file(lib_dirs, 'gdbm')):
1085            exts.append( Extension('gdbm', ['gdbmmodule.c'],
1086                                   libraries = ['gdbm'] ) )
1087        else:
1088            missing.append('gdbm')
1089
1090        # Unix-only modules
1091        if platform not in ['mac', 'win32']:
1092            # Steen Lumholt's termios module
1093            exts.append( Extension('termios', ['termios.c']) )
1094            # Jeremy Hylton's rlimit interface
1095            if platform not in ['atheos']:
1096                exts.append( Extension('resource', ['resource.c']) )
1097            else:
1098                missing.append('resource')
1099
1100            # Sun yellow pages. Some systems have the functions in libc.
1101            if (platform not in ['cygwin', 'atheos', 'qnx6'] and
1102                find_file('rpcsvc/yp_prot.h', inc_dirs, []) is not None):
1103                if (self.compiler_obj.find_library_file(lib_dirs, 'nsl')):
1104                    libs = ['nsl']
1105                else:
1106                    libs = []
1107                exts.append( Extension('nis', ['nismodule.c'],
1108                                       libraries = libs) )
1109            else:
1110                missing.append('nis')
1111        else:
1112            missing.extend(['nis', 'resource', 'termios'])
1113
1114        # Curses support, requiring the System V version of curses, often
1115        # provided by the ncurses library.
1116        panel_library = 'panel'
1117        if (self.compiler_obj.find_library_file(lib_dirs, 'ncursesw')):
1118            curses_libs = ['ncursesw']
1119            # Bug 1464056: If _curses.so links with ncursesw,
1120            # _curses_panel.so must link with panelw.
1121            panel_library = 'panelw'
1122            exts.append( Extension('_curses', ['_cursesmodule.c'],
1123                                   libraries = curses_libs) )
1124        elif (self.compiler_obj.find_library_file(lib_dirs, 'ncurses')):
1125            curses_libs = ['ncurses']
1126            exts.append( Extension('_curses', ['_cursesmodule.c'],
1127                                   libraries = curses_libs) )
1128        elif (self.compiler_obj.find_library_file(lib_dirs, 'curses')
1129              and platform != 'darwin'):
1130                # OSX has an old Berkeley curses, not good enough for
1131                # the _curses module.
1132            if (self.compiler_obj.find_library_file(lib_dirs, 'terminfo')):
1133                curses_libs = ['curses', 'terminfo']
1134            elif (self.compiler_obj.find_library_file(lib_dirs, 'termcap')):
1135                curses_libs = ['curses', 'termcap']
1136            else:
1137                curses_libs = ['curses']
1138
1139            exts.append( Extension('_curses', ['_cursesmodule.c'],
1140                                   libraries = curses_libs) )
1141        else:
1142            missing.append('_curses')
1143
1144        # If the curses module is enabled, check for the panel module
1145        if (module_enabled(exts, '_curses') and
1146            self.compiler_obj.find_library_file(lib_dirs, panel_library)):
1147            exts.append( Extension('_curses_panel', ['_curses_panel.c'],
1148                                   libraries = [panel_library] + curses_libs) )
1149        else:
1150            missing.append('_curses_panel')
1151
1152        # Andrew Kuchling's zlib module.  Note that some versions of zlib
1153        # 1.1.3 have security problems.  See CERT Advisory CA-2002-07:
1154        # http://www.cert.org/advisories/CA-2002-07.html
1155        #
1156        # zlib 1.1.4 is fixed, but at least one vendor (RedHat) has decided to
1157        # patch its zlib 1.1.3 package instead of upgrading to 1.1.4.  For
1158        # now, we still accept 1.1.3, because we think it's difficult to
1159        # exploit this in Python, and we'd rather make it RedHat's problem
1160        # than our problem <wink>.
1161        #
1162        # You can upgrade zlib to version 1.1.4 yourself by going to
1163        # http://www.gzip.org/zlib/
1164        zlib_inc = find_file('zlib.h', [], inc_dirs)
1165        have_zlib = False
1166        if zlib_inc is not None:
1167            zlib_h = zlib_inc[0] + '/zlib.h'
1168            version = '"0.0.0"'
1169            version_req = '"1.1.3"'
1170            fp = open(zlib_h)
1171            while 1:
1172                line = fp.readline()
1173                if not line:
1174                    break
1175                if line.startswith('#define ZLIB_VERSION'):
1176                    version = line.split()[2]
1177                    break
1178            if version >= version_req:
1179                if (self.compiler_obj.find_library_file(lib_dirs, 'z')):
1180                    if sys.platform == "darwin":
1181                        zlib_extra_link_args = ('-Wl,-search_paths_first',)
1182                    else:
1183                        zlib_extra_link_args = ()
1184                    exts.append( Extension('zlib', ['zlibmodule.c'],
1185                                           libraries = ['z'],
1186                                           extra_link_args = zlib_extra_link_args))
1187                    have_zlib = True
1188                else:
1189                    missing.append('zlib')
1190            else:
1191                missing.append('zlib')
1192        else:
1193            missing.append('zlib')
1194
1195        # Helper module for various ascii-encoders.  Uses zlib for an optimized
1196        # crc32 if we have it.  Otherwise binascii uses its own.
1197        if have_zlib:
1198            extra_compile_args = ['-DUSE_ZLIB_CRC32']
1199            libraries = ['z']
1200            extra_link_args = zlib_extra_link_args
1201        else:
1202            extra_compile_args = []
1203            libraries = []
1204            extra_link_args = []
1205        exts.append( Extension('binascii', ['binascii.c'],
1206                               extra_compile_args = extra_compile_args,
1207                               libraries = libraries,
1208                               extra_link_args = extra_link_args) )
1209
1210        # Gustavo Niemeyer's bz2 module.
1211        if (self.compiler_obj.find_library_file(lib_dirs, 'bz2')):
1212            if sys.platform == "darwin":
1213                bz2_extra_link_args = ('-Wl,-search_paths_first',)
1214            else:
1215                bz2_extra_link_args = ()
1216            exts.append( Extension('bz2', ['bz2module.c'],
1217                                   libraries = ['bz2'],
1218                                   extra_link_args = bz2_extra_link_args) )
1219        else:
1220            missing.append('bz2')
1221
1222        # Interface to the Expat XML parser
1223        #
1224        # Expat was written by James Clark and is now maintained by a group of
1225        # developers on SourceForge; see www.libexpat.org for more information.
1226        # The pyexpat module was written by Paul Prescod after a prototype by
1227        # Jack Jansen.  The Expat source is included in Modules/expat/.  Usage
1228        # of a system shared libexpat.so is possible with --with-system-expat
1229        # cofigure option.
1230        #
1231        # More information on Expat can be found at www.libexpat.org.
1232        #
1233        if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"):
1234            expat_inc = []
1235            define_macros = []
1236            expat_lib = ['expat']
1237            expat_sources = []
1238        else:
1239            expat_inc = [os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')]
1240            define_macros = [
1241                ('HAVE_EXPAT_CONFIG_H', '1'),
1242            ]
1243            expat_lib = []
1244            expat_sources = ['expat/xmlparse.c',
1245                             'expat/xmlrole.c',
1246                             'expat/xmltok.c']
1247
1248        exts.append(Extension('pyexpat',
1249                              define_macros = define_macros,
1250                              include_dirs = expat_inc,
1251                              libraries = expat_lib,
1252                              sources = ['pyexpat.c'] + expat_sources
1253                              ))
1254
1255        # Fredrik Lundh's cElementTree module.  Note that this also
1256        # uses expat (via the CAPI hook in pyexpat).
1257
1258        if os.path.isfile(os.path.join(srcdir, 'Modules', '_elementtree.c')):
1259            define_macros.append(('USE_PYEXPAT_CAPI', None))
1260            exts.append(Extension('_elementtree',
1261                                  define_macros = define_macros,
1262                                  include_dirs = expat_inc,
1263                                  libraries = expat_lib,
1264                                  sources = ['_elementtree.c'],
1265                                  ))
1266        else:
1267            missing.append('_elementtree')
1268
1269        # Hye-Shik Chang's CJKCodecs modules.
1270        if have_unicode:
1271            exts.append(Extension('_multibytecodec',
1272                                  ['cjkcodecs/multibytecodec.c']))
1273            for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'):
1274                exts.append(Extension('_codecs_%s' % loc,
1275                                      ['cjkcodecs/_codecs_%s.c' % loc]))
1276        else:
1277            missing.append('_multibytecodec')
1278            for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'):
1279                missing.append('_codecs_%s' % loc)
1280
1281        # Dynamic loading module
1282        if sys.maxint == 0x7fffffff:
1283            # This requires sizeof(int) == sizeof(long) == sizeof(char*)
1284            dl_inc = find_file('dlfcn.h', [], inc_dirs)
1285            if (dl_inc is not None) and (platform not in ['atheos']):
1286                exts.append( Extension('dl', ['dlmodule.c']) )
1287            else:
1288                missing.append('dl')
1289        else:
1290            missing.append('dl')
1291
1292        # Thomas Heller's _ctypes module
1293        self.detect_ctypes(inc_dirs, lib_dirs)
1294
1295        # Richard Oudkerk's multiprocessing module
1296        if platform == 'win32':             # Windows
1297            macros = dict()
1298            libraries = ['ws2_32']
1299
1300        elif platform == 'darwin':          # Mac OSX
1301            macros = dict()
1302            libraries = []
1303
1304        elif platform == 'cygwin':          # Cygwin
1305            macros = dict()
1306            libraries = []
1307
1308        elif platform in ('freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'freebsd8'):
1309            # FreeBSD's P1003.1b semaphore support is very experimental
1310            # and has many known problems. (as of June 2008)
1311            macros = dict()
1312            libraries = []
1313
1314        elif platform.startswith('openbsd'):
1315            macros = dict()
1316            libraries = []
1317
1318        elif platform.startswith('netbsd'):
1319            macros = dict()
1320            libraries = []
1321
1322        else:                                   # Linux and other unices
1323            macros = dict()
1324            libraries = ['rt']
1325
1326        if platform == 'win32':
1327            multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c',
1328                                     '_multiprocessing/semaphore.c',
1329                                     '_multiprocessing/pipe_connection.c',
1330                                     '_multiprocessing/socket_connection.c',
1331                                     '_multiprocessing/win32_functions.c'
1332                                   ]
1333
1334        else:
1335            multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c',
1336                                     '_multiprocessing/socket_connection.c'
1337                                   ]
1338            if (sysconfig.get_config_var('HAVE_SEM_OPEN') and not
1339                sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED')):
1340                multiprocessing_srcs.append('_multiprocessing/semaphore.c')
1341
1342        if sysconfig.get_config_var('WITH_THREAD'):
1343            exts.append ( Extension('_multiprocessing', multiprocessing_srcs,
1344                                    define_macros=macros.items(),
1345                                    include_dirs=["Modules/_multiprocessing"]))
1346        else:
1347            missing.append('_multiprocessing')
1348
1349        # End multiprocessing
1350
1351
1352        # Platform-specific libraries
1353        if platform == 'linux2':
1354            # Linux-specific modules
1355            exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) )
1356        else:
1357            missing.append('linuxaudiodev')
1358
1359        if platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6',
1360                        'freebsd7', 'freebsd8'):
1361            exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
1362        else:
1363            missing.append('ossaudiodev')
1364
1365        if platform == 'sunos5':
1366            # SunOS specific modules
1367            exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) )
1368        else:
1369            missing.append('sunaudiodev')
1370
1371        if platform == 'darwin':
1372            # _scproxy
1373            exts.append(Extension("_scproxy", [os.path.join(srcdir, "Mac/Modules/_scproxy.c")],
1374                extra_link_args= [
1375                    '-framework', 'SystemConfiguration',
1376                    '-framework', 'CoreFoundation'
1377                ]))
1378
1379
1380        if platform == 'darwin' and ("--disable-toolbox-glue" not in
1381                sysconfig.get_config_var("CONFIG_ARGS")):
1382
1383            if os.uname()[2] > '8.':
1384                # We're on Mac OS X 10.4 or later, the compiler should
1385                # support '-Wno-deprecated-declarations'. This will
1386                # surpress deprecation warnings for the Carbon extensions,
1387                # these extensions wrap the Carbon APIs and even those
1388                # parts that are deprecated.
1389                carbon_extra_compile_args = ['-Wno-deprecated-declarations']
1390            else:
1391                carbon_extra_compile_args = []
1392
1393            # Mac OS X specific modules.
1394            def macSrcExists(name1, name2=''):
1395                if not name1:
1396                    return None
1397                names = (name1,)
1398                if name2:
1399                    names = (name1, name2)
1400                path = os.path.join(srcdir, 'Mac', 'Modules', *names)
1401                return os.path.exists(path)
1402
1403            def addMacExtension(name, kwds, extra_srcs=[]):
1404                dirname = ''
1405                if name[0] == '_':
1406                    dirname = name[1:].lower()
1407                cname = name + '.c'
1408                cmodulename = name + 'module.c'
1409                # Check for NNN.c, NNNmodule.c, _nnn/NNN.c, _nnn/NNNmodule.c
1410                if macSrcExists(cname):
1411                    srcs = [cname]
1412                elif macSrcExists(cmodulename):
1413                    srcs = [cmodulename]
1414                elif macSrcExists(dirname, cname):
1415                    # XXX(nnorwitz): If all the names ended with module, we
1416                    # wouldn't need this condition.  ibcarbon is the only one.
1417                    srcs = [os.path.join(dirname, cname)]
1418                elif macSrcExists(dirname, cmodulename):
1419                    srcs = [os.path.join(dirname, cmodulename)]
1420                else:
1421                    raise RuntimeError("%s not found" % name)
1422
1423                # Here's the whole point:  add the extension with sources
1424                exts.append(Extension(name, srcs + extra_srcs, **kwds))
1425
1426            # Core Foundation
1427            core_kwds = {'extra_compile_args': carbon_extra_compile_args,
1428                         'extra_link_args': ['-framework', 'CoreFoundation'],
1429                        }
1430            addMacExtension('_CF', core_kwds, ['cf/pycfbridge.c'])
1431            addMacExtension('autoGIL', core_kwds)
1432
1433
1434
1435            # Carbon
1436            carbon_kwds = {'extra_compile_args': carbon_extra_compile_args,
1437                           'extra_link_args': ['-framework', 'Carbon'],
1438                          }
1439            CARBON_EXTS = ['ColorPicker', 'gestalt', 'MacOS', 'Nav',
1440                           'OSATerminology', 'icglue',
1441                           # All these are in subdirs
1442                           '_AE', '_AH', '_App', '_CarbonEvt', '_Cm', '_Ctl',
1443                           '_Dlg', '_Drag', '_Evt', '_File', '_Folder', '_Fm',
1444                           '_Help', '_Icn', '_IBCarbon', '_List',
1445                           '_Menu', '_Mlte', '_OSA', '_Res', '_Qd', '_Qdoffs',
1446                           '_Scrap', '_Snd', '_TE',
1447                          ]
1448            for name in CARBON_EXTS:
1449                addMacExtension(name, carbon_kwds)
1450
1451            # Workaround for a bug in the version of gcc shipped with Xcode 3.
1452            # The _Win extension should build just like the other Carbon extensions, but
1453            # this actually results in a hard crash of the linker.
1454            #
1455            if '-arch ppc64' in cflags and '-arch ppc' in cflags:
1456                win_kwds = {'extra_compile_args': carbon_extra_compile_args + ['-arch', 'i386', '-arch', 'ppc'],
1457                               'extra_link_args': ['-framework', 'Carbon', '-arch', 'i386', '-arch', 'ppc'],
1458                           }
1459                addMacExtension('_Win', win_kwds)
1460            else:
1461                addMacExtension('_Win', carbon_kwds)
1462
1463
1464            # Application Services & QuickTime
1465            app_kwds = {'extra_compile_args': carbon_extra_compile_args,
1466                        'extra_link_args': ['-framework','ApplicationServices'],
1467                       }
1468            addMacExtension('_Launch', app_kwds)
1469            addMacExtension('_CG', app_kwds)
1470
1471            exts.append( Extension('_Qt', ['qt/_Qtmodule.c'],
1472                        extra_compile_args=carbon_extra_compile_args,
1473                        extra_link_args=['-framework', 'QuickTime',
1474                                     '-framework', 'Carbon']) )
1475
1476
1477        self.extensions.extend(exts)
1478
1479        # Call the method for detecting whether _tkinter can be compiled
1480        self.detect_tkinter(inc_dirs, lib_dirs)
1481
1482        if '_tkinter' not in [e.name for e in self.extensions]:
1483            missing.append('_tkinter')
1484
1485        return missing
1486
1487    def detect_tkinter_darwin(self, inc_dirs, lib_dirs):
1488        # The _tkinter module, using frameworks. Since frameworks are quite
1489        # different the UNIX search logic is not sharable.
1490        from os.path import join, exists
1491        framework_dirs = [
1492            '/Library/Frameworks',
1493            '/System/Library/Frameworks/',
1494            join(os.getenv('HOME'), '/Library/Frameworks')
1495        ]
1496
1497        # Find the directory that contains the Tcl.framework and Tk.framework
1498        # bundles.
1499        # XXX distutils should support -F!
1500        for F in framework_dirs:
1501            # both Tcl.framework and Tk.framework should be present
1502            for fw in 'Tcl', 'Tk':
1503                if not exists(join(F, fw + '.framework')):
1504                    break
1505            else:
1506                # ok, F is now directory with both frameworks. Continure
1507                # building
1508                break
1509        else:
1510            # Tk and Tcl frameworks not found. Normal "unix" tkinter search
1511            # will now resume.
1512            return 0
1513
1514        # For 8.4a2, we must add -I options that point inside the Tcl and Tk
1515        # frameworks. In later release we should hopefully be able to pass
1516        # the -F option to gcc, which specifies a framework lookup path.
1517        #
1518        include_dirs = [
1519            join(F, fw + '.framework', H)
1520            for fw in 'Tcl', 'Tk'
1521            for H in 'Headers', 'Versions/Current/PrivateHeaders'
1522        ]
1523
1524        # For 8.4a2, the X11 headers are not included. Rather than include a
1525        # complicated search, this is a hard-coded path. It could bail out
1526        # if X11 libs are not found...
1527        include_dirs.append('/usr/X11R6/include')
1528        frameworks = ['-framework', 'Tcl', '-framework', 'Tk']
1529
1530        # All existing framework builds of Tcl/Tk don't support 64-bit
1531        # architectures.
1532        cflags = sysconfig.get_config_vars('CFLAGS')[0]
1533        archs = re.findall('-arch\s+(\w+)', cflags)
1534        fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(F,))
1535        detected_archs = []
1536        for ln in fp:
1537            a = ln.split()[-1]
1538            if a in archs:
1539                detected_archs.append(ln.split()[-1])
1540        fp.close()
1541
1542        for a in detected_archs:
1543            frameworks.append('-arch')
1544            frameworks.append(a)
1545
1546        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1547                        define_macros=[('WITH_APPINIT', 1)],
1548                        include_dirs = include_dirs,
1549                        libraries = [],
1550                        extra_compile_args = frameworks[2:],
1551                        extra_link_args = frameworks,
1552                        )
1553        self.extensions.append(ext)
1554        return 1
1555
1556
1557    def detect_tkinter(self, inc_dirs, lib_dirs):
1558        # The _tkinter module.
1559
1560        # Rather than complicate the code below, detecting and building
1561        # AquaTk is a separate method. Only one Tkinter will be built on
1562        # Darwin - either AquaTk, if it is found, or X11 based Tk.
1563        platform = self.get_platform()
1564        if (platform == 'darwin' and
1565            self.detect_tkinter_darwin(inc_dirs, lib_dirs)):
1566            return
1567
1568        # Assume we haven't found any of the libraries or include files
1569        # The versions with dots are used on Unix, and the versions without
1570        # dots on Windows, for detection by cygwin.
1571        tcllib = tklib = tcl_includes = tk_includes = None
1572        for version in ['8.6', '86', '8.5', '85', '8.4', '84', '8.3', '83',
1573                        '8.2', '82', '8.1', '81', '8.0', '80']:
1574            tklib = self.compiler_obj.find_library_file(lib_dirs,
1575                                                        'tk' + version)
1576            tcllib = self.compiler_obj.find_library_file(lib_dirs,
1577                                                         'tcl' + version)
1578            if tklib and tcllib:
1579                # Exit the loop when we've found the Tcl/Tk libraries
1580                break
1581
1582        # Now check for the header files
1583        if tklib and tcllib:
1584            # Check for the include files on Debian and {Free,Open}BSD, where
1585            # they're put in /usr/include/{tcl,tk}X.Y
1586            dotversion = version
1587            if '.' not in dotversion and "bsd" in sys.platform.lower():
1588                # OpenBSD and FreeBSD use Tcl/Tk library names like libtcl83.a,
1589                # but the include subdirs are named like .../include/tcl8.3.
1590                dotversion = dotversion[:-1] + '.' + dotversion[-1]
1591            tcl_include_sub = []
1592            tk_include_sub = []
1593            for dir in inc_dirs:
1594                tcl_include_sub += [dir + os.sep + "tcl" + dotversion]
1595                tk_include_sub += [dir + os.sep + "tk" + dotversion]
1596            tk_include_sub += tcl_include_sub
1597            tcl_includes = find_file('tcl.h', inc_dirs, tcl_include_sub)
1598            tk_includes = find_file('tk.h', inc_dirs, tk_include_sub)
1599
1600        if (tcllib is None or tklib is None or
1601            tcl_includes is None or tk_includes is None):
1602            self.announce("INFO: Can't locate Tcl/Tk libs and/or headers", 2)
1603            return
1604
1605        # OK... everything seems to be present for Tcl/Tk.
1606
1607        include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = []
1608        for dir in tcl_includes + tk_includes:
1609            if dir not in include_dirs:
1610                include_dirs.append(dir)
1611
1612        # Check for various platform-specific directories
1613        if platform == 'sunos5':
1614            include_dirs.append('/usr/openwin/include')
1615            added_lib_dirs.append('/usr/openwin/lib')
1616        elif os.path.exists('/usr/X11R6/include'):
1617            include_dirs.append('/usr/X11R6/include')
1618            added_lib_dirs.append('/usr/X11R6/lib64')
1619            added_lib_dirs.append('/usr/X11R6/lib')
1620        elif os.path.exists('/usr/X11R5/include'):
1621            include_dirs.append('/usr/X11R5/include')
1622            added_lib_dirs.append('/usr/X11R5/lib')
1623        else:
1624            # Assume default location for X11
1625            include_dirs.append('/usr/X11/include')
1626            added_lib_dirs.append('/usr/X11/lib')
1627
1628        # If Cygwin, then verify that X is installed before proceeding
1629        if platform == 'cygwin':
1630            x11_inc = find_file('X11/Xlib.h', [], include_dirs)
1631            if x11_inc is None:
1632                return
1633
1634        # Check for BLT extension
1635        if self.compiler_obj.find_library_file(lib_dirs + added_lib_dirs,
1636                                               'BLT8.0'):
1637            defs.append( ('WITH_BLT', 1) )
1638            libs.append('BLT8.0')
1639        elif self.compiler_obj.find_library_file(lib_dirs + added_lib_dirs,
1640                                                'BLT'):
1641            defs.append( ('WITH_BLT', 1) )
1642            libs.append('BLT')
1643
1644        # Add the Tcl/Tk libraries
1645        libs.append('tk'+ version)
1646        libs.append('tcl'+ version)
1647
1648        if platform in ['aix3', 'aix4']:
1649            libs.append('ld')
1650
1651        # Finally, link with the X11 libraries (not appropriate on cygwin)
1652        if platform != "cygwin":
1653            libs.append('X11')
1654
1655        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1656                        define_macros=[('WITH_APPINIT', 1)] + defs,
1657                        include_dirs = include_dirs,
1658                        libraries = libs,
1659                        library_dirs = added_lib_dirs,
1660                        )
1661        self.extensions.append(ext)
1662
1663##         # Uncomment these lines if you want to play with xxmodule.c
1664##         ext = Extension('xx', ['xxmodule.c'])
1665##         self.extensions.append(ext)
1666
1667        # XXX handle these, but how to detect?
1668        # *** Uncomment and edit for PIL (TkImaging) extension only:
1669        #       -DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \
1670        # *** Uncomment and edit for TOGL extension only:
1671        #       -DWITH_TOGL togl.c \
1672        # *** Uncomment these for TOGL extension only:
1673        #       -lGL -lGLU -lXext -lXmu \
1674
1675    def configure_ctypes_darwin(self, ext):
1676        # Darwin (OS X) uses preconfigured files, in
1677        # the Modules/_ctypes/libffi_osx directory.
1678        srcdir = sysconfig.get_config_var('srcdir')
1679        ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
1680                                                  '_ctypes', 'libffi_osx'))
1681        sources = [os.path.join(ffi_srcdir, p)
1682                   for p in ['ffi.c',
1683                             'x86/darwin64.S',
1684                             'x86/x86-darwin.S',
1685                             'x86/x86-ffi_darwin.c',
1686                             'x86/x86-ffi64.c',
1687                             'powerpc/ppc-darwin.S',
1688                             'powerpc/ppc-darwin_closure.S',
1689                             'powerpc/ppc-ffi_darwin.c',
1690                             'powerpc/ppc64-darwin_closure.S',
1691                             ]]
1692
1693        # Add .S (preprocessed assembly) to C compiler source extensions.
1694        self.compiler_obj.src_extensions.append('.S')
1695
1696        include_dirs = [os.path.join(ffi_srcdir, 'include'),
1697                        os.path.join(ffi_srcdir, 'powerpc')]
1698        ext.include_dirs.extend(include_dirs)
1699        ext.sources.extend(sources)
1700        return True
1701
1702    def configure_ctypes(self, ext):
1703        if not self.use_system_libffi:
1704            if sys.platform == 'darwin':
1705                return self.configure_ctypes_darwin(ext)
1706
1707            srcdir = sysconfig.get_config_var('srcdir')
1708            ffi_builddir = os.path.join(self.build_temp, 'libffi')
1709            ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
1710                                         '_ctypes', 'libffi'))
1711            ffi_configfile = os.path.join(ffi_builddir, 'fficonfig.py')
1712
1713            from distutils.dep_util import newer_group
1714
1715            config_sources = [os.path.join(ffi_srcdir, fname)
1716                              for fname in os.listdir(ffi_srcdir)
1717                              if os.path.isfile(os.path.join(ffi_srcdir, fname))]
1718            if self.force or newer_group(config_sources,
1719                                         ffi_configfile):
1720                from distutils.dir_util import mkpath
1721                mkpath(ffi_builddir)
1722                config_args = []
1723
1724                # Pass empty CFLAGS because we'll just append the resulting
1725                # CFLAGS to Python's; -g or -O2 is to be avoided.
1726                cmd = "cd %s && env CFLAGS='' '%s/configure' %s" \
1727                      % (ffi_builddir, ffi_srcdir, " ".join(config_args))
1728
1729                res = os.system(cmd)
1730                if res or not os.path.exists(ffi_configfile):
1731                    print "Failed to configure _ctypes module"
1732                    return False
1733
1734            fficonfig = {}
1735            execfile(ffi_configfile, globals(), fficonfig)
1736            ffi_srcdir = os.path.join(fficonfig['ffi_srcdir'], 'src')
1737
1738            # Add .S (preprocessed assembly) to C compiler source extensions.
1739            self.compiler_obj.src_extensions.append('.S')
1740
1741            include_dirs = [os.path.join(ffi_builddir, 'include'),
1742                            ffi_builddir, ffi_srcdir]
1743            extra_compile_args = fficonfig['ffi_cflags'].split()
1744
1745            ext.sources.extend(fficonfig['ffi_sources'])
1746            ext.include_dirs.extend(include_dirs)
1747            ext.extra_compile_args.extend(extra_compile_args)
1748        return True
1749
1750    def detect_ctypes(self, inc_dirs, lib_dirs):
1751        self.use_system_libffi = False
1752        include_dirs = []
1753        extra_compile_args = []
1754        extra_link_args = []
1755        sources = ['_ctypes/_ctypes.c',
1756                   '_ctypes/callbacks.c',
1757                   '_ctypes/callproc.c',
1758                   '_ctypes/stgdict.c',
1759                   '_ctypes/cfield.c',
1760                   '_ctypes/malloc_closure.c']
1761        depends = ['_ctypes/ctypes.h']
1762
1763        if sys.platform == 'darwin':
1764            sources.append('_ctypes/darwin/dlfcn_simple.c')
1765            extra_compile_args.append('-DMACOSX')
1766            include_dirs.append('_ctypes/darwin')
1767# XXX Is this still needed?
1768##            extra_link_args.extend(['-read_only_relocs', 'warning'])
1769
1770        elif sys.platform == 'sunos5':
1771            # XXX This shouldn't be necessary; it appears that some
1772            # of the assembler code is non-PIC (i.e. it has relocations
1773            # when it shouldn't. The proper fix would be to rewrite
1774            # the assembler code to be PIC.
1775            # This only works with GCC; the Sun compiler likely refuses
1776            # this option. If you want to compile ctypes with the Sun
1777            # compiler, please research a proper solution, instead of
1778            # finding some -z option for the Sun compiler.
1779            extra_link_args.append('-mimpure-text')
1780
1781        elif sys.platform.startswith('hp-ux'):
1782            extra_link_args.append('-fPIC')
1783
1784        ext = Extension('_ctypes',
1785                        include_dirs=include_dirs,
1786                        extra_compile_args=extra_compile_args,
1787                        extra_link_args=extra_link_args,
1788                        libraries=[],
1789                        sources=sources,
1790                        depends=depends)
1791        ext_test = Extension('_ctypes_test',
1792                             sources=['_ctypes/_ctypes_test.c'])
1793        self.extensions.extend([ext, ext_test])
1794
1795        if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
1796            return
1797
1798        if sys.platform == 'darwin':
1799            # OS X 10.5 comes with libffi.dylib; the include files are
1800            # in /usr/include/ffi
1801            inc_dirs.append('/usr/include/ffi')
1802
1803        ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
1804        if not ffi_inc:
1805            ffi_inc = find_file('ffi.h', [], inc_dirs)
1806        if ffi_inc is not None:
1807            ffi_h = ffi_inc[0] + '/ffi.h'
1808            fp = open(ffi_h)
1809            while 1:
1810                line = fp.readline()
1811                if not line:
1812                    ffi_inc = None
1813                    break
1814                if line.startswith('#define LIBFFI_H'):
1815                    break
1816        ffi_lib = None
1817        if ffi_inc is not None:
1818            for lib_name in ('ffi_convenience', 'ffi_pic', 'ffi'):
1819                if (self.compiler_obj.find_library_file(lib_dirs, lib_name)):
1820                    ffi_lib = lib_name
1821                    break
1822
1823        if ffi_inc and ffi_lib:
1824            ext.include_dirs.extend(ffi_inc)
1825            ext.libraries.append(ffi_lib)
1826            self.use_system_libffi = True
1827
1828
1829class PyBuildInstall(install):
1830    # Suppress the warning about installation into the lib_dynload
1831    # directory, which is not in sys.path when running Python during
1832    # installation:
1833    def initialize_options (self):
1834        install.initialize_options(self)
1835        self.warn_dir=0
1836
1837class PyBuildInstallLib(install_lib):
1838    # Do exactly what install_lib does but make sure correct access modes get
1839    # set on installed directories and files. All installed files with get
1840    # mode 644 unless they are a shared library in which case they will get
1841    # mode 755. All installed directories will get mode 755.
1842
1843    so_ext = sysconfig.get_config_var("SO")
1844
1845    def install(self):
1846        outfiles = install_lib.install(self)
1847        self.set_file_modes(outfiles, 0644, 0755)
1848        self.set_dir_modes(self.install_dir, 0755)
1849        return outfiles
1850
1851    def set_file_modes(self, files, defaultMode, sharedLibMode):
1852        if not self.is_chmod_supported(): return
1853        if not files: return
1854
1855        for filename in files:
1856            if os.path.islink(filename): continue
1857            mode = defaultMode
1858            if filename.endswith(self.so_ext): mode = sharedLibMode
1859            log.info("changing mode of %s to %o", filename, mode)
1860            if not self.dry_run: os.chmod(filename, mode)
1861
1862    def set_dir_modes(self, dirname, mode):
1863        if not self.is_chmod_supported(): return
1864        os.path.walk(dirname, self.set_dir_modes_visitor, mode)
1865
1866    def set_dir_modes_visitor(self, mode, dirname, names):
1867        if os.path.islink(dirname): return
1868        log.info("changing mode of %s to %o", dirname, mode)
1869        if not self.dry_run: os.chmod(dirname, mode)
1870
1871    def is_chmod_supported(self):
1872        return hasattr(os, 'chmod')
1873
1874SUMMARY = """
1875Python is an interpreted, interactive, object-oriented programming
1876language. It is often compared to Tcl, Perl, Scheme or Java.
1877
1878Python combines remarkable power with very clear syntax. It has
1879modules, classes, exceptions, very high level dynamic data types, and
1880dynamic typing. There are interfaces to many system calls and
1881libraries, as well as to various windowing systems (X11, Motif, Tk,
1882Mac, MFC). New built-in modules are easily written in C or C++. Python
1883is also usable as an extension language for applications that need a
1884programmable interface.
1885
1886The Python implementation is portable: it runs on many brands of UNIX,
1887on Windows, DOS, OS/2, Mac, Amiga... If your favorite system isn't
1888listed here, it may still be supported, if there's a C compiler for
1889it. Ask around on comp.lang.python -- or just try compiling Python
1890yourself.
1891"""
1892
1893CLASSIFIERS = """
1894Development Status :: 6 - Mature
1895License :: OSI Approved :: Python Software Foundation License
1896Natural Language :: English
1897Programming Language :: C
1898Programming Language :: Python
1899Topic :: Software Development
1900"""
1901
1902def main():
1903    # turn off warnings when deprecated modules are imported
1904    import warnings
1905    warnings.filterwarnings("ignore",category=DeprecationWarning)
1906    setup(# PyPI Metadata (PEP 301)
1907          name = "Python",
1908          version = sys.version.split()[0],
1909          url = "http://www.python.org/%s" % sys.version[:3],
1910          maintainer = "Guido van Rossum and the Python community",
1911          maintainer_email = "python-dev@python.org",
1912          description = "A high-level object-oriented programming language",
1913          long_description = SUMMARY.strip(),
1914          license = "PSF license",
1915          classifiers = filter(None, CLASSIFIERS.split("\n")),
1916          platforms = ["Many"],
1917
1918          # Build info
1919          cmdclass = {'build_ext':PyBuildExt, 'install':PyBuildInstall,
1920                      'install_lib':PyBuildInstallLib},
1921          # The struct module is defined here, because build_ext won't be
1922          # called unless there's at least one extension module defined.
1923          ext_modules=[Extension('_struct', ['_struct.c'])],
1924
1925          # Scripts to install
1926          scripts = ['Tools/scripts/pydoc', 'Tools/scripts/idle',
1927                     'Tools/scripts/2to3',
1928                     'Lib/smtpd.py']
1929        )
1930
1931# --install-platlib
1932if __name__ == '__main__':
1933    main()
1934