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