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