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