setup.py revision a871ef2b3e924f058ec1b0aed7d4c83a546414b7
1# Autodetecting setup.py script for building the Python extensions
2#
3
4__version__ = "$Revision$"
5
6import sys, os, imp, re, optparse
7
8from distutils import log
9from distutils import sysconfig
10from distutils import text_file
11from distutils.errors import *
12from distutils.core import Extension, setup
13from distutils.command.build_ext import build_ext
14from distutils.command.install import install
15from distutils.command.install_lib import install_lib
16
17# This global variable is used to hold the list of modules to be disabled.
18disabled_module_list = []
19
20def add_dir_to_list(dirlist, dir):
21    """Add the directory 'dir' to the list 'dirlist' (at the front) if
22    1) 'dir' is not already in 'dirlist'
23    2) 'dir' actually exists, and is a directory."""
24    if dir is not None and os.path.isdir(dir) and dir not in dirlist:
25        dirlist.insert(0, dir)
26
27def find_file(filename, std_dirs, paths):
28    """Searches for the directory where a given file is located,
29    and returns a possibly-empty list of additional directories, or None
30    if the file couldn't be found at all.
31
32    'filename' is the name of a file, such as readline.h or libcrypto.a.
33    'std_dirs' is the list of standard system directories; if the
34        file is found in one of them, no additional directives are needed.
35    'paths' is a list of additional locations to check; if the file is
36        found in one of them, the resulting list will contain the directory.
37    """
38
39    # Check the standard locations
40    for dir in std_dirs:
41        f = os.path.join(dir, filename)
42        if os.path.exists(f): return []
43
44    # Check the additional directories
45    for dir in paths:
46        f = os.path.join(dir, filename)
47        if os.path.exists(f):
48            return [dir]
49
50    # Not found anywhere
51    return None
52
53def find_library_file(compiler, libname, std_dirs, paths):
54    result = compiler.find_library_file(std_dirs + paths, libname)
55    if result is None:
56        return None
57
58    # Check whether the found file is in one of the standard directories
59    dirname = os.path.dirname(result)
60    for p in std_dirs:
61        # Ensure path doesn't end with path separator
62        p = p.rstrip(os.sep)
63        if p == dirname:
64            return [ ]
65
66    # Otherwise, it must have been in one of the additional directories,
67    # so we have to figure out which one.
68    for p in paths:
69        # Ensure path doesn't end with path separator
70        p = p.rstrip(os.sep)
71        if p == dirname:
72            return [p]
73    else:
74        assert False, "Internal error: Path not found in std_dirs or paths"
75
76def module_enabled(extlist, modname):
77    """Returns whether the module 'modname' is present in the list
78    of extensions 'extlist'."""
79    extlist = [ext for ext in extlist if ext.name == modname]
80    return len(extlist)
81
82def find_module_file(module, dirlist):
83    """Find a module in a set of possible folders. If it is not found
84    return the unadorned filename"""
85    list = find_file(module, [], dirlist)
86    if not list:
87        return module
88    if len(list) > 1:
89        log.info("WARNING: multiple copies of %s found"%module)
90    return os.path.join(list[0], module)
91
92class PyBuildExt(build_ext):
93
94    def build_extensions(self):
95
96        # Detect which modules should be compiled
97        self.detect_modules()
98
99        # Remove modules that are present on the disabled list
100        self.extensions = [ext for ext in self.extensions
101                           if ext.name not in disabled_module_list]
102
103        # Fix up the autodetected modules, prefixing all the source files
104        # with Modules/ and adding Python's include directory to the path.
105        (srcdir,) = sysconfig.get_config_vars('srcdir')
106        if not srcdir:
107            # Maybe running on Windows but not using CYGWIN?
108            raise ValueError("No source directory; cannot proceed.")
109
110        # Figure out the location of the source code for extension modules
111        moddir = os.path.join(os.getcwd(), srcdir, 'Modules')
112        moddir = os.path.normpath(moddir)
113        srcdir, tail = os.path.split(moddir)
114        srcdir = os.path.normpath(srcdir)
115        moddir = os.path.normpath(moddir)
116
117        moddirlist = [moddir]
118        incdirlist = ['./Include']
119
120        # Platform-dependent module source and include directories
121        platform = self.get_platform()
122        if platform in ('darwin', 'mac') and ("--disable-toolbox-glue" not in
123            sysconfig.get_config_var("CONFIG_ARGS")):
124            # Mac OS X also includes some mac-specific modules
125            macmoddir = os.path.join(os.getcwd(), srcdir, 'Mac/Modules')
126            moddirlist.append(macmoddir)
127            incdirlist.append('./Mac/Include')
128
129        alldirlist = moddirlist + incdirlist
130
131        # Fix up the paths for scripts, too
132        self.distribution.scripts = [os.path.join(srcdir, filename)
133                                     for filename in self.distribution.scripts]
134
135        for ext in self.extensions[:]:
136            ext.sources = [ find_module_file(filename, moddirlist)
137                            for filename in ext.sources ]
138            if ext.depends is not None:
139                ext.depends = [find_module_file(filename, alldirlist)
140                               for filename in ext.depends]
141            ext.include_dirs.append( '.' ) # to get config.h
142            for incdir in incdirlist:
143                ext.include_dirs.append( os.path.join(srcdir, incdir) )
144
145            # If a module has already been built statically,
146            # don't build it here
147            if ext.name in sys.builtin_module_names:
148                self.extensions.remove(ext)
149
150        if platform != 'mac':
151            # Parse Modules/Setup and Modules/Setup.local to figure out which
152            # modules are turned on in the file.
153            remove_modules = []
154            for filename in ('Modules/Setup', 'Modules/Setup.local'):
155                input = text_file.TextFile(filename, join_lines=1)
156                while 1:
157                    line = input.readline()
158                    if not line: break
159                    line = line.split()
160                    remove_modules.append(line[0])
161                input.close()
162
163            for ext in self.extensions[:]:
164                if ext.name in remove_modules:
165                    self.extensions.remove(ext)
166
167        # When you run "make CC=altcc" or something similar, you really want
168        # those environment variables passed into the setup.py phase.  Here's
169        # a small set of useful ones.
170        compiler = os.environ.get('CC')
171        args = {}
172        # unfortunately, distutils doesn't let us provide separate C and C++
173        # compilers
174        if compiler is not None:
175            (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS')
176            args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags
177        self.compiler.set_executables(**args)
178
179        build_ext.build_extensions(self)
180
181    def build_extension(self, ext):
182
183        try:
184            build_ext.build_extension(self, ext)
185        except (CCompilerError, DistutilsError), why:
186            self.announce('WARNING: building of extension "%s" failed: %s' %
187                          (ext.name, sys.exc_info()[1]))
188            return
189        # Workaround for Mac OS X: The Carbon-based modules cannot be
190        # reliably imported into a command-line Python
191        if 'Carbon' in ext.extra_link_args:
192            self.announce(
193                'WARNING: skipping import check for Carbon-based "%s"' %
194                ext.name)
195            return
196        # Workaround for Cygwin: Cygwin currently has fork issues when many
197        # modules have been imported
198        if self.get_platform() == 'cygwin':
199            self.announce('WARNING: skipping import check for Cygwin-based "%s"'
200                % ext.name)
201            return
202        ext_filename = os.path.join(
203            self.build_lib,
204            self.get_ext_filename(self.get_ext_fullname(ext.name)))
205        try:
206            imp.load_dynamic(ext.name, ext_filename)
207        except ImportError, why:
208            self.announce('*** WARNING: renaming "%s" since importing it'
209                          ' failed: %s' % (ext.name, why), level=3)
210            assert not self.inplace
211            basename, tail = os.path.splitext(ext_filename)
212            newname = basename + "_failed" + tail
213            if os.path.exists(newname):
214                os.remove(newname)
215            os.rename(ext_filename, newname)
216
217            # XXX -- This relies on a Vile HACK in
218            # distutils.command.build_ext.build_extension().  The
219            # _built_objects attribute is stored there strictly for
220            # use here.
221            # If there is a failure, _built_objects may not be there,
222            # so catch the AttributeError and move on.
223            try:
224                for filename in self._built_objects:
225                    os.remove(filename)
226            except AttributeError:
227                self.announce('unable to remove files (ignored)')
228        except:
229            exc_type, why, tb = sys.exc_info()
230            self.announce('*** WARNING: importing extension "%s" '
231                          'failed with %s: %s' % (ext.name, exc_type, why),
232                          level=3)
233
234    def get_platform(self):
235        # Get value of sys.platform
236        for platform in ['cygwin', 'beos', 'darwin', 'atheos', 'osf1']:
237            if sys.platform.startswith(platform):
238                return platform
239        return sys.platform
240
241    def detect_modules(self):
242        # Ensure that /usr/local is always used
243        add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
244        add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
245
246        # Add paths specified in the environment variables LDFLAGS and
247        # CPPFLAGS for header and library files.
248        # We must get the values from the Makefile and not the environment
249        # directly since an inconsistently reproducible issue comes up where
250        # the environment variable is not set even though the value were passed
251        # into configure and stored in the Makefile (issue found on OS X 10.3).
252        for env_var, arg_name, dir_list in (
253                ('LDFLAGS', '-L', self.compiler.library_dirs),
254                ('CPPFLAGS', '-I', self.compiler.include_dirs)):
255            env_val = sysconfig.get_config_var(env_var)
256            if env_val:
257                # To prevent optparse from raising an exception about any
258                # options in env_val that is doesn't know about we strip out
259                # all double dashes and any dashes followed by a character
260                # that is not for the option we are dealing with.
261                #
262                # Please note that order of the regex is important!  We must
263                # strip out double-dashes first so that we don't end up with
264                # substituting "--Long" to "-Long" and thus lead to "ong" being
265                # used for a library directory.
266                env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1], '', env_val)
267                parser = optparse.OptionParser()
268                # Make sure that allowing args interspersed with options is
269                # allowed
270                parser.allow_interspersed_args = True
271                parser.error = lambda msg: None
272                parser.add_option(arg_name, dest="dirs", action="append")
273                options = parser.parse_args(env_val.split())[0]
274                if options.dirs:
275                    for directory in options.dirs:
276                        add_dir_to_list(dir_list, directory)
277
278        if os.path.normpath(sys.prefix) != '/usr':
279            add_dir_to_list(self.compiler.library_dirs,
280                            sysconfig.get_config_var("LIBDIR"))
281            add_dir_to_list(self.compiler.include_dirs,
282                            sysconfig.get_config_var("INCLUDEDIR"))
283
284        try:
285            have_unicode = unicode
286        except NameError:
287            have_unicode = 0
288
289        # lib_dirs and inc_dirs are used to search for files;
290        # if a file is found in one of those directories, it can
291        # be assumed that no additional -I,-L directives are needed.
292        lib_dirs = self.compiler.library_dirs + [
293            '/lib64', '/usr/lib64',
294            '/lib', '/usr/lib',
295            ]
296        inc_dirs = self.compiler.include_dirs + ['/usr/include']
297        exts = []
298
299        config_h = sysconfig.get_config_h_filename()
300        config_h_vars = sysconfig.parse_config_h(open(config_h))
301
302        platform = self.get_platform()
303        (srcdir,) = sysconfig.get_config_vars('srcdir')
304
305        # Check for AtheOS which has libraries in non-standard locations
306        if platform == 'atheos':
307            lib_dirs += ['/system/libs', '/atheos/autolnk/lib']
308            lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep)
309            inc_dirs += ['/system/include', '/atheos/autolnk/include']
310            inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep)
311
312        # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
313        if platform in ['osf1', 'unixware7', 'openunix8']:
314            lib_dirs += ['/usr/ccs/lib']
315
316        # Check for MacOS X, which doesn't need libm.a at all
317        math_libs = ['m']
318        if platform in ['darwin', 'beos', 'mac']:
319            math_libs = []
320
321        # XXX Omitted modules: gl, pure, dl, SGI-specific modules
322
323        #
324        # The following modules are all pretty straightforward, and compile
325        # on pretty much any POSIXish platform.
326        #
327
328        # Some modules that are normally always on:
329        exts.append( Extension('regex', ['regexmodule.c', 'regexpr.c']) )
330
331        exts.append( Extension('_weakref', ['_weakref.c']) )
332
333        # array objects
334        exts.append( Extension('array', ['arraymodule.c']) )
335        # complex math library functions
336        exts.append( Extension('cmath', ['cmathmodule.c'],
337                               libraries=math_libs) )
338
339        # math library functions, e.g. sin()
340        exts.append( Extension('math',  ['mathmodule.c'],
341                               libraries=math_libs) )
342        # fast string operations implemented in C
343        exts.append( Extension('strop', ['stropmodule.c']) )
344        # time operations and variables
345        exts.append( Extension('time', ['timemodule.c'],
346                               libraries=math_libs) )
347        exts.append( Extension('datetime', ['datetimemodule.c', 'timemodule.c'],
348                               libraries=math_libs) )
349        # random number generator implemented in C
350        exts.append( Extension("_random", ["_randommodule.c"]) )
351        # fast iterator tools implemented in C
352        exts.append( Extension("itertools", ["itertoolsmodule.c"]) )
353        # high-performance collections
354        exts.append( Extension("collections", ["collectionsmodule.c"]) )
355        # bisect
356        exts.append( Extension("_bisect", ["_bisectmodule.c"]) )
357        # heapq
358        exts.append( Extension("_heapq", ["_heapqmodule.c"]) )
359        # operator.add() and similar goodies
360        exts.append( Extension('operator', ['operator.c']) )
361        # functional
362        exts.append( Extension("functional", ["functionalmodule.c"]) )
363        # Python C API test module
364        exts.append( Extension('_testcapi', ['_testcapimodule.c']) )
365        # profilers (_lsprof is for cProfile.py)
366        exts.append( Extension('_hotshot', ['_hotshot.c']) )
367        exts.append( Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c']) )
368        # static Unicode character database
369        if have_unicode:
370            exts.append( Extension('unicodedata', ['unicodedata.c']) )
371        # access to ISO C locale support
372        data = open('pyconfig.h').read()
373        m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data)
374        if m is not None:
375            locale_libs = ['intl']
376        else:
377            locale_libs = []
378        if platform == 'darwin':
379            locale_extra_link_args = ['-framework', 'CoreFoundation']
380        else:
381            locale_extra_link_args = []
382
383
384        exts.append( Extension('_locale', ['_localemodule.c'],
385                               libraries=locale_libs,
386                               extra_link_args=locale_extra_link_args) )
387
388        # Modules with some UNIX dependencies -- on by default:
389        # (If you have a really backward UNIX, select and socket may not be
390        # supported...)
391
392        # fcntl(2) and ioctl(2)
393        exts.append( Extension('fcntl', ['fcntlmodule.c']) )
394        if platform not in ['mac']:
395            # pwd(3)
396            exts.append( Extension('pwd', ['pwdmodule.c']) )
397            # grp(3)
398            exts.append( Extension('grp', ['grpmodule.c']) )
399            # spwd, shadow passwords
400            if (config_h_vars.get('HAVE_GETSPNAM', False) or
401                    config_h_vars.get('HAVE_GETSPENT', False)):
402                exts.append( Extension('spwd', ['spwdmodule.c']) )
403        # select(2); not on ancient System V
404        exts.append( Extension('select', ['selectmodule.c']) )
405
406        # Helper module for various ascii-encoders
407        exts.append( Extension('binascii', ['binascii.c']) )
408
409        # Fred Drake's interface to the Python parser
410        exts.append( Extension('parser', ['parsermodule.c']) )
411
412        # cStringIO and cPickle
413        exts.append( Extension('cStringIO', ['cStringIO.c']) )
414        exts.append( Extension('cPickle', ['cPickle.c']) )
415
416        # Memory-mapped files (also works on Win32).
417        if platform not in ['atheos', 'mac']:
418            exts.append( Extension('mmap', ['mmapmodule.c']) )
419
420        # Lance Ellinghaus's syslog module
421        if platform not in ['mac']:
422            # syslog daemon interface
423            exts.append( Extension('syslog', ['syslogmodule.c']) )
424
425        # George Neville-Neil's timing module:
426        exts.append( Extension('timing', ['timingmodule.c']) )
427
428        #
429        # Here ends the simple stuff.  From here on, modules need certain
430        # libraries, are platform-specific, or present other surprises.
431        #
432
433        # Multimedia modules
434        # These don't work for 64-bit platforms!!!
435        # These represent audio samples or images as strings:
436
437        # Operations on audio samples
438        # According to #993173, this one should actually work fine on
439        # 64-bit platforms.
440        exts.append( Extension('audioop', ['audioop.c']) )
441
442        # Disabled on 64-bit platforms
443        if sys.maxint != 9223372036854775807L:
444            # Operations on images
445            exts.append( Extension('imageop', ['imageop.c']) )
446            # Read SGI RGB image files (but coded portably)
447            exts.append( Extension('rgbimg', ['rgbimgmodule.c']) )
448
449        # readline
450        if self.compiler.find_library_file(lib_dirs, 'readline'):
451            readline_libs = ['readline']
452            if self.compiler.find_library_file(lib_dirs,
453                                                 'ncurses'):
454                readline_libs.append('ncurses')
455            elif self.compiler.find_library_file(lib_dirs, 'curses'):
456                readline_libs.append('curses')
457            elif self.compiler.find_library_file(lib_dirs +
458                                               ['/usr/lib/termcap'],
459                                               'termcap'):
460                readline_libs.append('termcap')
461            exts.append( Extension('readline', ['readline.c'],
462                                   library_dirs=['/usr/lib/termcap'],
463                                   libraries=readline_libs) )
464        if platform not in ['mac']:
465            # crypt module.
466
467            if self.compiler.find_library_file(lib_dirs, 'crypt'):
468                libs = ['crypt']
469            else:
470                libs = []
471            exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) )
472
473        # CSV files
474        exts.append( Extension('_csv', ['_csv.c']) )
475
476        # socket(2)
477        exts.append( Extension('_socket', ['socketmodule.c'],
478                               depends = ['socketmodule.h']) )
479        # Detect SSL support for the socket module (via _ssl)
480        search_for_ssl_incs_in = [
481                              '/usr/local/ssl/include',
482                              '/usr/contrib/ssl/include/'
483                             ]
484        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
485                             search_for_ssl_incs_in
486                             )
487        if ssl_incs is not None:
488            krb5_h = find_file('krb5.h', inc_dirs,
489                               ['/usr/kerberos/include'])
490            if krb5_h:
491                ssl_incs += krb5_h
492        ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
493                                     ['/usr/local/ssl/lib',
494                                      '/usr/contrib/ssl/lib/'
495                                     ] )
496
497        if (ssl_incs is not None and
498            ssl_libs is not None):
499            exts.append( Extension('_ssl', ['_ssl.c'],
500                                   include_dirs = ssl_incs,
501                                   library_dirs = ssl_libs,
502                                   libraries = ['ssl', 'crypto'],
503                                   depends = ['socketmodule.h']), )
504
505        # find out which version of OpenSSL we have
506        openssl_ver = 0
507        openssl_ver_re = re.compile(
508            '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' )
509        for ssl_inc_dir in inc_dirs + search_for_ssl_incs_in:
510            name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h')
511            if os.path.isfile(name):
512                try:
513                    incfile = open(name, 'r')
514                    for line in incfile:
515                        m = openssl_ver_re.match(line)
516                        if m:
517                            openssl_ver = eval(m.group(1))
518                            break
519                except IOError:
520                    pass
521
522            # first version found is what we'll use (as the compiler should)
523            if openssl_ver:
524                break
525
526        #print 'openssl_ver = 0x%08x' % openssl_ver
527
528        if (ssl_incs is not None and
529            ssl_libs is not None and
530            openssl_ver >= 0x00907000):
531            # The _hashlib module wraps optimized implementations
532            # of hash functions from the OpenSSL library.
533            exts.append( Extension('_hashlib', ['_hashopenssl.c'],
534                                   include_dirs = ssl_incs,
535                                   library_dirs = ssl_libs,
536                                   libraries = ['ssl', 'crypto']) )
537        else:
538            # The _sha module implements the SHA1 hash algorithm.
539            exts.append( Extension('_sha', ['shamodule.c']) )
540            # The _md5 module implements the RSA Data Security, Inc. MD5
541            # Message-Digest Algorithm, described in RFC 1321.  The
542            # necessary files md5c.c and md5.h are included here.
543            exts.append( Extension('_md5', ['md5module.c', 'md5c.c']) )
544
545        if (openssl_ver < 0x00908000):
546            # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash
547            exts.append( Extension('_sha256', ['sha256module.c']) )
548            exts.append( Extension('_sha512', ['sha512module.c']) )
549
550
551        # Modules that provide persistent dictionary-like semantics.  You will
552        # probably want to arrange for at least one of them to be available on
553        # your machine, though none are defined by default because of library
554        # dependencies.  The Python module anydbm.py provides an
555        # implementation independent wrapper for these; dumbdbm.py provides
556        # similar functionality (but slower of course) implemented in Python.
557
558        # Sleepycat Berkeley DB interface.  http://www.sleepycat.com
559        #
560        # This requires the Sleepycat DB code. The earliest supported version
561        # of that library is 3.2, the latest supported version is 4.4.  A list
562        # of available releases can be found at
563        #
564        # http://www.sleepycat.com/update/index.html
565
566        max_db_ver = (4, 4)
567        min_db_ver = (3, 2)
568        db_setup_debug = False   # verbose debug prints from this script?
569
570        # construct a list of paths to look for the header file in on
571        # top of the normal inc_dirs.
572        db_inc_paths = [
573            '/usr/include/db4',
574            '/usr/local/include/db4',
575            '/opt/sfw/include/db4',
576            '/sw/include/db4',
577            '/usr/include/db3',
578            '/usr/local/include/db3',
579            '/opt/sfw/include/db3',
580            '/sw/include/db3',
581        ]
582        # 4.x minor number specific paths
583        for x in (0,1,2,3,4):
584            db_inc_paths.append('/usr/include/db4%d' % x)
585            db_inc_paths.append('/usr/include/db4.%d' % x)
586            db_inc_paths.append('/usr/local/BerkeleyDB.4.%d/include' % x)
587            db_inc_paths.append('/usr/local/include/db4%d' % x)
588            db_inc_paths.append('/pkg/db-4.%d/include' % x)
589            db_inc_paths.append('/opt/db-4.%d/include' % x)
590        # 3.x minor number specific paths
591        for x in (2,3):
592            db_inc_paths.append('/usr/include/db3%d' % x)
593            db_inc_paths.append('/usr/local/BerkeleyDB.3.%d/include' % x)
594            db_inc_paths.append('/usr/local/include/db3%d' % x)
595            db_inc_paths.append('/pkg/db-3.%d/include' % x)
596            db_inc_paths.append('/opt/db-3.%d/include' % x)
597
598        db_ver_inc_map = {}
599
600        class db_found(Exception): pass
601        try:
602            # See whether there is a Sleepycat header in the standard
603            # search path.
604            for d in inc_dirs + db_inc_paths:
605                f = os.path.join(d, "db.h")
606                if db_setup_debug: print "db: looking for db.h in", f
607                if os.path.exists(f):
608                    f = open(f).read()
609                    m = re.search(r"#define\WDB_VERSION_MAJOR\W(\d+)", f)
610                    if m:
611                        db_major = int(m.group(1))
612                        m = re.search(r"#define\WDB_VERSION_MINOR\W(\d+)", f)
613                        db_minor = int(m.group(1))
614                        db_ver = (db_major, db_minor)
615
616                        if ( (not db_ver_inc_map.has_key(db_ver)) and
617                           (db_ver <= max_db_ver and db_ver >= min_db_ver) ):
618                            # save the include directory with the db.h version
619                            # (first occurrance only)
620                            db_ver_inc_map[db_ver] = d
621                            print "db.h: found", db_ver, "in", d
622                        else:
623                            # we already found a header for this library version
624                            if db_setup_debug: print "db.h: ignoring", d
625                    else:
626                        # ignore this header, it didn't contain a version number
627                        if db_setup_debug: print "db.h: unsupported version", db_ver, "in", d
628
629            db_found_vers = db_ver_inc_map.keys()
630            db_found_vers.sort()
631
632            while db_found_vers:
633                db_ver = db_found_vers.pop()
634                db_incdir = db_ver_inc_map[db_ver]
635
636                # check lib directories parallel to the location of the header
637                db_dirs_to_check = [
638                    os.path.join(db_incdir, '..', 'lib64'),
639                    os.path.join(db_incdir, '..', 'lib'),
640                    os.path.join(db_incdir, '..', '..', 'lib64'),
641                    os.path.join(db_incdir, '..', '..', 'lib'),
642                ]
643                db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check)
644
645                # Look for a version specific db-X.Y before an ambiguoius dbX
646                # XXX should we -ever- look for a dbX name?  Do any
647                # systems really not name their library by version and
648                # symlink to more general names?
649                for dblib in (('db-%d.%d' % db_ver),
650                              ('db%d%d' % db_ver),
651                              ('db%d' % db_ver[0])):
652                    dblib_file = self.compiler.find_library_file(
653                                    db_dirs_to_check + lib_dirs, dblib )
654                    if dblib_file:
655                        dblib_dir = [ os.path.abspath(os.path.dirname(dblib_file)) ]
656                        raise db_found
657                    else:
658                        if db_setup_debug: print "db lib: ", dblib, "not found"
659
660        except db_found:
661            print "db lib: using", db_ver, dblib
662            if db_setup_debug: print "db: lib dir", dblib_dir, "inc dir", db_incdir
663            db_incs = [db_incdir]
664            dblibs = [dblib]
665            # We add the runtime_library_dirs argument because the
666            # BerkeleyDB lib we're linking against often isn't in the
667            # system dynamic library search path.  This is usually
668            # correct and most trouble free, but may cause problems in
669            # some unusual system configurations (e.g. the directory
670            # is on an NFS server that goes away).
671            exts.append(Extension('_bsddb', ['_bsddb.c'],
672                                  library_dirs=dblib_dir,
673                                  runtime_library_dirs=dblib_dir,
674                                  include_dirs=db_incs,
675                                  libraries=dblibs))
676        else:
677            if db_setup_debug: print "db: no appropriate library found"
678            db_incs = None
679            dblibs = []
680            dblib_dir = None
681
682
683        # Look for Berkeley db 1.85.   Note that it is built as a different
684        # module name so it can be included even when later versions are
685        # available.  A very restrictive search is performed to avoid
686        # accidentally building this module with a later version of the
687        # underlying db library.  May BSD-ish Unixes incorporate db 1.85
688        # symbols into libc and place the include file in /usr/include.
689        f = "/usr/include/db.h"
690        if os.path.exists(f):
691            data = open(f).read()
692            m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data)
693            if m is not None:
694                # bingo - old version used hash file format version 2
695                ### XXX this should be fixed to not be platform-dependent
696                ### but I don't have direct access to an osf1 platform and
697                ### seemed to be muffing the search somehow
698                libraries = platform == "osf1" and ['db'] or None
699                if libraries is not None:
700                    exts.append(Extension('bsddb185', ['bsddbmodule.c'],
701                                          libraries=libraries))
702                else:
703                    exts.append(Extension('bsddb185', ['bsddbmodule.c']))
704
705        # The standard Unix dbm module:
706        if platform not in ['cygwin']:
707            if find_file("ndbm.h", inc_dirs, []) is not None:
708                # Some systems have -lndbm, others don't
709                if self.compiler.find_library_file(lib_dirs, 'ndbm'):
710                    ndbm_libs = ['ndbm']
711                else:
712                    ndbm_libs = []
713                exts.append( Extension('dbm', ['dbmmodule.c'],
714                                       define_macros=[('HAVE_NDBM_H',None)],
715                                       libraries = ndbm_libs ) )
716            elif (self.compiler.find_library_file(lib_dirs, 'gdbm')
717                  and find_file("gdbm/ndbm.h", inc_dirs, []) is not None):
718                exts.append( Extension('dbm', ['dbmmodule.c'],
719                                       define_macros=[('HAVE_GDBM_NDBM_H',None)],
720                                       libraries = ['gdbm'] ) )
721            elif db_incs is not None:
722                exts.append( Extension('dbm', ['dbmmodule.c'],
723                                       library_dirs=dblib_dir,
724                                       runtime_library_dirs=dblib_dir,
725                                       include_dirs=db_incs,
726                                       define_macros=[('HAVE_BERKDB_H',None),
727                                                      ('DB_DBM_HSEARCH',None)],
728                                       libraries=dblibs))
729
730        # Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:
731        if (self.compiler.find_library_file(lib_dirs, 'gdbm')):
732            exts.append( Extension('gdbm', ['gdbmmodule.c'],
733                                   libraries = ['gdbm'] ) )
734
735        # Unix-only modules
736        if platform not in ['mac', 'win32']:
737            # Steen Lumholt's termios module
738            exts.append( Extension('termios', ['termios.c']) )
739            # Jeremy Hylton's rlimit interface
740            if platform not in ['atheos']:
741                exts.append( Extension('resource', ['resource.c']) )
742
743            # Sun yellow pages. Some systems have the functions in libc.
744            if platform not in ['cygwin', 'atheos']:
745                if (self.compiler.find_library_file(lib_dirs, 'nsl')):
746                    libs = ['nsl']
747                else:
748                    libs = []
749                exts.append( Extension('nis', ['nismodule.c'],
750                                       libraries = libs) )
751
752        # Curses support, requiring the System V version of curses, often
753        # provided by the ncurses library.
754        if (self.compiler.find_library_file(lib_dirs, 'ncurses')):
755            curses_libs = ['ncurses']
756            exts.append( Extension('_curses', ['_cursesmodule.c'],
757                                   libraries = curses_libs) )
758        elif (self.compiler.find_library_file(lib_dirs, 'curses')
759              and platform != 'darwin'):
760                # OSX has an old Berkeley curses, not good enough for
761                # the _curses module.
762            if (self.compiler.find_library_file(lib_dirs, 'terminfo')):
763                curses_libs = ['curses', 'terminfo']
764            elif (self.compiler.find_library_file(lib_dirs, 'termcap')):
765                curses_libs = ['curses', 'termcap']
766            else:
767                curses_libs = ['curses']
768
769            exts.append( Extension('_curses', ['_cursesmodule.c'],
770                                   libraries = curses_libs) )
771
772        # If the curses module is enabled, check for the panel module
773        if (module_enabled(exts, '_curses') and
774            self.compiler.find_library_file(lib_dirs, 'panel')):
775            exts.append( Extension('_curses_panel', ['_curses_panel.c'],
776                                   libraries = ['panel'] + curses_libs) )
777
778
779        # Andrew Kuchling's zlib module.  Note that some versions of zlib
780        # 1.1.3 have security problems.  See CERT Advisory CA-2002-07:
781        # http://www.cert.org/advisories/CA-2002-07.html
782        #
783        # zlib 1.1.4 is fixed, but at least one vendor (RedHat) has decided to
784        # patch its zlib 1.1.3 package instead of upgrading to 1.1.4.  For
785        # now, we still accept 1.1.3, because we think it's difficult to
786        # exploit this in Python, and we'd rather make it RedHat's problem
787        # than our problem <wink>.
788        #
789        # You can upgrade zlib to version 1.1.4 yourself by going to
790        # http://www.gzip.org/zlib/
791        zlib_inc = find_file('zlib.h', [], inc_dirs)
792        if zlib_inc is not None:
793            zlib_h = zlib_inc[0] + '/zlib.h'
794            version = '"0.0.0"'
795            version_req = '"1.1.3"'
796            fp = open(zlib_h)
797            while 1:
798                line = fp.readline()
799                if not line:
800                    break
801                if line.startswith('#define ZLIB_VERSION'):
802                    version = line.split()[2]
803                    break
804            if version >= version_req:
805                if (self.compiler.find_library_file(lib_dirs, 'z')):
806                    exts.append( Extension('zlib', ['zlibmodule.c'],
807                                           libraries = ['z']) )
808
809        # Gustavo Niemeyer's bz2 module.
810        if (self.compiler.find_library_file(lib_dirs, 'bz2')):
811            exts.append( Extension('bz2', ['bz2module.c'],
812                                   libraries = ['bz2']) )
813
814        # Interface to the Expat XML parser
815        #
816        # Expat was written by James Clark and is now maintained by a
817        # group of developers on SourceForge; see www.libexpat.org for
818        # more information.  The pyexpat module was written by Paul
819        # Prescod after a prototype by Jack Jansen.  The Expat source
820        # is included in Modules/expat/.  Usage of a system
821        # shared libexpat.so/expat.dll is not advised.
822        #
823        # More information on Expat can be found at www.libexpat.org.
824        #
825        if sys.byteorder == "little":
826            xmlbo = "1234"
827        else:
828            xmlbo = "4321"
829        expatinc = os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')
830        define_macros = [
831            ('XML_NS', '1'),
832            ('XML_DTD', '1'),
833            ('BYTEORDER', xmlbo),
834            ('XML_CONTEXT_BYTES','1024'),
835            ]
836        for feature_macro in ['HAVE_MEMMOVE', 'HAVE_BCOPY']:
837            if config_h_vars.has_key(feature_macro):
838                define_macros.append((feature_macro, '1'))
839        exts.append(Extension('pyexpat',
840                              define_macros = define_macros,
841                              include_dirs = [expatinc],
842                              sources = ['pyexpat.c',
843                                         'expat/xmlparse.c',
844                                         'expat/xmlrole.c',
845                                         'expat/xmltok.c',
846                                         ],
847                              ))
848
849        # Fredrik Lundh's cElementTree module.  Note that this also
850        # uses expat (via the CAPI hook in pyexpat).
851
852        if os.path.isfile('Modules/_elementtree.c'):
853            define_macros.append(('USE_PYEXPAT_CAPI', None))
854            exts.append(Extension('_elementtree',
855                                  define_macros = define_macros,
856                                  include_dirs = [expatinc],
857                                  sources = ['_elementtree.c'],
858                                  ))
859
860        # Hye-Shik Chang's CJKCodecs modules.
861        if have_unicode:
862            exts.append(Extension('_multibytecodec',
863                                  ['cjkcodecs/multibytecodec.c']))
864            for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'):
865                exts.append(Extension('_codecs_' + loc,
866                                      ['cjkcodecs/_codecs_%s.c' % loc]))
867
868        # Dynamic loading module
869        if sys.maxint == 0x7fffffff:
870            # This requires sizeof(int) == sizeof(long) == sizeof(char*)
871            dl_inc = find_file('dlfcn.h', [], inc_dirs)
872            if (dl_inc is not None) and (platform not in ['atheos', 'darwin']):
873                exts.append( Extension('dl', ['dlmodule.c']) )
874
875        # Platform-specific libraries
876        if platform == 'linux2':
877            # Linux-specific modules
878            exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) )
879
880        if platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6',
881                        'freebsd7'):
882            exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
883
884        if platform == 'sunos5':
885            # SunOS specific modules
886            exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) )
887
888        if platform == 'darwin' and ("--disable-toolbox-glue" not in
889            sysconfig.get_config_var("CONFIG_ARGS")):
890            # Mac OS X specific modules.
891            exts.append( Extension('_CF', ['cf/_CFmodule.c', 'cf/pycfbridge.c'],
892                        extra_link_args=['-framework', 'CoreFoundation']) )
893
894            exts.append( Extension('ColorPicker', ['ColorPickermodule.c'],
895                        extra_link_args=['-framework', 'Carbon']) )
896            exts.append( Extension('autoGIL', ['autoGIL.c'],
897                        extra_link_args=['-framework', 'CoreFoundation']) )
898            exts.append( Extension('gestalt', ['gestaltmodule.c'],
899                        extra_link_args=['-framework', 'Carbon']) )
900            exts.append( Extension('MacOS', ['macosmodule.c'],
901                        extra_link_args=['-framework', 'Carbon']) )
902            exts.append( Extension('OSATerminology', ['OSATerminology.c'],
903                        extra_link_args=['-framework', 'Carbon']) )
904            exts.append( Extension('icglue', ['icgluemodule.c'],
905                        extra_link_args=['-framework', 'Carbon']) )
906            exts.append( Extension('_Res', ['res/_Resmodule.c'],
907                        extra_link_args=['-framework', 'Carbon']) )
908            exts.append( Extension('_Snd', ['snd/_Sndmodule.c'],
909                        extra_link_args=['-framework', 'Carbon']) )
910            exts.append( Extension('Nav', ['Nav.c'],
911                    extra_link_args=['-framework', 'Carbon']) )
912            exts.append( Extension('_AE', ['ae/_AEmodule.c'],
913                    extra_link_args=['-framework', 'Carbon']) )
914            exts.append( Extension('_AH', ['ah/_AHmodule.c'],
915                    extra_link_args=['-framework', 'Carbon']) )
916            exts.append( Extension('_App', ['app/_Appmodule.c'],
917                    extra_link_args=['-framework', 'Carbon']) )
918            exts.append( Extension('_CarbonEvt', ['carbonevt/_CarbonEvtmodule.c'],
919                    extra_link_args=['-framework', 'Carbon']) )
920            exts.append( Extension('_CG', ['cg/_CGmodule.c'],
921                    extra_link_args=['-framework', 'ApplicationServices']) )
922            exts.append( Extension('_Cm', ['cm/_Cmmodule.c'],
923                    extra_link_args=['-framework', 'Carbon']) )
924            exts.append( Extension('_Ctl', ['ctl/_Ctlmodule.c'],
925                    extra_link_args=['-framework', 'Carbon']) )
926            exts.append( Extension('_Dlg', ['dlg/_Dlgmodule.c'],
927                    extra_link_args=['-framework', 'Carbon']) )
928            exts.append( Extension('_Drag', ['drag/_Dragmodule.c'],
929                    extra_link_args=['-framework', 'Carbon']) )
930            exts.append( Extension('_Evt', ['evt/_Evtmodule.c'],
931                    extra_link_args=['-framework', 'Carbon']) )
932            exts.append( Extension('_File', ['file/_Filemodule.c'],
933                    extra_link_args=['-framework', 'Carbon']) )
934            exts.append( Extension('_Folder', ['folder/_Foldermodule.c'],
935                    extra_link_args=['-framework', 'Carbon']) )
936            exts.append( Extension('_Fm', ['fm/_Fmmodule.c'],
937                    extra_link_args=['-framework', 'Carbon']) )
938            exts.append( Extension('_Help', ['help/_Helpmodule.c'],
939                    extra_link_args=['-framework', 'Carbon']) )
940            exts.append( Extension('_Icn', ['icn/_Icnmodule.c'],
941                    extra_link_args=['-framework', 'Carbon']) )
942            exts.append( Extension('_IBCarbon', ['ibcarbon/_IBCarbon.c'],
943                    extra_link_args=['-framework', 'Carbon']) )
944            exts.append( Extension('_Launch', ['launch/_Launchmodule.c'],
945                    extra_link_args=['-framework', 'ApplicationServices']) )
946            exts.append( Extension('_List', ['list/_Listmodule.c'],
947                    extra_link_args=['-framework', 'Carbon']) )
948            exts.append( Extension('_Menu', ['menu/_Menumodule.c'],
949                    extra_link_args=['-framework', 'Carbon']) )
950            exts.append( Extension('_Mlte', ['mlte/_Mltemodule.c'],
951                    extra_link_args=['-framework', 'Carbon']) )
952            exts.append( Extension('_OSA', ['osa/_OSAmodule.c'],
953                    extra_link_args=['-framework', 'Carbon']) )
954            exts.append( Extension('_Qd', ['qd/_Qdmodule.c'],
955                    extra_link_args=['-framework', 'Carbon']) )
956            exts.append( Extension('_Qdoffs', ['qdoffs/_Qdoffsmodule.c'],
957                    extra_link_args=['-framework', 'Carbon']) )
958            exts.append( Extension('_Qt', ['qt/_Qtmodule.c'],
959                    extra_link_args=['-framework', 'QuickTime',
960                                     '-framework', 'Carbon']) )
961            exts.append( Extension('_Scrap', ['scrap/_Scrapmodule.c'],
962                    extra_link_args=['-framework', 'Carbon']) )
963            exts.append( Extension('_TE', ['te/_TEmodule.c'],
964                    extra_link_args=['-framework', 'Carbon']) )
965            # As there is no standardized place (yet) to put
966            # user-installed Mac libraries on OSX, we search for "waste"
967            # in parent directories of the Python source tree. You
968            # should put a symlink to your Waste installation in the
969            # same folder as your python source tree.  Or modify the
970            # next few lines:-)
971            waste_incs = find_file("WASTE.h", [],
972                    ['../'*n + 'waste/C_C++ Headers' for n in (0,1,2,3,4)])
973            waste_libs = find_library_file(self.compiler, "WASTE", [],
974                    ["../"*n + "waste/Static Libraries" for n in (0,1,2,3,4)])
975            if waste_incs != None and waste_libs != None:
976                (srcdir,) = sysconfig.get_config_vars('srcdir')
977                exts.append( Extension('waste',
978                               ['waste/wastemodule.c'] + [
979                                os.path.join(srcdir, d) for d in
980                                'Mac/Wastemods/WEObjectHandlers.c',
981                                'Mac/Wastemods/WETabHooks.c',
982                                'Mac/Wastemods/WETabs.c'
983                               ],
984                               include_dirs = waste_incs + [os.path.join(srcdir, 'Mac/Wastemods')],
985                               library_dirs = waste_libs,
986                               libraries = ['WASTE'],
987                               extra_link_args = ['-framework', 'Carbon'],
988                ) )
989            exts.append( Extension('_Win', ['win/_Winmodule.c'],
990                    extra_link_args=['-framework', 'Carbon']) )
991
992        self.extensions.extend(exts)
993
994        # Call the method for detecting whether _tkinter can be compiled
995        self.detect_tkinter(inc_dirs, lib_dirs)
996
997    def detect_tkinter_darwin(self, inc_dirs, lib_dirs):
998        # The _tkinter module, using frameworks. Since frameworks are quite
999        # different the UNIX search logic is not sharable.
1000        from os.path import join, exists
1001        framework_dirs = [
1002            '/System/Library/Frameworks/',
1003            '/Library/Frameworks',
1004            join(os.getenv('HOME'), '/Library/Frameworks')
1005        ]
1006
1007        # Find the directory that contains the Tcl.framework and Tk.framework
1008        # bundles.
1009        # XXX distutils should support -F!
1010        for F in framework_dirs:
1011            # both Tcl.framework and Tk.framework should be present
1012            for fw in 'Tcl', 'Tk':
1013                if not exists(join(F, fw + '.framework')):
1014                    break
1015            else:
1016                # ok, F is now directory with both frameworks. Continure
1017                # building
1018                break
1019        else:
1020            # Tk and Tcl frameworks not found. Normal "unix" tkinter search
1021            # will now resume.
1022            return 0
1023
1024        # For 8.4a2, we must add -I options that point inside the Tcl and Tk
1025        # frameworks. In later release we should hopefully be able to pass
1026        # the -F option to gcc, which specifies a framework lookup path.
1027        #
1028        include_dirs = [
1029            join(F, fw + '.framework', H)
1030            for fw in 'Tcl', 'Tk'
1031            for H in 'Headers', 'Versions/Current/PrivateHeaders'
1032        ]
1033
1034        # For 8.4a2, the X11 headers are not included. Rather than include a
1035        # complicated search, this is a hard-coded path. It could bail out
1036        # if X11 libs are not found...
1037        include_dirs.append('/usr/X11R6/include')
1038        frameworks = ['-framework', 'Tcl', '-framework', 'Tk']
1039
1040        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1041                        define_macros=[('WITH_APPINIT', 1)],
1042                        include_dirs = include_dirs,
1043                        libraries = [],
1044                        extra_compile_args = frameworks,
1045                        extra_link_args = frameworks,
1046                        )
1047        self.extensions.append(ext)
1048        return 1
1049
1050
1051    def detect_tkinter(self, inc_dirs, lib_dirs):
1052        # The _tkinter module.
1053
1054        # Rather than complicate the code below, detecting and building
1055        # AquaTk is a separate method. Only one Tkinter will be built on
1056        # Darwin - either AquaTk, if it is found, or X11 based Tk.
1057        platform = self.get_platform()
1058        if (platform == 'darwin' and
1059            self.detect_tkinter_darwin(inc_dirs, lib_dirs)):
1060            return
1061
1062        # Assume we haven't found any of the libraries or include files
1063        # The versions with dots are used on Unix, and the versions without
1064        # dots on Windows, for detection by cygwin.
1065        tcllib = tklib = tcl_includes = tk_includes = None
1066        for version in ['8.5', '85', '8.4', '84', '8.3', '83', '8.2',
1067                        '82', '8.1', '81', '8.0', '80']:
1068            tklib = self.compiler.find_library_file(lib_dirs, 'tk' + version)
1069            tcllib = self.compiler.find_library_file(lib_dirs, 'tcl' + version)
1070            if tklib and tcllib:
1071                # Exit the loop when we've found the Tcl/Tk libraries
1072                break
1073
1074        # Now check for the header files
1075        if tklib and tcllib:
1076            # Check for the include files on Debian and {Free,Open}BSD, where
1077            # they're put in /usr/include/{tcl,tk}X.Y
1078            dotversion = version
1079            if '.' not in dotversion and "bsd" in sys.platform.lower():
1080                # OpenBSD and FreeBSD use Tcl/Tk library names like libtcl83.a,
1081                # but the include subdirs are named like .../include/tcl8.3.
1082                dotversion = dotversion[:-1] + '.' + dotversion[-1]
1083            tcl_include_sub = []
1084            tk_include_sub = []
1085            for dir in inc_dirs:
1086                tcl_include_sub += [dir + os.sep + "tcl" + dotversion]
1087                tk_include_sub += [dir + os.sep + "tk" + dotversion]
1088            tk_include_sub += tcl_include_sub
1089            tcl_includes = find_file('tcl.h', inc_dirs, tcl_include_sub)
1090            tk_includes = find_file('tk.h', inc_dirs, tk_include_sub)
1091
1092        if (tcllib is None or tklib is None or
1093            tcl_includes is None or tk_includes is None):
1094            self.announce("INFO: Can't locate Tcl/Tk libs and/or headers", 2)
1095            return
1096
1097        # OK... everything seems to be present for Tcl/Tk.
1098
1099        include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = []
1100        for dir in tcl_includes + tk_includes:
1101            if dir not in include_dirs:
1102                include_dirs.append(dir)
1103
1104        # Check for various platform-specific directories
1105        if platform == 'sunos5':
1106            include_dirs.append('/usr/openwin/include')
1107            added_lib_dirs.append('/usr/openwin/lib')
1108        elif os.path.exists('/usr/X11R6/include'):
1109            include_dirs.append('/usr/X11R6/include')
1110            added_lib_dirs.append('/usr/X11R6/lib64')
1111            added_lib_dirs.append('/usr/X11R6/lib')
1112        elif os.path.exists('/usr/X11R5/include'):
1113            include_dirs.append('/usr/X11R5/include')
1114            added_lib_dirs.append('/usr/X11R5/lib')
1115        else:
1116            # Assume default location for X11
1117            include_dirs.append('/usr/X11/include')
1118            added_lib_dirs.append('/usr/X11/lib')
1119
1120        # If Cygwin, then verify that X is installed before proceeding
1121        if platform == 'cygwin':
1122            x11_inc = find_file('X11/Xlib.h', [], include_dirs)
1123            if x11_inc is None:
1124                return
1125
1126        # Check for BLT extension
1127        if self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1128                                           'BLT8.0'):
1129            defs.append( ('WITH_BLT', 1) )
1130            libs.append('BLT8.0')
1131        elif self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1132                                           'BLT'):
1133            defs.append( ('WITH_BLT', 1) )
1134            libs.append('BLT')
1135
1136        # Add the Tcl/Tk libraries
1137        libs.append('tk'+ version)
1138        libs.append('tcl'+ version)
1139
1140        if platform in ['aix3', 'aix4']:
1141            libs.append('ld')
1142
1143        # Finally, link with the X11 libraries (not appropriate on cygwin)
1144        if platform != "cygwin":
1145            libs.append('X11')
1146
1147        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1148                        define_macros=[('WITH_APPINIT', 1)] + defs,
1149                        include_dirs = include_dirs,
1150                        libraries = libs,
1151                        library_dirs = added_lib_dirs,
1152                        )
1153        self.extensions.append(ext)
1154
1155##         # Uncomment these lines if you want to play with xxmodule.c
1156##         ext = Extension('xx', ['xxmodule.c'])
1157##         self.extensions.append(ext)
1158
1159        # XXX handle these, but how to detect?
1160        # *** Uncomment and edit for PIL (TkImaging) extension only:
1161        #       -DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \
1162        # *** Uncomment and edit for TOGL extension only:
1163        #       -DWITH_TOGL togl.c \
1164        # *** Uncomment these for TOGL extension only:
1165        #       -lGL -lGLU -lXext -lXmu \
1166
1167class PyBuildInstall(install):
1168    # Suppress the warning about installation into the lib_dynload
1169    # directory, which is not in sys.path when running Python during
1170    # installation:
1171    def initialize_options (self):
1172        install.initialize_options(self)
1173        self.warn_dir=0
1174
1175class PyBuildInstallLib(install_lib):
1176    # Do exactly what install_lib does but make sure correct access modes get
1177    # set on installed directories and files. All installed files with get
1178    # mode 644 unless they are a shared library in which case they will get
1179    # mode 755. All installed directories will get mode 755.
1180
1181    so_ext = sysconfig.get_config_var("SO")
1182
1183    def install(self):
1184        outfiles = install_lib.install(self)
1185        self.set_file_modes(outfiles, 0644, 0755)
1186        self.set_dir_modes(self.install_dir, 0755)
1187        return outfiles
1188
1189    def set_file_modes(self, files, defaultMode, sharedLibMode):
1190        if not self.is_chmod_supported(): return
1191        if not files: return
1192
1193        for filename in files:
1194            if os.path.islink(filename): continue
1195            mode = defaultMode
1196            if filename.endswith(self.so_ext): mode = sharedLibMode
1197            log.info("changing mode of %s to %o", filename, mode)
1198            if not self.dry_run: os.chmod(filename, mode)
1199
1200    def set_dir_modes(self, dirname, mode):
1201        if not self.is_chmod_supported(): return
1202        os.path.walk(dirname, self.set_dir_modes_visitor, mode)
1203
1204    def set_dir_modes_visitor(self, mode, dirname, names):
1205        if os.path.islink(dirname): return
1206        log.info("changing mode of %s to %o", dirname, mode)
1207        if not self.dry_run: os.chmod(dirname, mode)
1208
1209    def is_chmod_supported(self):
1210        return hasattr(os, 'chmod')
1211
1212SUMMARY = """
1213Python is an interpreted, interactive, object-oriented programming
1214language. It is often compared to Tcl, Perl, Scheme or Java.
1215
1216Python combines remarkable power with very clear syntax. It has
1217modules, classes, exceptions, very high level dynamic data types, and
1218dynamic typing. There are interfaces to many system calls and
1219libraries, as well as to various windowing systems (X11, Motif, Tk,
1220Mac, MFC). New built-in modules are easily written in C or C++. Python
1221is also usable as an extension language for applications that need a
1222programmable interface.
1223
1224The Python implementation is portable: it runs on many brands of UNIX,
1225on Windows, DOS, OS/2, Mac, Amiga... If your favorite system isn't
1226listed here, it may still be supported, if there's a C compiler for
1227it. Ask around on comp.lang.python -- or just try compiling Python
1228yourself.
1229"""
1230
1231CLASSIFIERS = """
1232Development Status :: 3 - Alpha
1233Development Status :: 6 - Mature
1234License :: OSI Approved :: Python Software Foundation License
1235Natural Language :: English
1236Programming Language :: C
1237Programming Language :: Python
1238Topic :: Software Development
1239"""
1240
1241def main():
1242    # turn off warnings when deprecated modules are imported
1243    import warnings
1244    warnings.filterwarnings("ignore",category=DeprecationWarning)
1245    setup(# PyPI Metadata (PEP 301)
1246          name = "Python",
1247          version = sys.version.split()[0],
1248          url = "http://www.python.org/%s" % sys.version[:3],
1249          maintainer = "Guido van Rossum and the Python community",
1250          maintainer_email = "python-dev@python.org",
1251          description = "A high-level object-oriented programming language",
1252          long_description = SUMMARY.strip(),
1253          license = "PSF license",
1254          classifiers = filter(None, CLASSIFIERS.split("\n")),
1255          platforms = ["Many"],
1256
1257          # Build info
1258          cmdclass = {'build_ext':PyBuildExt, 'install':PyBuildInstall,
1259                      'install_lib':PyBuildInstallLib},
1260          # The struct module is defined here, because build_ext won't be
1261          # called unless there's at least one extension module defined.
1262          ext_modules=[Extension('struct', ['structmodule.c'])],
1263
1264          # Scripts to install
1265          scripts = ['Tools/scripts/pydoc', 'Tools/scripts/idle',
1266                     'Lib/smtpd.py']
1267        )
1268
1269# --install-platlib
1270if __name__ == '__main__':
1271    main()
1272