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