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