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