setup.py revision 0c4102760c440af3e7b575b0fd27fe25549641a2
1# Autodetecting setup.py script for building the Python extensions
2#
3
4__version__ = "$Revision$"
5
6import sys, os, getopt, imp, re
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'):
123            # Mac OS X also includes some mac-specific modules
124            macmoddir = os.path.join(os.getcwd(), srcdir, 'Mac/Modules')
125            moddirlist.append(macmoddir)
126            incdirlist.append('./Mac/Include')
127
128        alldirlist = moddirlist + incdirlist
129
130        # Fix up the paths for scripts, too
131        self.distribution.scripts = [os.path.join(srcdir, filename)
132                                     for filename in self.distribution.scripts]
133
134        for ext in self.extensions[:]:
135            ext.sources = [ find_module_file(filename, moddirlist)
136                            for filename in ext.sources ]
137            if ext.depends is not None:
138                ext.depends = [find_module_file(filename, alldirlist)
139                               for filename in ext.depends]
140            ext.include_dirs.append( '.' ) # to get config.h
141            for incdir in incdirlist:
142                ext.include_dirs.append( os.path.join(srcdir, incdir) )
143
144            # If a module has already been built statically,
145            # don't build it here
146            if ext.name in sys.builtin_module_names:
147                self.extensions.remove(ext)
148
149        if platform != 'mac':
150            # Parse Modules/Setup to figure out which modules are turned
151            # on in the file.
152            input = text_file.TextFile('Modules/Setup', join_lines=1)
153            remove_modules = []
154            while 1:
155                line = input.readline()
156                if not line: break
157                line = line.split()
158                remove_modules.append( line[0] )
159            input.close()
160
161            for ext in self.extensions[:]:
162                if ext.name in remove_modules:
163                    self.extensions.remove(ext)
164
165        # When you run "make CC=altcc" or something similar, you really want
166        # those environment variables passed into the setup.py phase.  Here's
167        # a small set of useful ones.
168        compiler = os.environ.get('CC')
169        linker_so = os.environ.get('LDSHARED')
170        args = {}
171        # unfortunately, distutils doesn't let us provide separate C and C++
172        # compilers
173        if compiler is not None:
174            (ccshared,opt,base) = sysconfig.get_config_vars('CCSHARED','OPT','BASECFLAGS')
175            args['compiler_so'] = compiler + ' ' + opt + ' ' + ccshared + ' ' + base
176        if linker_so is not None:
177            args['linker_so'] = linker_so
178        self.compiler.set_executables(**args)
179
180        build_ext.build_extensions(self)
181
182    def build_extension(self, ext):
183
184        try:
185            build_ext.build_extension(self, ext)
186        except (CCompilerError, DistutilsError), why:
187            self.announce('WARNING: building of extension "%s" failed: %s' %
188                          (ext.name, sys.exc_info()[1]))
189            return
190        # Workaround for Mac OS X: The Carbon-based modules cannot be
191        # reliably imported into a command-line Python
192        if 'Carbon' in ext.extra_link_args:
193            self.announce(
194                'WARNING: skipping import check for Carbon-based "%s"' %
195                ext.name)
196            return
197        # Workaround for Cygwin: Cygwin currently has fork issues when many
198        # modules have been imported
199        if self.get_platform() == 'cygwin':
200            self.announce('WARNING: skipping import check for Cygwin-based "%s"'
201                % ext.name)
202            return
203        ext_filename = os.path.join(
204            self.build_lib,
205            self.get_ext_filename(self.get_ext_fullname(ext.name)))
206        try:
207            imp.load_dynamic(ext.name, ext_filename)
208        except ImportError, why:
209            self.announce('*** WARNING: renaming "%s" since importing it'
210                          ' failed: %s' % (ext.name, why), level=3)
211            assert not self.inplace
212            basename, tail = os.path.splitext(ext_filename)
213            newname = basename + "_failed" + tail
214            if os.path.exists(newname):
215                os.remove(newname)
216            os.rename(ext_filename, newname)
217
218            # XXX -- This relies on a Vile HACK in
219            # distutils.command.build_ext.build_extension().  The
220            # _built_objects attribute is stored there strictly for
221            # use here.
222            # If there is a failure, _built_objects may not be there,
223            # so catch the AttributeError and move on.
224            try:
225                for filename in self._built_objects:
226                    os.remove(filename)
227            except AttributeError:
228                self.announce('unable to remove files (ignored)')
229        except:
230            exc_type, why, tb = sys.exc_info()
231            self.announce('*** WARNING: importing extension "%s" '
232                          'failed with %s: %s' % (ext.name, exc_type, why),
233                          level=3)
234
235    def get_platform(self):
236        # Get value of sys.platform
237        for platform in ['cygwin', 'beos', 'darwin', 'atheos', 'osf1']:
238            if sys.platform.startswith(platform):
239                return platform
240        return sys.platform
241
242    def detect_modules(self):
243        # Ensure that /usr/local is always used
244        add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
245        add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
246
247        # fink installs lots of goodies in /sw/... - make sure we
248        # check there
249        if sys.platform == "darwin":
250            add_dir_to_list(self.compiler.library_dirs, '/sw/lib')
251            add_dir_to_list(self.compiler.include_dirs, '/sw/include')
252
253        if os.path.normpath(sys.prefix) != '/usr':
254            add_dir_to_list(self.compiler.library_dirs,
255                            sysconfig.get_config_var("LIBDIR"))
256            add_dir_to_list(self.compiler.include_dirs,
257                            sysconfig.get_config_var("INCLUDEDIR"))
258
259        try:
260            have_unicode = unicode
261        except NameError:
262            have_unicode = 0
263
264        # lib_dirs and inc_dirs are used to search for files;
265        # if a file is found in one of those directories, it can
266        # be assumed that no additional -I,-L directives are needed.
267        lib_dirs = self.compiler.library_dirs + ['/lib', '/usr/lib']
268        inc_dirs = self.compiler.include_dirs + ['/usr/include']
269        exts = []
270
271        platform = self.get_platform()
272        (srcdir,) = sysconfig.get_config_vars('srcdir')
273
274        # Check for AtheOS which has libraries in non-standard locations
275        if platform == 'atheos':
276            lib_dirs += ['/system/libs', '/atheos/autolnk/lib']
277            lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep)
278            inc_dirs += ['/system/include', '/atheos/autolnk/include']
279            inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep)
280
281        # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
282        if platform in ['osf1', 'unixware7', 'openunix8']:
283            lib_dirs += ['/usr/ccs/lib']
284
285        # Check for MacOS X, which doesn't need libm.a at all
286        math_libs = ['m']
287        if platform in ['darwin', 'beos', 'mac']:
288            math_libs = []
289
290        # XXX Omitted modules: gl, pure, dl, SGI-specific modules
291
292        #
293        # The following modules are all pretty straightforward, and compile
294        # on pretty much any POSIXish platform.
295        #
296
297        # Some modules that are normally always on:
298        exts.append( Extension('regex', ['regexmodule.c', 'regexpr.c']) )
299        exts.append( Extension('pcre', ['pcremodule.c', 'pypcre.c']) )
300
301        exts.append( Extension('_hotshot', ['_hotshot.c']) )
302        exts.append( Extension('_weakref', ['_weakref.c']) )
303        exts.append( Extension('xreadlines', ['xreadlinesmodule.c']) )
304
305        # array objects
306        exts.append( Extension('array', ['arraymodule.c']) )
307        # complex math library functions
308        exts.append( Extension('cmath', ['cmathmodule.c'],
309                               libraries=math_libs) )
310
311        # math library functions, e.g. sin()
312        exts.append( Extension('math',  ['mathmodule.c'],
313                               libraries=math_libs) )
314        # fast string operations implemented in C
315        exts.append( Extension('strop', ['stropmodule.c']) )
316        # time operations and variables
317        exts.append( Extension('time', ['timemodule.c'],
318                               libraries=math_libs) )
319        exts.append( Extension('datetime', ['datetimemodule.c'],
320                               libraries=math_libs) )
321        # random number generator implemented in C
322        exts.append( Extension("_random", ["_randommodule.c"]) )
323        # fast iterator tools implemented in C
324        exts.append( Extension("itertools", ["itertoolsmodule.c"]) )
325        # bisect
326        exts.append( Extension("_bisect", ["_bisectmodule.c"]) )
327        # heapq
328        exts.append( Extension("heapq", ["heapqmodule.c"]) )
329        # operator.add() and similar goodies
330        exts.append( Extension('operator', ['operator.c']) )
331        # Python C API test module
332        exts.append( Extension('_testcapi', ['_testcapimodule.c']) )
333        # static Unicode character database
334        if have_unicode:
335            exts.append( Extension('unicodedata', ['unicodedata.c']) )
336        # access to ISO C locale support
337        data = open('pyconfig.h').read()
338        m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data)
339        if m is not None:
340            locale_libs = ['intl']
341        else:
342            locale_libs = []
343        exts.append( Extension('_locale', ['_localemodule.c'],
344                               libraries=locale_libs ) )
345
346        # Modules with some UNIX dependencies -- on by default:
347        # (If you have a really backward UNIX, select and socket may not be
348        # supported...)
349
350        # fcntl(2) and ioctl(2)
351        exts.append( Extension('fcntl', ['fcntlmodule.c']) )
352        if platform not in ['mac']:
353                # pwd(3)
354            exts.append( Extension('pwd', ['pwdmodule.c']) )
355            # grp(3)
356            exts.append( Extension('grp', ['grpmodule.c']) )
357        # select(2); not on ancient System V
358        exts.append( Extension('select', ['selectmodule.c']) )
359
360        # The md5 module implements the RSA Data Security, Inc. MD5
361        # Message-Digest Algorithm, described in RFC 1321.  The
362        # necessary files md5c.c and md5.h are included here.
363        exts.append( Extension('md5', ['md5module.c', 'md5c.c']) )
364
365        # The sha module implements the SHA checksum algorithm.
366        # (NIST's Secure Hash Algorithm.)
367        exts.append( Extension('sha', ['shamodule.c']) )
368
369        # Helper module for various ascii-encoders
370        exts.append( Extension('binascii', ['binascii.c']) )
371
372        # Fred Drake's interface to the Python parser
373        exts.append( Extension('parser', ['parsermodule.c']) )
374
375        # cStringIO and cPickle
376        exts.append( Extension('cStringIO', ['cStringIO.c']) )
377        exts.append( Extension('cPickle', ['cPickle.c']) )
378
379        # Memory-mapped files (also works on Win32).
380        if platform not in ['atheos', 'mac']:
381            exts.append( Extension('mmap', ['mmapmodule.c']) )
382
383        # Lance Ellinghaus's modules:
384        # enigma-inspired encryption
385        exts.append( Extension('rotor', ['rotormodule.c']) )
386        if platform not in ['mac']:
387            # syslog daemon interface
388            exts.append( Extension('syslog', ['syslogmodule.c']) )
389
390        # George Neville-Neil's timing module:
391        exts.append( Extension('timing', ['timingmodule.c']) )
392
393        #
394        # Here ends the simple stuff.  From here on, modules need certain
395        # libraries, are platform-specific, or present other surprises.
396        #
397
398        # Multimedia modules
399        # These don't work for 64-bit platforms!!!
400        # These represent audio samples or images as strings:
401
402        # Disabled on 64-bit platforms
403        if sys.maxint != 9223372036854775807L:
404            # Operations on audio samples
405            exts.append( Extension('audioop', ['audioop.c']) )
406            # Operations on images
407            exts.append( Extension('imageop', ['imageop.c']) )
408            # Read SGI RGB image files (but coded portably)
409            exts.append( Extension('rgbimg', ['rgbimgmodule.c']) )
410
411        # readline
412        if self.compiler.find_library_file(lib_dirs, 'readline'):
413            readline_libs = ['readline']
414            if self.compiler.find_library_file(lib_dirs,
415                                                 'ncurses'):
416                readline_libs.append('ncurses')
417            elif self.compiler.find_library_file(lib_dirs, 'curses'):
418                readline_libs.append('curses')
419            elif self.compiler.find_library_file(lib_dirs +
420                                               ['/usr/lib/termcap'],
421                                               'termcap'):
422                readline_libs.append('termcap')
423            exts.append( Extension('readline', ['readline.c'],
424                                   library_dirs=['/usr/lib/termcap'],
425                                   libraries=readline_libs) )
426        if platform not in ['mac']:
427            # crypt module.
428
429            if self.compiler.find_library_file(lib_dirs, 'crypt'):
430                libs = ['crypt']
431            else:
432                libs = []
433            exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) )
434
435        # CSV files
436        exts.append( Extension('_csv', ['_csv.c']) )
437
438        # socket(2)
439        exts.append( Extension('_socket', ['socketmodule.c'],
440                               depends = ['socketmodule.h']) )
441        # Detect SSL support for the socket module (via _ssl)
442        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
443                             ['/usr/local/ssl/include',
444                              '/usr/contrib/ssl/include/'
445                             ]
446                             )
447        if ssl_incs is not None:
448            krb5_h = find_file('krb5.h', inc_dirs,
449                               ['/usr/kerberos/include'])
450            if krb5_h:
451                ssl_incs += krb5_h
452        ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
453                                     ['/usr/local/ssl/lib',
454                                      '/usr/contrib/ssl/lib/'
455                                     ] )
456
457        if (ssl_incs is not None and
458            ssl_libs is not None):
459            exts.append( Extension('_ssl', ['_ssl.c'],
460                                   include_dirs = ssl_incs,
461                                   library_dirs = ssl_libs,
462                                   libraries = ['ssl', 'crypto'],
463                                   depends = ['socketmodule.h']), )
464
465        # Modules that provide persistent dictionary-like semantics.  You will
466        # probably want to arrange for at least one of them to be available on
467        # your machine, though none are defined by default because of library
468        # dependencies.  The Python module anydbm.py provides an
469        # implementation independent wrapper for these; dumbdbm.py provides
470        # similar functionality (but slower of course) implemented in Python.
471
472        # Sleepycat Berkeley DB interface.  http://www.sleepycat.com
473        #
474        # This requires the Sleepycat DB code. The earliest supported version
475        # of that library is 3.2, the latest supported version is 4.2.  A list
476        # of available releases can be found at
477        #
478        # http://www.sleepycat.com/update/index.html
479
480        # when sorted in reverse order, keys for this dict must appear in the
481        # order you wish to search - e.g., search for db4 before db3
482        db_try_this = {
483            'db4': {'libs': ('db-4.2', 'db42', 'db-4.1', 'db41', 'db-4.0', 'db4',),
484                    'libdirs': ('/usr/local/BerkeleyDB.4.2/lib',
485                                '/usr/local/BerkeleyDB.4.1/lib',
486                                '/usr/local/BerkeleyDB.4.0/lib',
487                                '/usr/local/lib',
488                                '/opt/sfw',
489                                '/sw/lib',
490                                ),
491                    'incdirs': ('/usr/local/BerkeleyDB.4.2/include',
492                                '/usr/local/include/db42',
493                                '/usr/local/BerkeleyDB.4.1/include',
494                                '/usr/local/include/db41',
495                                '/usr/local/BerkeleyDB.4.0/include',
496                                '/usr/local/include/db4',
497                                '/opt/sfw/include/db4',
498                                '/sw/include/db4',
499                                '/usr/include/db4',
500                                )},
501            'db3': {'libs': ('db-3.3', 'db-3.2', 'db3',),
502                    'libdirs': ('/usr/local/BerkeleyDB.3.3/lib',
503                                '/usr/local/BerkeleyDB.3.2/lib',
504                                '/usr/local/lib',
505                                '/opt/sfw/lib',
506                                '/sw/lib',
507                                ),
508                    'incdirs': ('/usr/local/BerkeleyDB.3.3/include',
509                                '/usr/local/BerkeleyDB.3.2/include',
510                                '/usr/local/include/db3',
511                                '/opt/sfw/include/db3',
512                                '/sw/include/db3',
513                                '/usr/include/db3',
514                                )},
515            }
516
517        db_search_order = db_try_this.keys()
518        db_search_order.sort()
519        db_search_order.reverse()
520
521        class found(Exception): pass
522        try:
523            # See whether there is a Sleepycat header in the standard
524            # search path.
525            std_dbinc = None
526            for d in inc_dirs:
527                f = os.path.join(d, "db.h")
528                if os.path.exists(f):
529                    f = open(f).read()
530                    m = re.search(r"#define\WDB_VERSION_MAJOR\W([1-9]+)", f)
531                    if m:
532                        std_dbinc = 'db' + m.group(1)
533            for dbkey in db_search_order:
534                dbd = db_try_this[dbkey]
535                for dblib in dbd['libs']:
536                    # Prefer version-specific includes over standard
537                    # include locations.
538                    db_incs = find_file('db.h', [], dbd['incdirs'])
539                    dblib_dir = find_library_file(self.compiler,
540                                                  dblib,
541                                                  lib_dirs,
542                                                  list(dbd['libdirs']))
543                    if (db_incs or dbkey == std_dbinc) and \
544                           dblib_dir is not None:
545                        dblibs = [dblib]
546                        raise found
547        except found:
548            dblibs = [dblib]
549            # A default source build puts Berkeley DB in something like
550            # /usr/local/Berkeley.3.3 and the lib dir under that isn't
551            # normally on ld.so's search path, unless the sysadmin has hacked
552            # /etc/ld.so.conf.  We add the directory to runtime_library_dirs
553            # so the proper -R/--rpath flags get passed to the linker.  This
554            # is usually correct and most trouble free, but may cause problems
555            # in some unusual system configurations (e.g. the directory is on
556            # an NFS server that goes away).
557            exts.append(Extension('_bsddb', ['_bsddb.c'],
558                                  library_dirs=dblib_dir,
559                                  runtime_library_dirs=dblib_dir,
560                                  include_dirs=db_incs,
561                                  libraries=dblibs))
562        else:
563            db_incs = None
564            dblibs = []
565            dblib_dir = None
566
567
568        # Look for Berkeley db 1.85.   Note that it is built as a different
569        # module name so it can be included even when later versions are
570        # available.  A very restrictive search is performed to avoid
571        # accidentally building this module with a later version of the
572        # underlying db library.  May BSD-ish Unixes incorporate db 1.85
573        # symbols into libc and place the include file in /usr/include.
574        f = "/usr/include/db.h"
575        if os.path.exists(f):
576            data = open(f).read()
577            m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data)
578            if m is not None:
579                # bingo - old version used hash file format version 2
580                ### XXX this should be fixed to not be platform-dependent
581                ### but I don't have direct access to an osf1 platform and
582                ### seemed to be muffing the search somehow
583                libraries = platform == "osf1" and ['db'] or None
584                if libraries is not None:
585                    exts.append(Extension('bsddb185', ['bsddbmodule.c'],
586                                          libraries=libraries))
587                else:
588                    exts.append(Extension('bsddb185', ['bsddbmodule.c']))
589
590        # The standard Unix dbm module:
591        if platform not in ['cygwin']:
592            if find_file("ndbm.h", inc_dirs, []) is not None:
593                # Some systems have -lndbm, others don't
594                if self.compiler.find_library_file(lib_dirs, 'ndbm'):
595                    ndbm_libs = ['ndbm']
596                else:
597                    ndbm_libs = []
598                exts.append( Extension('dbm', ['dbmmodule.c'],
599                                       define_macros=[('HAVE_NDBM_H',None)],
600                                       libraries = ndbm_libs ) )
601            elif (self.compiler.find_library_file(lib_dirs, 'gdbm')
602                  and find_file("gdbm/ndbm.h", inc_dirs, []) is not None):
603                exts.append( Extension('dbm', ['dbmmodule.c'],
604                                       define_macros=[('HAVE_GDBM_NDBM_H',None)],
605                                       libraries = ['gdbm'] ) )
606            elif db_incs is not None:
607                exts.append( Extension('dbm', ['dbmmodule.c'],
608                                       library_dirs=dblib_dir,
609                                       runtime_library_dirs=dblib_dir,
610                                       include_dirs=db_incs,
611                                       define_macros=[('HAVE_BERKDB_H',None),
612                                                      ('DB_DBM_HSEARCH',None)],
613                                       libraries=dblibs))
614
615        # Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:
616        if (self.compiler.find_library_file(lib_dirs, 'gdbm')):
617            exts.append( Extension('gdbm', ['gdbmmodule.c'],
618                                   libraries = ['gdbm'] ) )
619
620        # The mpz module interfaces to the GNU Multiple Precision library.
621        # You need to ftp the GNU MP library.
622        # This was originally written and tested against GMP 1.2 and 1.3.2.
623        # It has been modified by Rob Hooft to work with 2.0.2 as well, but I
624        # haven't tested it recently, and it definitely doesn't work with
625        # GMP 4.0.  For more complete modules, refer to
626        # http://gmpy.sourceforge.net and
627        # http://www.egenix.com/files/python/mxNumber.html
628
629        # A compatible MP library unencumbered by the GPL also exists.  It was
630        # posted to comp.sources.misc in volume 40 and is widely available from
631        # FTP archive sites. One URL for it is:
632        # ftp://gatekeeper.dec.com/.b/usenet/comp.sources.misc/volume40/fgmp/part01.Z
633
634        if (self.compiler.find_library_file(lib_dirs, 'gmp')):
635            exts.append( Extension('mpz', ['mpzmodule.c'],
636                                   libraries = ['gmp'] ) )
637
638
639        # Unix-only modules
640        if platform not in ['mac', 'win32']:
641            # Steen Lumholt's termios module
642            exts.append( Extension('termios', ['termios.c']) )
643            # Jeremy Hylton's rlimit interface
644            if platform not in ['atheos']:
645                exts.append( Extension('resource', ['resource.c']) )
646
647            # Sun yellow pages. Some systems have the functions in libc.
648            if platform not in ['cygwin', 'atheos']:
649                if (self.compiler.find_library_file(lib_dirs, 'nsl')):
650                    libs = ['nsl']
651                else:
652                    libs = []
653                exts.append( Extension('nis', ['nismodule.c'],
654                                       libraries = libs) )
655
656        # Curses support, requring the System V version of curses, often
657        # provided by the ncurses library.
658        if platform == 'sunos4':
659            inc_dirs += ['/usr/5include']
660            lib_dirs += ['/usr/5lib']
661
662        if (self.compiler.find_library_file(lib_dirs, 'ncurses')):
663            curses_libs = ['ncurses']
664            exts.append( Extension('_curses', ['_cursesmodule.c'],
665                                   libraries = curses_libs) )
666        elif (self.compiler.find_library_file(lib_dirs, 'curses')
667              and platform != 'darwin'):
668                # OSX has an old Berkeley curses, not good enough for
669                # the _curses module.
670            if (self.compiler.find_library_file(lib_dirs, 'terminfo')):
671                curses_libs = ['curses', 'terminfo']
672            elif (self.compiler.find_library_file(lib_dirs, 'termcap')):
673                curses_libs = ['curses', 'termcap']
674            else:
675                curses_libs = ['curses']
676
677            exts.append( Extension('_curses', ['_cursesmodule.c'],
678                                   libraries = curses_libs) )
679
680        # If the curses module is enabled, check for the panel module
681        if (module_enabled(exts, '_curses') and
682            self.compiler.find_library_file(lib_dirs, 'panel')):
683            exts.append( Extension('_curses_panel', ['_curses_panel.c'],
684                                   libraries = ['panel'] + curses_libs) )
685
686
687        # Andrew Kuchling's zlib module.  Note that some versions of zlib
688        # 1.1.3 have security problems.  See CERT Advisory CA-2002-07:
689        # http://www.cert.org/advisories/CA-2002-07.html
690        #
691        # zlib 1.1.4 is fixed, but at least one vendor (RedHat) has decided to
692        # patch its zlib 1.1.3 package instead of upgrading to 1.1.4.  For
693        # now, we still accept 1.1.3, because we think it's difficult to
694        # exploit this in Python, and we'd rather make it RedHat's problem
695        # than our problem <wink>.
696        #
697        # You can upgrade zlib to version 1.1.4 yourself by going to
698        # http://www.gzip.org/zlib/
699        zlib_inc = find_file('zlib.h', [], inc_dirs)
700        if zlib_inc is not None:
701            zlib_h = zlib_inc[0] + '/zlib.h'
702            version = '"0.0.0"'
703            version_req = '"1.1.3"'
704            fp = open(zlib_h)
705            while 1:
706                line = fp.readline()
707                if not line:
708                    break
709                if line.startswith('#define ZLIB_VERSION'):
710                    version = line.split()[2]
711                    break
712            if version >= version_req:
713                if (self.compiler.find_library_file(lib_dirs, 'z')):
714                    exts.append( Extension('zlib', ['zlibmodule.c'],
715                                           libraries = ['z']) )
716
717        # Gustavo Niemeyer's bz2 module.
718        if (self.compiler.find_library_file(lib_dirs, 'bz2')):
719            exts.append( Extension('bz2', ['bz2module.c'],
720                                   libraries = ['bz2']) )
721
722        # Interface to the Expat XML parser
723        #
724        # Expat was written by James Clark and is now maintained by a
725        # group of developers on SourceForge; see www.libexpat.org for
726        # more information.  The pyexpat module was written by Paul
727        # Prescod after a prototype by Jack Jansen.  The Expat source
728        # is included in Modules/expat/.  Usage of a system
729        # shared libexpat.so/expat.dll is not advised.
730        #
731        # More information on Expat can be found at www.libexpat.org.
732        #
733        if sys.byteorder == "little":
734            xmlbo = "1234"
735        else:
736            xmlbo = "4321"
737        expatinc = os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')
738        define_macros = [
739            ('XML_NS', '1'),
740            ('XML_DTD', '1'),
741            ('BYTEORDER', xmlbo),
742            ('XML_CONTEXT_BYTES','1024'),
743            ]
744        config_h = sysconfig.get_config_h_filename()
745        config_h_vars = sysconfig.parse_config_h(open(config_h))
746        for feature_macro in ['HAVE_MEMMOVE', 'HAVE_BCOPY']:
747            if config_h_vars.has_key(feature_macro):
748                define_macros.append((feature_macro, '1'))
749        exts.append(Extension('pyexpat',
750                              define_macros = define_macros,
751                              include_dirs = [expatinc],
752                              sources = ['pyexpat.c',
753                                         'expat/xmlparse.c',
754                                         'expat/xmlrole.c',
755                                         'expat/xmltok.c',
756                                         ],
757                              ))
758
759        # Dynamic loading module
760        if sys.maxint == 0x7fffffff:
761            # This requires sizeof(int) == sizeof(long) == sizeof(char*)
762            dl_inc = find_file('dlfcn.h', [], inc_dirs)
763            if (dl_inc is not None) and (platform not in ['atheos', 'darwin']):
764                exts.append( Extension('dl', ['dlmodule.c']) )
765
766        # Platform-specific libraries
767        if platform == 'linux2':
768            # Linux-specific modules
769            exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) )
770
771        if platform in ('linux2', 'freebsd4'):
772            exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
773
774        if platform == 'sunos5':
775            # SunOS specific modules
776            exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) )
777
778        if platform == 'darwin':
779            # Mac OS X specific modules.
780            exts.append( Extension('_CF', ['cf/_CFmodule.c', 'cf/pycfbridge.c'],
781                        extra_link_args=['-framework', 'CoreFoundation']) )
782
783            exts.append( Extension('ColorPicker', ['ColorPickermodule.c'],
784                        extra_link_args=['-framework', 'Carbon']) )
785            exts.append( Extension('autoGIL', ['autoGIL.c'],
786                        extra_link_args=['-framework', 'CoreFoundation']) )
787            exts.append( Extension('gestalt', ['gestaltmodule.c'],
788                        extra_link_args=['-framework', 'Carbon']) )
789            exts.append( Extension('MacOS', ['macosmodule.c'],
790                        extra_link_args=['-framework', 'Carbon']) )
791            exts.append( Extension('OSATerminology', ['OSATerminology.c'],
792                        extra_link_args=['-framework', 'Carbon']) )
793            exts.append( Extension('icglue', ['icgluemodule.c'],
794                        extra_link_args=['-framework', 'Carbon']) )
795            exts.append( Extension('_Res', ['res/_Resmodule.c'],
796                        extra_link_args=['-framework', 'Carbon']) )
797            exts.append( Extension('_Snd', ['snd/_Sndmodule.c'],
798                        extra_link_args=['-framework', 'Carbon']) )
799            exts.append( Extension('Nav', ['Nav.c'],
800                    extra_link_args=['-framework', 'Carbon']) )
801            exts.append( Extension('_AE', ['ae/_AEmodule.c'],
802                    extra_link_args=['-framework', 'Carbon']) )
803            exts.append( Extension('_AH', ['ah/_AHmodule.c'],
804                    extra_link_args=['-framework', 'Carbon']) )
805            exts.append( Extension('_App', ['app/_Appmodule.c'],
806                    extra_link_args=['-framework', 'Carbon']) )
807            exts.append( Extension('_CarbonEvt', ['carbonevt/_CarbonEvtmodule.c'],
808                    extra_link_args=['-framework', 'Carbon']) )
809            exts.append( Extension('_CG', ['cg/_CGmodule.c'],
810                    extra_link_args=['-framework', 'ApplicationServices']) )
811            exts.append( Extension('_Cm', ['cm/_Cmmodule.c'],
812                    extra_link_args=['-framework', 'Carbon']) )
813            exts.append( Extension('_Ctl', ['ctl/_Ctlmodule.c'],
814                    extra_link_args=['-framework', 'Carbon']) )
815            exts.append( Extension('_Dlg', ['dlg/_Dlgmodule.c'],
816                    extra_link_args=['-framework', 'Carbon']) )
817            exts.append( Extension('_Drag', ['drag/_Dragmodule.c'],
818                    extra_link_args=['-framework', 'Carbon']) )
819            exts.append( Extension('_Evt', ['evt/_Evtmodule.c'],
820                    extra_link_args=['-framework', 'Carbon']) )
821            exts.append( Extension('_File', ['file/_Filemodule.c'],
822                    extra_link_args=['-framework', 'Carbon']) )
823            exts.append( Extension('_Folder', ['folder/_Foldermodule.c'],
824                    extra_link_args=['-framework', 'Carbon']) )
825            exts.append( Extension('_Fm', ['fm/_Fmmodule.c'],
826                    extra_link_args=['-framework', 'Carbon']) )
827            exts.append( Extension('_Help', ['help/_Helpmodule.c'],
828                    extra_link_args=['-framework', 'Carbon']) )
829            exts.append( Extension('_Icn', ['icn/_Icnmodule.c'],
830                    extra_link_args=['-framework', 'Carbon']) )
831            exts.append( Extension('_IBCarbon', ['ibcarbon/_IBCarbon.c'],
832                    extra_link_args=['-framework', 'Carbon']) )
833            exts.append( Extension('_Launch', ['launch/_Launchmodule.c'],
834                    extra_link_args=['-framework', 'ApplicationServices']) )
835            exts.append( Extension('_List', ['list/_Listmodule.c'],
836                    extra_link_args=['-framework', 'Carbon']) )
837            exts.append( Extension('_Menu', ['menu/_Menumodule.c'],
838                    extra_link_args=['-framework', 'Carbon']) )
839            exts.append( Extension('_Mlte', ['mlte/_Mltemodule.c'],
840                    extra_link_args=['-framework', 'Carbon']) )
841            exts.append( Extension('_OSA', ['osa/_OSAmodule.c'],
842                    extra_link_args=['-framework', 'Carbon']) )
843            exts.append( Extension('_Qd', ['qd/_Qdmodule.c'],
844                    extra_link_args=['-framework', 'Carbon']) )
845            exts.append( Extension('_Qdoffs', ['qdoffs/_Qdoffsmodule.c'],
846                    extra_link_args=['-framework', 'Carbon']) )
847            exts.append( Extension('_Qt', ['qt/_Qtmodule.c'],
848                    extra_link_args=['-framework', 'QuickTime',
849                                     '-framework', 'Carbon']) )
850            exts.append( Extension('_Scrap', ['scrap/_Scrapmodule.c'],
851                    extra_link_args=['-framework', 'Carbon']) )
852            exts.append( Extension('_TE', ['te/_TEmodule.c'],
853                    extra_link_args=['-framework', 'Carbon']) )
854            # As there is no standardized place (yet) to put
855            # user-installed Mac libraries on OSX, we search for "waste"
856            # in parent directories of the Python source tree. You
857            # should put a symlink to your Waste installation in the
858            # same folder as your python source tree.  Or modify the
859            # next few lines:-)
860            waste_incs = find_file("WASTE.h", [],
861                    ['../'*n + 'waste/C_C++ Headers' for n in (0,1,2,3,4)])
862            waste_libs = find_library_file(self.compiler, "WASTE", [],
863                    ["../"*n + "waste/Static Libraries" for n in (0,1,2,3,4)])
864            if waste_incs != None and waste_libs != None:
865                (srcdir,) = sysconfig.get_config_vars('srcdir')
866                exts.append( Extension('waste',
867                               ['waste/wastemodule.c'] + [
868                                os.path.join(srcdir, d) for d in
869                                'Mac/Wastemods/WEObjectHandlers.c',
870                                'Mac/Wastemods/WETabHooks.c',
871                                'Mac/Wastemods/WETabs.c'
872                               ],
873                               include_dirs = waste_incs + [os.path.join(srcdir, 'Mac/Wastemods')],
874                               library_dirs = waste_libs,
875                               libraries = ['WASTE'],
876                               extra_link_args = ['-framework', 'Carbon'],
877                ) )
878            exts.append( Extension('_Win', ['win/_Winmodule.c'],
879                    extra_link_args=['-framework', 'Carbon']) )
880
881        self.extensions.extend(exts)
882
883        # Call the method for detecting whether _tkinter can be compiled
884        self.detect_tkinter(inc_dirs, lib_dirs)
885
886    def detect_tkinter_darwin(self, inc_dirs, lib_dirs):
887        # The _tkinter module, using frameworks. Since frameworks are quite
888        # different the UNIX search logic is not sharable.
889        from os.path import join, exists
890        framework_dirs = [
891            '/System/Library/Frameworks/',
892            '/Library/Frameworks',
893            join(os.getenv('HOME'), '/Library/Frameworks')
894        ]
895
896        # Find the directory that contains the Tcl.framwork and Tk.framework
897        # bundles.
898        # XXX distutils should support -F!
899        for F in framework_dirs:
900            # both Tcl.framework and Tk.framework should be present
901            for fw in 'Tcl', 'Tk':
902                if not exists(join(F, fw + '.framework')):
903                    break
904            else:
905                # ok, F is now directory with both frameworks. Continure
906                # building
907                break
908        else:
909            # Tk and Tcl frameworks not found. Normal "unix" tkinter search
910            # will now resume.
911            return 0
912
913        # For 8.4a2, we must add -I options that point inside the Tcl and Tk
914        # frameworks. In later release we should hopefully be able to pass
915        # the -F option to gcc, which specifies a framework lookup path.
916        #
917        include_dirs = [
918            join(F, fw + '.framework', H)
919            for fw in 'Tcl', 'Tk'
920            for H in 'Headers', 'Versions/Current/PrivateHeaders'
921        ]
922
923        # For 8.4a2, the X11 headers are not included. Rather than include a
924        # complicated search, this is a hard-coded path. It could bail out
925        # if X11 libs are not found...
926        include_dirs.append('/usr/X11R6/include')
927        frameworks = ['-framework', 'Tcl', '-framework', 'Tk']
928
929        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
930                        define_macros=[('WITH_APPINIT', 1)],
931                        include_dirs = include_dirs,
932                        libraries = [],
933                        extra_compile_args = frameworks,
934                        extra_link_args = frameworks,
935                        )
936        self.extensions.append(ext)
937        return 1
938
939
940    def detect_tkinter(self, inc_dirs, lib_dirs):
941        # The _tkinter module.
942
943        # Rather than complicate the code below, detecting and building
944        # AquaTk is a separate method. Only one Tkinter will be built on
945        # Darwin - either AquaTk, if it is found, or X11 based Tk.
946        platform = self.get_platform()
947        if platform == 'darwin' and \
948           self.detect_tkinter_darwin(inc_dirs, lib_dirs):
949            return
950
951        # Assume we haven't found any of the libraries or include files
952        # The versions with dots are used on Unix, and the versions without
953        # dots on Windows, for detection by cygwin.
954        tcllib = tklib = tcl_includes = tk_includes = None
955        for version in ['8.4', '84', '8.3', '83', '8.2',
956                        '82', '8.1', '81', '8.0', '80']:
957            tklib = self.compiler.find_library_file(lib_dirs, 'tk' + version)
958            tcllib = self.compiler.find_library_file(lib_dirs, 'tcl' + version)
959            if tklib and tcllib:
960                # Exit the loop when we've found the Tcl/Tk libraries
961                break
962
963        # Now check for the header files
964        if tklib and tcllib:
965            # Check for the include files on Debian, where
966            # they're put in /usr/include/{tcl,tk}X.Y
967            debian_tcl_include = [ '/usr/include/tcl' + version ]
968            debian_tk_include =  [ '/usr/include/tk'  + version ] + \
969                                 debian_tcl_include
970            tcl_includes = find_file('tcl.h', inc_dirs, debian_tcl_include)
971            tk_includes = find_file('tk.h', inc_dirs, debian_tk_include)
972
973        if (tcllib is None or tklib is None or
974            tcl_includes is None or tk_includes is None):
975            # Something's missing, so give up
976            return
977
978        # OK... everything seems to be present for Tcl/Tk.
979
980        include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = []
981        for dir in tcl_includes + tk_includes:
982            if dir not in include_dirs:
983                include_dirs.append(dir)
984
985        # Check for various platform-specific directories
986        if platform == 'sunos5':
987            include_dirs.append('/usr/openwin/include')
988            added_lib_dirs.append('/usr/openwin/lib')
989        elif os.path.exists('/usr/X11R6/include'):
990            include_dirs.append('/usr/X11R6/include')
991            added_lib_dirs.append('/usr/X11R6/lib')
992        elif os.path.exists('/usr/X11R5/include'):
993            include_dirs.append('/usr/X11R5/include')
994            added_lib_dirs.append('/usr/X11R5/lib')
995        else:
996            # Assume default location for X11
997            include_dirs.append('/usr/X11/include')
998            added_lib_dirs.append('/usr/X11/lib')
999
1000        # If Cygwin, then verify that X is installed before proceeding
1001        if platform == 'cygwin':
1002            x11_inc = find_file('X11/Xlib.h', [], include_dirs)
1003            if x11_inc is None:
1004                return
1005
1006        # Check for BLT extension
1007        if self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1008                                           'BLT8.0'):
1009            defs.append( ('WITH_BLT', 1) )
1010            libs.append('BLT8.0')
1011        elif self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1012                                           'BLT'):
1013            defs.append( ('WITH_BLT', 1) )
1014            libs.append('BLT')
1015
1016        # Add the Tcl/Tk libraries
1017        libs.append('tk'+ version)
1018        libs.append('tcl'+ version)
1019
1020        if platform in ['aix3', 'aix4']:
1021            libs.append('ld')
1022
1023        # Finally, link with the X11 libraries (not appropriate on cygwin)
1024        if platform != "cygwin":
1025            libs.append('X11')
1026
1027        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1028                        define_macros=[('WITH_APPINIT', 1)] + defs,
1029                        include_dirs = include_dirs,
1030                        libraries = libs,
1031                        library_dirs = added_lib_dirs,
1032                        )
1033        self.extensions.append(ext)
1034
1035##         # Uncomment these lines if you want to play with xxmodule.c
1036##         ext = Extension('xx', ['xxmodule.c'])
1037##         self.extensions.append(ext)
1038
1039        # XXX handle these, but how to detect?
1040        # *** Uncomment and edit for PIL (TkImaging) extension only:
1041        #       -DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \
1042        # *** Uncomment and edit for TOGL extension only:
1043        #       -DWITH_TOGL togl.c \
1044        # *** Uncomment these for TOGL extension only:
1045        #       -lGL -lGLU -lXext -lXmu \
1046
1047class PyBuildInstall(install):
1048    # Suppress the warning about installation into the lib_dynload
1049    # directory, which is not in sys.path when running Python during
1050    # installation:
1051    def initialize_options (self):
1052        install.initialize_options(self)
1053        self.warn_dir=0
1054
1055class PyBuildInstallLib(install_lib):
1056    # Do exactly what install_lib does but make sure correct access modes get
1057    # set on installed directories and files. All installed files with get
1058    # mode 644 unless they are a shared library in which case they will get
1059    # mode 755. All installed directories will get mode 755.
1060
1061    so_ext = sysconfig.get_config_var("SO")
1062
1063    def install(self):
1064        outfiles = install_lib.install(self)
1065        self.set_file_modes(outfiles, 0644, 0755)
1066        self.set_dir_modes(self.install_dir, 0755)
1067        return outfiles
1068
1069    def set_file_modes(self, files, defaultMode, sharedLibMode):
1070        if not self.is_chmod_supported(): return
1071        if not files: return
1072
1073        for filename in files:
1074            if os.path.islink(filename): continue
1075            mode = defaultMode
1076            if filename.endswith(self.so_ext): mode = sharedLibMode
1077            log.info("changing mode of %s to %o", filename, mode)
1078            if not self.dry_run: os.chmod(filename, mode)
1079
1080    def set_dir_modes(self, dirname, mode):
1081        if not self.is_chmod_supported(): return
1082        os.path.walk(dirname, self.set_dir_modes_visitor, mode)
1083
1084    def set_dir_modes_visitor(self, mode, dirname, names):
1085        if os.path.islink(dirname): return
1086        log.info("changing mode of %s to %o", dirname, mode)
1087        if not self.dry_run: os.chmod(dirname, mode)
1088
1089    def is_chmod_supported(self):
1090        return hasattr(os, 'chmod')
1091
1092SUMMARY = """
1093Python is an interpreted, interactive, object-oriented programming
1094language. It is often compared to Tcl, Perl, Scheme or Java.
1095
1096Python combines remarkable power with very clear syntax. It has
1097modules, classes, exceptions, very high level dynamic data types, and
1098dynamic typing. There are interfaces to many system calls and
1099libraries, as well as to various windowing systems (X11, Motif, Tk,
1100Mac, MFC). New built-in modules are easily written in C or C++. Python
1101is also usable as an extension language for applications that need a
1102programmable interface.
1103
1104The Python implementation is portable: it runs on many brands of UNIX,
1105on Windows, DOS, OS/2, Mac, Amiga... If your favorite system isn't
1106listed here, it may still be supported, if there's a C compiler for
1107it. Ask around on comp.lang.python -- or just try compiling Python
1108yourself.
1109"""
1110
1111CLASSIFIERS = """
1112Development Status :: 3 - Alpha
1113Development Status :: 6 - Mature
1114License :: OSI Approved :: Python Software Foundation License
1115Natural Language :: English
1116Programming Language :: C
1117Programming Language :: Python
1118Topic :: Software Development
1119"""
1120
1121def main():
1122    # turn off warnings when deprecated modules are imported
1123    import warnings
1124    warnings.filterwarnings("ignore",category=DeprecationWarning)
1125    setup(# PyPI Metadata (PEP 301)
1126          name = "Python",
1127          version = sys.version.split()[0],
1128          url = "http://www.python.org/%s" % sys.version[:3],
1129          maintainer = "Guido van Rossum and the Python community",
1130          maintainer_email = "python-dev@python.org",
1131          description = "A high-level object-oriented programming language",
1132          long_description = SUMMARY.strip(),
1133          license = "PSF license",
1134          classifiers = filter(None, CLASSIFIERS.split("\n")),
1135          platforms = ["Many"],
1136
1137          # Build info
1138          cmdclass = {'build_ext':PyBuildExt, 'install':PyBuildInstall,
1139                      'install_lib':PyBuildInstallLib},
1140          # The struct module is defined here, because build_ext won't be
1141          # called unless there's at least one extension module defined.
1142          ext_modules=[Extension('struct', ['structmodule.c'])],
1143
1144          # Scripts to install
1145          scripts = ['Tools/scripts/pydoc', 'Tools/scripts/idle']
1146        )
1147
1148# --install-platlib
1149if __name__ == '__main__':
1150    main()
1151