setup.py 46.7 KB
Newer Older
1 2
# Autodetecting setup.py script for building the Python extensions
#
3

4 5
__version__ = "$Revision$"

Michael W. Hudson's avatar
Michael W. Hudson committed
6
import sys, os, getopt, imp
7
from distutils import sysconfig
8
from distutils import text_file
9
from distutils.errors import *
10 11
from distutils.core import Extension, setup
from distutils.command.build_ext import build_ext
12
from distutils.command.install import install
13 14 15 16

# This global variable is used to hold the list of modules to be disabled.
disabled_module_list = []

17 18 19 20
def add_dir_to_list(dirlist, dir):
    """Add the directory 'dir' to the list 'dirlist' (at the front) if
    1) 'dir' is not already in 'dirlist'
    2) 'dir' actually exists, and is a directory."""
21
    if dir is not None and os.path.isdir(dir) and dir not in dirlist:
22 23
        dirlist.insert(0, dir)

24 25 26 27
def find_file(filename, std_dirs, paths):
    """Searches for the directory where a given file is located,
    and returns a possibly-empty list of additional directories, or None
    if the file couldn't be found at all.
28

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
    'filename' is the name of a file, such as readline.h or libcrypto.a.
    'std_dirs' is the list of standard system directories; if the
        file is found in one of them, no additional directives are needed.
    'paths' is a list of additional locations to check; if the file is
        found in one of them, the resulting list will contain the directory.
    """

    # Check the standard locations
    for dir in std_dirs:
        f = os.path.join(dir, filename)
        if os.path.exists(f): return []

    # Check the additional directories
    for dir in paths:
        f = os.path.join(dir, filename)
        if os.path.exists(f):
            return [dir]

    # Not found anywhere
48 49
    return None

50 51 52 53
def find_library_file(compiler, libname, std_dirs, paths):
    filename = compiler.library_filename(libname, lib_type='shared')
    result = find_file(filename, std_dirs, paths)
    if result is not None: return result
54

55 56 57 58
    filename = compiler.library_filename(libname, lib_type='static')
    result = find_file(filename, std_dirs, paths)
    return result

59 60 61 62 63
def module_enabled(extlist, modname):
    """Returns whether the module 'modname' is present in the list
    of extensions 'extlist'."""
    extlist = [ext for ext in extlist if ext.name == modname]
    return len(extlist)
64

65 66 67 68 69 70 71 72 73
def find_module_file(module, dirlist):
    """Find a module in a set of possible folders. If it is not found
    return the unadorned filename"""
    list = find_file(module, [], dirlist)
    if not list:
        return module
    if len(list) > 1:
        self.announce("WARNING: multiple copies of %s found"%module)
    return os.path.join(list[0], module)
74

75
class PyBuildExt(build_ext):
76

77 78 79 80 81 82 83 84
    def build_extensions(self):

        # Detect which modules should be compiled
        self.detect_modules()

        # Remove modules that are present on the disabled list
        self.extensions = [ext for ext in self.extensions
                           if ext.name not in disabled_module_list]
85

86 87 88 89
        # Fix up the autodetected modules, prefixing all the source files
        # with Modules/ and adding Python's include directory to the path.
        (srcdir,) = sysconfig.get_config_vars('srcdir')

90 91
        # Figure out the location of the source code for extension modules
        moddir = os.path.join(os.getcwd(), srcdir, 'Modules')
92 93 94 95
        moddir = os.path.normpath(moddir)
        srcdir, tail = os.path.split(moddir)
        srcdir = os.path.normpath(srcdir)
        moddir = os.path.normpath(moddir)
96

97 98
        moddirlist = [moddir]
        incdirlist = ['./Include']
99

100 101
        # Platform-dependent module source and include directories
        platform = self.get_platform()
102
        if platform in ('darwin', 'mac'):
103 104 105 106
            # Mac OS X also includes some mac-specific modules
            macmoddir = os.path.join(os.getcwd(), srcdir, 'Mac/Modules')
            moddirlist.append(macmoddir)
            incdirlist.append('./Mac/Include')
107

108 109
        alldirlist = moddirlist + incdirlist

110 111 112 113
        # Fix up the paths for scripts, too
        self.distribution.scripts = [os.path.join(srcdir, filename)
                                     for filename in self.distribution.scripts]

114
        for ext in self.extensions[:]:
115
            ext.sources = [ find_module_file(filename, moddirlist)
116
                            for filename in ext.sources ]
117 118 119
            if ext.depends is not None:
                ext.depends = [find_module_file(filename, alldirlist)
                               for filename in ext.depends]
120 121 122
            ext.include_dirs.append( '.' ) # to get config.h
            for incdir in incdirlist:
                ext.include_dirs.append( os.path.join(srcdir, incdir) )
123

124
            # If a module has already been built statically,
125
            # don't build it here
126
            if ext.name in sys.builtin_module_names:
127
                self.extensions.remove(ext)
128

129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
        if platform != 'mac':
            # Parse Modules/Setup to figure out which modules are turned
            # on in the file.
            input = text_file.TextFile('Modules/Setup', join_lines=1)
            remove_modules = []
            while 1:
                line = input.readline()
                if not line: break
                line = line.split()
                remove_modules.append( line[0] )
            input.close()
    
            for ext in self.extensions[:]:
                if ext.name in remove_modules:
                    self.extensions.remove(ext)
144

145 146 147 148 149 150 151 152 153
        # When you run "make CC=altcc" or something similar, you really want
        # those environment variables passed into the setup.py phase.  Here's
        # a small set of useful ones.
        compiler = os.environ.get('CC')
        linker_so = os.environ.get('LDSHARED')
        args = {}
        # unfortunately, distutils doesn't let us provide separate C and C++
        # compilers
        if compiler is not None:
154 155
            (ccshared,opt) = sysconfig.get_config_vars('CCSHARED','OPT')
            args['compiler_so'] = compiler + ' ' + opt + ' ' + ccshared
156
        if linker_so is not None:
157
            args['linker_so'] = linker_so
158 159
        self.compiler.set_executables(**args)

160 161
        build_ext.build_extensions(self)

162 163 164 165 166 167 168
    def build_extension(self, ext):

        try:
            build_ext.build_extension(self, ext)
        except (CCompilerError, DistutilsError), why:
            self.announce('WARNING: building of extension "%s" failed: %s' %
                          (ext.name, sys.exc_info()[1]))
169
            return
170 171 172
        # Workaround for Mac OS X: The Carbon-based modules cannot be
        # reliably imported into a command-line Python
        if 'Carbon' in ext.extra_link_args:
173 174 175 176
            self.announce(
                'WARNING: skipping import check for Carbon-based "%s"' %
                ext.name)
            return
177 178 179 180 181 182
        # Workaround for Cygwin: Cygwin currently has fork issues when many
        # modules have been imported
        if self.get_platform() == 'cygwin':
            self.announce('WARNING: skipping import check for Cygwin-based "%s"'
                % ext.name)
            return
Michael W. Hudson's avatar
Michael W. Hudson committed
183 184 185
        ext_filename = os.path.join(
            self.build_lib,
            self.get_ext_filename(self.get_ext_fullname(ext.name)))
186
        try:
Michael W. Hudson's avatar
Michael W. Hudson committed
187
            imp.load_dynamic(ext.name, ext_filename)
188 189 190
        except ImportError, why:

            if 1:
191
                self.announce('*** WARNING: renaming "%s" since importing it'
192 193
                              ' failed: %s' % (ext.name, why))
                assert not self.inplace
194 195 196 197
                basename, tail = os.path.splitext(ext_filename)
                newname = basename + "_failed" + tail
                if os.path.exists(newname): os.remove(newname)
                os.rename(ext_filename, newname)
198 199 200 201 202

                # XXX -- This relies on a Vile HACK in
                # distutils.command.build_ext.build_extension().  The
                # _built_objects attribute is stored there strictly for
                # use here.
203 204 205 206 207 208 209
                # If there is a failure, _built_objects may not be there,
                # so catch the AttributeError and move on.
                try:
                    for filename in self._built_objects:
                        os.remove(filename)
                except AttributeError:
                    self.announce('unable to remove files (ignored)')
210 211 212
            else:
                self.announce('*** WARNING: importing extension "%s" '
                              'failed: %s' % (ext.name, why))
213

214
    def get_platform (self):
215 216 217 218
        # Get value of sys.platform
        platform = sys.platform
        if platform[:6] =='cygwin':
            platform = 'cygwin'
219 220
        elif platform[:4] =='beos':
            platform = 'beos'
221 222
        elif platform[:6] == 'darwin':
            platform = 'darwin'
223 224
        elif platform[:6] == 'atheos':
            platform = 'atheos'
225

226
        return platform
227

228
    def detect_modules(self):
229
        # Ensure that /usr/local is always used
230 231 232
        add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
        add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')

Michael W. Hudson's avatar
Michael W. Hudson committed
233 234 235 236 237
        if os.path.normpath(sys.prefix) != '/usr':
            add_dir_to_list(self.compiler.library_dirs,
                            sysconfig.get_config_var("LIBDIR"))
            add_dir_to_list(self.compiler.include_dirs,
                            sysconfig.get_config_var("INCLUDEDIR"))
238

239 240 241 242 243
        try:
            have_unicode = unicode
        except NameError:
            have_unicode = 0

244 245 246 247
        # lib_dirs and inc_dirs are used to search for files;
        # if a file is found in one of those directories, it can
        # be assumed that no additional -I,-L directives are needed.
        lib_dirs = self.compiler.library_dirs + ['/lib', '/usr/lib']
248
        inc_dirs = self.compiler.include_dirs + ['/usr/include']
249 250
        exts = []

251
        platform = self.get_platform()
252
        (srcdir,) = sysconfig.get_config_vars('srcdir')
253

254 255 256 257 258 259 260
        # Check for AtheOS which has libraries in non-standard locations
        if platform == 'atheos':
            lib_dirs += ['/system/libs', '/atheos/autolnk/lib']
            lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep)
            inc_dirs += ['/system/include', '/atheos/autolnk/include']
            inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep)

261 262
        # Check for MacOS X, which doesn't need libm.a at all
        math_libs = ['m']
263
        if platform in ['darwin', 'beos', 'mac']:
264
            math_libs = []
265

266 267 268 269 270 271
        # XXX Omitted modules: gl, pure, dl, SGI-specific modules

        #
        # The following modules are all pretty straightforward, and compile
        # on pretty much any POSIXish platform.
        #
272

273 274 275
        # Some modules that are normally always on:
        exts.append( Extension('regex', ['regexmodule.c', 'regexpr.c']) )
        exts.append( Extension('pcre', ['pcremodule.c', 'pypcre.c']) )
276

Fred Drake's avatar
Fred Drake committed
277
        exts.append( Extension('_hotshot', ['_hotshot.c']) )
278
        exts.append( Extension('_weakref', ['_weakref.c']) )
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
279
        exts.append( Extension('xreadlines', ['xreadlinesmodule.c']) )
280 281 282 283

        # array objects
        exts.append( Extension('array', ['arraymodule.c']) )
        # complex math library functions
284 285
        exts.append( Extension('cmath', ['cmathmodule.c'],
                               libraries=math_libs) )
286

287
        # math library functions, e.g. sin()
288 289
        exts.append( Extension('math',  ['mathmodule.c'],
                               libraries=math_libs) )
290 291 292
        # fast string operations implemented in C
        exts.append( Extension('strop', ['stropmodule.c']) )
        # time operations and variables
293 294
        exts.append( Extension('time', ['timemodule.c'],
                               libraries=math_libs) )
295 296 297 298
        # operator.add() and similar goodies
        exts.append( Extension('operator', ['operator.c']) )
        # access to the builtin codecs and codec registry
        exts.append( Extension('_codecs', ['_codecsmodule.c']) )
299
        # Python C API test module
300
        exts.append( Extension('_testcapi', ['_testcapimodule.c']) )
301
        # static Unicode character database
302 303
        if have_unicode:
            exts.append( Extension('unicodedata', ['unicodedata.c']) )
304
        # access to ISO C locale support
305 306 307 308 309 310
        if platform in ['cygwin']:
            locale_libs = ['intl']
        else:
            locale_libs = []
        exts.append( Extension('_locale', ['_localemodule.c'],
                               libraries=locale_libs ) )
311 312 313 314 315 316 317

        # Modules with some UNIX dependencies -- on by default:
        # (If you have a really backward UNIX, select and socket may not be
        # supported...)

        # fcntl(2) and ioctl(2)
        exts.append( Extension('fcntl', ['fcntlmodule.c']) )
318 319 320 321 322
        if platform not in ['mac']:
                # pwd(3)
                exts.append( Extension('pwd', ['pwdmodule.c']) )
                # grp(3)
                exts.append( Extension('grp', ['grpmodule.c']) )
323 324 325 326
        # select(2); not on ancient System V
        exts.append( Extension('select', ['selectmodule.c']) )

        # The md5 module implements the RSA Data Security, Inc. MD5
Fred Drake's avatar
Fred Drake committed
327 328
        # Message-Digest Algorithm, described in RFC 1321.  The
        # necessary files md5c.c and md5.h are included here.
329 330 331 332 333 334 335 336 337 338 339 340
        exts.append( Extension('md5', ['md5module.c', 'md5c.c']) )

        # The sha module implements the SHA checksum algorithm.
        # (NIST's Secure Hash Algorithm.)
        exts.append( Extension('sha', ['shamodule.c']) )

        # Helper module for various ascii-encoders
        exts.append( Extension('binascii', ['binascii.c']) )

        # Fred Drake's interface to the Python parser
        exts.append( Extension('parser', ['parsermodule.c']) )

341
        # cStringIO and cPickle
342 343 344 345
        exts.append( Extension('cStringIO', ['cStringIO.c']) )
        exts.append( Extension('cPickle', ['cPickle.c']) )

        # Memory-mapped files (also works on Win32).
346
        if platform not in ['atheos', 'mac']:
347
            exts.append( Extension('mmap', ['mmapmodule.c']) )
348 349 350 351

        # Lance Ellinghaus's modules:
        # enigma-inspired encryption
        exts.append( Extension('rotor', ['rotormodule.c']) )
352 353 354
        if platform not in ['mac']:
                # syslog daemon interface
                exts.append( Extension('syslog', ['syslogmodule.c']) )
355 356 357 358 359

        # George Neville-Neil's timing module:
        exts.append( Extension('timing', ['timingmodule.c']) )

        #
360 361
        # Here ends the simple stuff.  From here on, modules need certain
        # libraries, are platform-specific, or present other surprises.
362 363 364 365 366 367
        #

        # Multimedia modules
        # These don't work for 64-bit platforms!!!
        # These represent audio samples or images as strings:

368
        # Disabled on 64-bit platforms
369 370 371 372 373 374 375 376 377
        if sys.maxint != 9223372036854775807L:
            # Operations on audio samples
            exts.append( Extension('audioop', ['audioop.c']) )
            # Operations on images
            exts.append( Extension('imageop', ['imageop.c']) )
            # Read SGI RGB image files (but coded portably)
            exts.append( Extension('rgbimg', ['rgbimgmodule.c']) )

        # readline
378 379
        if self.compiler.find_library_file(lib_dirs, 'readline'):
            readline_libs = ['readline']
380 381 382 383
            if self.compiler.find_library_file(lib_dirs,
                                                 'ncurses'):
                readline_libs.append('ncurses')
            elif self.compiler.find_library_file(lib_dirs +
384 385 386
                                               ['/usr/lib/termcap'],
                                               'termcap'):
                readline_libs.append('termcap')
387
            exts.append( Extension('readline', ['readline.c'],
388
                                   library_dirs=['/usr/lib/termcap'],
389
                                   libraries=readline_libs) )
390 391 392 393 394 395 396 397
        if platform not in ['mac']:
                # crypt module.
        
                if self.compiler.find_library_file(lib_dirs, 'crypt'):
                    libs = ['crypt']
                else:
                    libs = []
                exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) )
398 399

        # socket(2)
400
        exts.append( Extension('_socket', ['socketmodule.c'],
401
                               depends = ['socketmodule.h']) )
402
        # Detect SSL support for the socket module (via _ssl)
403
        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
404 405 406
                             ['/usr/local/ssl/include',
                              '/usr/contrib/ssl/include/'
                             ]
407 408
                             )
        ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
409 410 411
                                     ['/usr/local/ssl/lib',
                                      '/usr/contrib/ssl/lib/'
                                     ] )
412

413 414
        if (ssl_incs is not None and
            ssl_libs is not None):
415
            exts.append( Extension('_ssl', ['_ssl.c'],
416
                                   include_dirs = ssl_incs,
417
                                   library_dirs = ssl_libs,
418
                                   libraries = ['ssl', 'crypto'],
419
                                   depends = ['socketmodule.h']), )
420 421 422 423 424 425 426 427

        # Modules that provide persistent dictionary-like semantics.  You will
        # probably want to arrange for at least one of them to be available on
        # your machine, though none are defined by default because of library
        # dependencies.  The Python module anydbm.py provides an
        # implementation independent wrapper for these; dumbdbm.py provides
        # similar functionality (but slower of course) implemented in Python.

428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
        # Berkeley DB interface.
        #
        # This requires the Berkeley DB code, see
        # ftp://ftp.cs.berkeley.edu/pub/4bsd/db.1.85.tar.gz
        #
        # (See http://pybsddb.sourceforge.net/ for an interface to
        # Berkeley DB 3.x.)

        # when sorted in reverse order, keys for this dict must appear in the
        # order you wish to search - e.g., search for db3 before db2, db2
        # before db1
        db_try_this = {
            'db4': {'libs': ('db-4.3', 'db-4.2', 'db-4.1', 'db-4.0'),
                    'libdirs': ('/usr/local/BerkeleyDB.4.3/lib',
                                '/usr/local/BerkeleyDB.4.2/lib',
                                '/usr/local/BerkeleyDB.4.1/lib',
                                '/usr/local/BerkeleyDB.4.0/lib',
445
                                '/usr/local/lib',
446 447 448 449 450 451 452 453 454
                                '/usr/lib',
                                '/opt/sfw',
                                '/sw/lib',
                                '/lib',
                                ),
                    'incdirs': ('/usr/local/BerkeleyDB.4.3/include',
                                '/usr/local/BerkeleyDB.4.2/include',
                                '/usr/local/BerkeleyDB.4.1/include',
                                '/usr/local/BerkeleyDB.4.0/include',
455
                                '/usr/local/include/db3',
456 457
                                '/opt/sfw/include/db3',
                                '/sw/include/db3',
458
                                '/usr/include/db3',
459 460 461 462 463 464 465
                                ),
                    'incs': ('db_185.h',)},
            'db3': {'libs': ('db-3.3', 'db-3.2', 'db-3.1', 'db-3.0'),
                    'libdirs': ('/usr/local/BerkeleyDB.3.3/lib',
                                '/usr/local/BerkeleyDB.3.2/lib',
                                '/usr/local/BerkeleyDB.3.1/lib',
                                '/usr/local/BerkeleyDB.3.0/lib',
466
                                '/usr/local/lib',
467 468
                                '/opt/sfw',
                                '/sw/lib',
469
                                '/usr/lib',
470 471 472 473 474 475
                                '/lib',
                                ),
                    'incdirs': ('/usr/local/BerkeleyDB.3.3/include',
                                '/usr/local/BerkeleyDB.3.2/include',
                                '/usr/local/BerkeleyDB.3.1/include',
                                '/usr/local/BerkeleyDB.3.0/include',
476
                                '/usr/local/include/db3',
477 478
                                '/opt/sfw/include/db3',
                                '/sw/include/db3',
479
                                '/usr/include/db3',
480 481 482
                                ),
                    'incs': ('db_185.h',)},
            'db2': {'libs': ('db2',),
483 484 485 486 487 488 489
                    'libdirs': ('/usr/local/lib',
                                '/sw/lib',
                                '/usr/lib',
                                '/lib'),
                    'incdirs': ('/usr/local/include/db2',
                                '/sw/include/db2',
                                '/usr/include/db2'),
490 491 492 493
                    'incs': ('db_185.h',)},
            # if you are willing to risk hash db file corruption you can
            # uncomment the lines below for db1.  Note that this will affect
            # not only the bsddb module, but the dbhash and anydbm modules
494
            # as well.  YOU HAVE BEEN WARNED!!!
495
            ##'db1': {'libs': ('db1', 'db'),
496 497 498 499 500 501 502 503
            ##        'libdirs': ('/usr/local/lib',
            ##                    '/sw/lib',
            ##                    '/usr/lib',
            ##                    '/lib'),
            ##        'incdirs': ('/usr/local/include/db1',
            ##                    '/usr/local/include',
            ##                    '/usr/include/db1',
            ##                    '/usr/include'),
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
            ##        'incs': ('db.h',)},
            }

        # override this list to affect the library version search order
        # for example, if you want to force version 2 to be used:
        #   db_search_order = ["db2"]
        db_search_order = db_try_this.keys()
        db_search_order.sort()
        db_search_order.reverse()
        
        find_lib_file = self.compiler.find_library_file
        class found(Exception): pass
        try:
            for dbkey in db_search_order:
                dbd = db_try_this[dbkey]
                for dblib in dbd['libs']:
                    for dbinc in dbd['incs']:
                        db_incs = find_file(dbinc, [], dbd['incdirs'])
                        dblib_dir = find_lib_file(dbd['libdirs'], dblib)
                        if db_incs and dblib_dir:
                            dblib_dir = os.path.dirname(dblib_dir)
                            dblibs = [dblib]
                            raise found
        except found:
528
            dblibs = [dblib]
529 530 531 532 533 534 535 536
            # A default source build puts Berkeley DB in something like
            # /usr/local/Berkeley.3.3 and the lib dir under that isn't
            # normally on ld.so's search path, unless the sysadmin has hacked
            # /etc/ld.so.conf.  We add the directory to runtime_library_dirs
            # so the proper -R/--rpath flags get passed to the linker.  This
            # is usually correct and most trouble free, but may cause problems
            # in some unusual system configurations (e.g. the directory is on
            # an NFS server that goes away).
537 538 539
            if dbinc == 'db_185.h':
                exts.append(Extension('bsddb', ['bsddbmodule.c'],
                                      library_dirs=[dblib_dir],
540
                                      runtime_library_dirs=[dblib_dir],
541 542
                                      include_dirs=db_incs,
                                      define_macros=[('HAVE_DB_185_H',1)],
543
                                      libraries=dblibs))
544 545 546
            else:
                exts.append(Extension('bsddb', ['bsddbmodule.c'],
                                      library_dirs=[dblib_dir],
547
                                      runtime_library_dirs=[dblib_dir],
548
                                      include_dirs=db_incs,
549
                                      libraries=dblibs))
550 551 552 553 554
        else:
            db_incs = None
            dblibs = []
            dblib_dir = None

555
        # The standard Unix dbm module:
556 557 558
        if platform not in ['cygwin']:
            if (self.compiler.find_library_file(lib_dirs, 'ndbm')
                and find_file("ndbm.h", inc_dirs, []) is not None):
559
                exts.append( Extension('dbm', ['dbmmodule.c'],
560
                                       define_macros=[('HAVE_NDBM_H',None)],
561
                                       libraries = ['ndbm'] ) )
562 563 564
            elif (platform in ['darwin']
                and find_file("ndbm.h", inc_dirs, []) is not None):
                # Darwin has ndbm in libc
565
                exts.append( Extension('dbm', ['dbmmodule.c'],
566 567 568 569 570
                                       define_macros=[('HAVE_NDBM_H',None)]) )
            elif (self.compiler.find_library_file(lib_dirs, 'gdbm')
                  and find_file("gdbm/ndbm.h", inc_dirs, []) is not None):
                exts.append( Extension('dbm', ['dbmmodule.c'],
                                       define_macros=[('HAVE_GDBM_NDBM_H',None)],
571 572 573
                                       libraries = ['gdbm'] ) )
            elif db_incs is not None:
                exts.append( Extension('dbm', ['dbmmodule.c'],
574
                                       library_dirs=[dblib_dir],
575
                                       include_dirs=db_incs,
576 577
                                       define_macros=[('HAVE_BERKDB_H',None),
                                                      ('DB_DBM_HSEARCH',None)],
578
                                       libraries=dblibs))
579

580 581 582 583 584 585
        # Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:
        if (self.compiler.find_library_file(lib_dirs, 'gdbm')):
            exts.append( Extension('gdbm', ['gdbmmodule.c'],
                                   libraries = ['gdbm'] ) )

        # The mpz module interfaces to the GNU Multiple Precision library.
586
        # You need to ftp the GNU MP library.
587 588
        # This was originally written and tested against GMP 1.2 and 1.3.2.
        # It has been modified by Rob Hooft to work with 2.0.2 as well, but I
589 590 591 592
        # haven't tested it recently, and it definitely doesn't work with
        # GMP 4.0.  For more complete modules, refer to
        # http://gmpy.sourceforge.net and
        # http://www.egenix.com/files/python/mxNumber.html
593

594
        # A compatible MP library unencumbered by the GPL also exists.  It was
595 596 597 598 599 600 601 602 603 604
        # posted to comp.sources.misc in volume 40 and is widely available from
        # FTP archive sites. One URL for it is:
        # ftp://gatekeeper.dec.com/.b/usenet/comp.sources.misc/volume40/fgmp/part01.Z

        if (self.compiler.find_library_file(lib_dirs, 'gmp')):
            exts.append( Extension('mpz', ['mpzmodule.c'],
                                   libraries = ['gmp'] ) )


        # Unix-only modules
605
        if platform not in ['mac', 'win32']:
606 607 608
            # Steen Lumholt's termios module
            exts.append( Extension('termios', ['termios.c']) )
            # Jeremy Hylton's rlimit interface
609 610
	    if platform not in ['atheos']:
                exts.append( Extension('resource', ['resource.c']) )
611

612
            # Sun yellow pages. Some systems have the functions in libc.
613
            if platform not in ['cygwin', 'atheos']:
614 615 616 617 618 619
                if (self.compiler.find_library_file(lib_dirs, 'nsl')):
                    libs = ['nsl']
                else:
                    libs = []
                exts.append( Extension('nis', ['nismodule.c'],
                                       libraries = libs) )
620 621

        # Curses support, requring the System V version of curses, often
622
        # provided by the ncurses library.
623
        if platform == 'sunos4':
624
            inc_dirs += ['/usr/5include']
625 626 627 628 629 630
            lib_dirs += ['/usr/5lib']

        if (self.compiler.find_library_file(lib_dirs, 'ncurses')):
            curses_libs = ['ncurses']
            exts.append( Extension('_curses', ['_cursesmodule.c'],
                                   libraries = curses_libs) )
Fred Drake's avatar
Fred Drake committed
631 632
        elif (self.compiler.find_library_file(lib_dirs, 'curses')
              and platform != 'darwin'):
633 634
                # OSX has an old Berkeley curses, not good enough for
                # the _curses module.
635 636 637 638
            if (self.compiler.find_library_file(lib_dirs, 'terminfo')):
                curses_libs = ['curses', 'terminfo']
            else:
                curses_libs = ['curses', 'termcap']
639

640 641
            exts.append( Extension('_curses', ['_cursesmodule.c'],
                                   libraries = curses_libs) )
642

643
        # If the curses module is enabled, check for the panel module
644
        if (module_enabled(exts, '_curses') and
645 646 647
            self.compiler.find_library_file(lib_dirs, 'panel')):
            exts.append( Extension('_curses_panel', ['_curses_panel.c'],
                                   libraries = ['panel'] + curses_libs) )
648 649


650 651 652 653 654

        # Lee Busby's SIGFPE modules.
        # The library to link fpectl with is platform specific.
        # Choose *one* of the options below for fpectl:

655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
        # Disabled; it's dangerous or useless except in the hands of experts.
##        if platform == 'irix5':
##            # For SGI IRIX (tested on 5.3):
##            exts.append( Extension('fpectl', ['fpectlmodule.c'],
##                                   libraries=['fpe']) )
##        elif 0: # XXX how to detect SunPro?
##            # For Solaris with SunPro compiler (tested on Solaris 2.5
##            # with SunPro C 4.2): (Without the compiler you don't have
##            # -lsunmath.)
##            #fpectl fpectlmodule.c -R/opt/SUNWspro/lib -lsunmath -lm
##            pass
##        else:
##            # For other systems: see instructions in fpectlmodule.c.
##            #fpectl fpectlmodule.c ...
##            exts.append( Extension('fpectl', ['fpectlmodule.c']) )
670 671


672 673 674 675 676 677 678 679 680 681 682 683
        # Andrew Kuchling's zlib module.  Note that some versions of zlib
        # 1.1.3 have security problems.  See CERT Advisory CA-2002-07:
        # http://www.cert.org/advisories/CA-2002-07.html
        #
        # zlib 1.1.4 is fixed, but at least one vendor (RedHat) has decided to
        # patch its zlib 1.1.3 package instead of upgrading to 1.1.4.  For
        # now, we still accept 1.1.3, because we think it's difficult to
        # exploit this in Python, and we'd rather make it RedHat's problem
        # than our problem <wink>.
        #
        # You can upgrade zlib to version 1.1.4 yourself by going to
        # http://www.gzip.org/zlib/
684 685 686 687
        zlib_inc = find_file('zlib.h', [], inc_dirs)
        if zlib_inc is not None:
            zlib_h = zlib_inc[0] + '/zlib.h'
            version = '"0.0.0"'
688
            version_req = '"1.1.3"'
689 690 691 692 693
            fp = open(zlib_h)
            while 1:
                line = fp.readline()
                if not line:
                    break
694
                if line.startswith('#define ZLIB_VERSION'):
695 696 697 698 699 700
                    version = line.split()[2]
                    break
            if version >= version_req:
                if (self.compiler.find_library_file(lib_dirs, 'z')):
                    exts.append( Extension('zlib', ['zlibmodule.c'],
                                           libraries = ['z']) )
701 702 703

        # Interface to the Expat XML parser
        #
704 705 706 707 708 709 710 711 712
        # Expat was written by James Clark and is now maintained by a
        # group of developers on SourceForge; see www.libexpat.org for
        # more information.  The pyexpat module was written by Paul
        # Prescod after a prototype by Jack Jansen.  Source of Expat
        # 1.95.2 is included in Modules/expat/.  Usage of a system
        # shared libexpat.so/expat.dll is not advised.
        #
        # More information on Expat can be found at www.libexpat.org.
        #
713 714
        if sys.byteorder == "little":
            xmlbo = "12"
715
        else:
716
            xmlbo = "21"
717
        expatinc = os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')
718 719 720 721 722 723 724 725 726 727 728 729 730 731
        exts.append(Extension('pyexpat',
                              sources = [
            'pyexpat.c',
            'expat/xmlparse.c',
            'expat/xmlrole.c',
            'expat/xmltok.c',
            ],
                              define_macros = [
            ('HAVE_EXPAT_H',None),
            ('XML_NS', '1'),
            ('XML_DTD', '1'),
            ('XML_BYTE_ORDER', xmlbo),
            ('XML_CONTEXT_BYTES','1024'),
            ],
732
                              include_dirs = [expatinc]
733
                               ))                        
734

735
        # Dynamic loading module
736 737 738 739 740
        if sys.maxint == 0x7fffffff:
            # This requires sizeof(int) == sizeof(long) == sizeof(char*)
            dl_inc = find_file('dlfcn.h', [], inc_dirs)
            if (dl_inc is not None) and (platform not in ['atheos']):
                exts.append( Extension('dl', ['dlmodule.c']) )
741

742
        # Platform-specific libraries
743
        if platform == 'linux2':
744 745 746
            # Linux-specific modules
            exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) )

747
        if platform == 'sunos5':
748
            # SunOS specific modules
749
            exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) )
750

751
        if platform == 'darwin':
752 753 754 755 756
            # Mac OS X specific modules. Modules linked against the Carbon
            # framework are only built for framework-enabled Pythons. As
            # of MacOSX 10.1 importing the Carbon framework from a non-windowing
            # application (MacOSX server, not logged in on the console) may
            # result in Python crashing.
757 758 759 760
            #
            # I would like to trigger on WITH_NEXT_FRAMEWORK but that isn't
            # available here. This Makefile variable is also what the install
            # procedure triggers on.
761
            exts.append( Extension('_CF', ['cf/_CFmodule.c', 'cf/pycfbridge.c'],
762
                        extra_link_args=['-framework', 'CoreFoundation']) )
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779

            framework = sysconfig.get_config_var('PYTHONFRAMEWORK')
            if framework:
                exts.append( Extension('gestalt', ['gestaltmodule.c'],
                            extra_link_args=['-framework', 'Carbon']) )
                exts.append( Extension('MacOS', ['macosmodule.c'],
                            extra_link_args=['-framework', 'Carbon']) )
                exts.append( Extension('icglue', ['icgluemodule.c'],
                            extra_link_args=['-framework', 'Carbon']) )
                exts.append( Extension('macfs',
                                       ['macfsmodule.c',
                                        '../Python/getapplbycreator.c'],
                            extra_link_args=['-framework', 'Carbon']) )
                exts.append( Extension('_Res', ['res/_Resmodule.c'],
                            extra_link_args=['-framework', 'Carbon']) )
                exts.append( Extension('_Snd', ['snd/_Sndmodule.c'],
                            extra_link_args=['-framework', 'Carbon']) )
780
                exts.append( Extension('Nav', ['Nav.c'],
781
                        extra_link_args=['-framework', 'Carbon']) )
782
                exts.append( Extension('_AE', ['ae/_AEmodule.c'],
783
                        extra_link_args=['-framework', 'Carbon']) )
784 785
                exts.append( Extension('_AH', ['ah/_AHmodule.c'],
                        extra_link_args=['-framework', 'Carbon']) )
786
                exts.append( Extension('_App', ['app/_Appmodule.c'],
787
                        extra_link_args=['-framework', 'Carbon']) )
788
                exts.append( Extension('_CarbonEvt', ['carbonevt/_CarbonEvtmodule.c'],
789
                        extra_link_args=['-framework', 'Carbon']) )
790
                exts.append( Extension('_CG', ['cg/_CGmodule.c'],
791
                        extra_link_args=['-framework', 'ApplicationServices',
792
                                         '-framework', 'Carbon']) )
793
                exts.append( Extension('_Cm', ['cm/_Cmmodule.c'],
794
                        extra_link_args=['-framework', 'Carbon']) )
795
                exts.append( Extension('_Ctl', ['ctl/_Ctlmodule.c'],
796
                        extra_link_args=['-framework', 'Carbon']) )
797
                exts.append( Extension('_Dlg', ['dlg/_Dlgmodule.c'],
798
                        extra_link_args=['-framework', 'Carbon']) )
799
                exts.append( Extension('_Drag', ['drag/_Dragmodule.c'],
800
                        extra_link_args=['-framework', 'Carbon']) )
801
                exts.append( Extension('_Evt', ['evt/_Evtmodule.c'],
802
                        extra_link_args=['-framework', 'Carbon']) )
803
                exts.append( Extension('_Fm', ['fm/_Fmmodule.c'],
804
                        extra_link_args=['-framework', 'Carbon']) )
805 806
                exts.append( Extension('_Help', ['help/_Helpmodule.c'],
                        extra_link_args=['-framework', 'Carbon']) )
807
                exts.append( Extension('_Icn', ['icn/_Icnmodule.c'],
808
                        extra_link_args=['-framework', 'Carbon']) )
809 810
                exts.append( Extension('_IBCarbon', ['ibcarbon/_IBCarbon.c'],
                        extra_link_args=['-framework', 'Carbon']) )
811
                exts.append( Extension('_List', ['list/_Listmodule.c'],
812
                        extra_link_args=['-framework', 'Carbon']) )
813
                exts.append( Extension('_Menu', ['menu/_Menumodule.c'],
814
                        extra_link_args=['-framework', 'Carbon']) )
815
                exts.append( Extension('_Mlte', ['mlte/_Mltemodule.c'],
816
                        extra_link_args=['-framework', 'Carbon']) )
817
                exts.append( Extension('_Qd', ['qd/_Qdmodule.c'],
818
                        extra_link_args=['-framework', 'Carbon']) )
819
                exts.append( Extension('_Qdoffs', ['qdoffs/_Qdoffsmodule.c'],
820
                        extra_link_args=['-framework', 'Carbon']) )
821
                exts.append( Extension('_Qt', ['qt/_Qtmodule.c'],
Fred Drake's avatar
Fred Drake committed
822 823
                        extra_link_args=['-framework', 'QuickTime',
                                         '-framework', 'Carbon']) )
824
                exts.append( Extension('_Scrap', ['scrap/_Scrapmodule.c'],
825
                        extra_link_args=['-framework', 'Carbon']) )
826
                exts.append( Extension('_TE', ['te/_TEmodule.c'],
827
                        extra_link_args=['-framework', 'Carbon']) )
828 829 830 831 832 833 834 835
                # As there is no standardized place (yet) to put
                # user-installed Mac libraries on OSX, we search for "waste"
                # in parent directories of the Python source tree. You
                # should put a symlink to your Waste installation in the
                # same folder as your python source tree.  Or modify the
                # next few lines:-)
                waste_incs = find_file("WASTE.h", [], 
                        ['../'*n + 'waste/C_C++ Headers' for n in (0,1,2,3,4)])
836
                waste_libs = find_library_file(self.compiler, "WASTE", [],
837
            [           "../"*n + "waste/Static Libraries" for n in (0,1,2,3,4)])
838
                if waste_incs != None and waste_libs != None:
839
                    (srcdir,) = sysconfig.get_config_vars('srcdir')
840
                    exts.append( Extension('waste',
841 842
                                   ['waste/wastemodule.c'] + [
                                    os.path.join(srcdir, d) for d in 
843 844 845 846
                                    'Mac/Wastemods/WEObjectHandlers.c',
                                    'Mac/Wastemods/WETabHooks.c',
                                    'Mac/Wastemods/WETabs.c'
                                   ],
847
                                   include_dirs = waste_incs + [os.path.join(srcdir, 'Mac/Wastemods')],
848 849 850 851
                                   library_dirs = waste_libs,
                                   libraries = ['WASTE'],
                                   extra_link_args = ['-framework', 'Carbon'],
                    ) )
852
                exts.append( Extension('_Win', ['win/_Winmodule.c'],
853 854
                        extra_link_args=['-framework', 'Carbon']) )

855 856 857 858
        self.extensions.extend(exts)

        # Call the method for detecting whether _tkinter can be compiled
        self.detect_tkinter(inc_dirs, lib_dirs)
859

860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
    def detect_tkinter_darwin(self, inc_dirs, lib_dirs):
        # The _tkinter module, using frameworks. Since frameworks are quite
        # different the UNIX search logic is not sharable.
        from os.path import join, exists
        framework_dirs = [
            '/System/Library/Frameworks/', 
            '/Library/Frameworks', 
            join(os.getenv('HOME'), '/Library/Frameworks')
        ]

        # Find the directory that contains the Tcl.framwork and Tk.framework
        # bundles.
        # XXX distutils should support -F!
        for F in framework_dirs:
            # both Tcl.framework and Tk.framework should be present 
            for fw in 'Tcl', 'Tk':
            	if not exists(join(F, fw + '.framework')):
                    break
            else:
                # ok, F is now directory with both frameworks. Continure
                # building
                break
        else:
            # Tk and Tcl frameworks not found. Normal "unix" tkinter search
            # will now resume.
            return 0
                
        # For 8.4a2, we must add -I options that point inside the Tcl and Tk
        # frameworks. In later release we should hopefully be able to pass
        # the -F option to gcc, which specifies a framework lookup path. 
        #
        include_dirs = [
            join(F, fw + '.framework', H) 
            for fw in 'Tcl', 'Tk'
            for H in 'Headers', 'Versions/Current/PrivateHeaders'
        ]

        # For 8.4a2, the X11 headers are not included. Rather than include a 
        # complicated search, this is a hard-coded path. It could bail out
        # if X11 libs are not found...
        include_dirs.append('/usr/X11R6/include')
        frameworks = ['-framework', 'Tcl', '-framework', 'Tk']

        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
                        define_macros=[('WITH_APPINIT', 1)],
                        include_dirs = include_dirs,
                        libraries = [],
                        extra_compile_args = frameworks,
                        extra_link_args = frameworks,
                        )
        self.extensions.append(ext)
        return 1

         
914
    def detect_tkinter(self, inc_dirs, lib_dirs):
915
        # The _tkinter module.
916

917 918 919 920 921 922 923 924
        # Rather than complicate the code below, detecting and building
        # AquaTk is a separate method. Only one Tkinter will be built on
        # Darwin - either AquaTk, if it is found, or X11 based Tk.
        platform = self.get_platform()
        if platform == 'darwin' and \
           self.detect_tkinter_darwin(inc_dirs, lib_dirs):
          return

925
        # Assume we haven't found any of the libraries or include files
926 927
        # The versions with dots are used on Unix, and the versions without
        # dots on Windows, for detection by cygwin.
928
        tcllib = tklib = tcl_includes = tk_includes = None
929 930
        for version in ['8.4', '84', '8.3', '83', '8.2',
                        '82', '8.1', '81', '8.0', '80']:
931 932 933 934 935
            tklib = self.compiler.find_library_file(lib_dirs,
                                                    'tk' + version )
            tcllib = self.compiler.find_library_file(lib_dirs,
                                                     'tcl' + version )
            if tklib and tcllib:
936 937
                # Exit the loop when we've found the Tcl/Tk libraries
                break
938

939
        # Now check for the header files
940 941 942
        if tklib and tcllib:
            # Check for the include files on Debian, where
            # they're put in /usr/include/{tcl,tk}X.Y
943
            debian_tcl_include = [ '/usr/include/tcl' + version ]
Fred Drake's avatar
Fred Drake committed
944 945
            debian_tk_include =  [ '/usr/include/tk'  + version ] + \
                                 debian_tcl_include
946 947
            tcl_includes = find_file('tcl.h', inc_dirs, debian_tcl_include)
            tk_includes = find_file('tk.h', inc_dirs, debian_tk_include)
948 949 950 951 952

        if (tcllib is None or tklib is None and
            tcl_includes is None or tk_includes is None):
            # Something's missing, so give up
            return
953

954 955 956 957 958 959
        # OK... everything seems to be present for Tcl/Tk.

        include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = []
        for dir in tcl_includes + tk_includes:
            if dir not in include_dirs:
                include_dirs.append(dir)
960

961
        # Check for various platform-specific directories
962
        if platform == 'sunos5':
963 964 965 966 967 968 969 970 971
            include_dirs.append('/usr/openwin/include')
            added_lib_dirs.append('/usr/openwin/lib')
        elif os.path.exists('/usr/X11R6/include'):
            include_dirs.append('/usr/X11R6/include')
            added_lib_dirs.append('/usr/X11R6/lib')
        elif os.path.exists('/usr/X11R5/include'):
            include_dirs.append('/usr/X11R5/include')
            added_lib_dirs.append('/usr/X11R5/lib')
        else:
972
            # Assume default location for X11
973 974 975
            include_dirs.append('/usr/X11/include')
            added_lib_dirs.append('/usr/X11/lib')

976 977 978 979 980 981 982
        # If Cygwin, then verify that X is installed before proceeding
        if platform == 'cygwin':
            x11_inc = find_file('X11/Xlib.h', [], inc_dirs)
            if x11_inc is None:
                # X header files missing, so give up
                return

983
        # Check for BLT extension
Fred Drake's avatar
Fred Drake committed
984 985
        if self.compiler.find_library_file(lib_dirs + added_lib_dirs,
                                           'BLT8.0'):
986 987 988 989
            defs.append( ('WITH_BLT', 1) )
            libs.append('BLT8.0')

        # Add the Tcl/Tk libraries
990
        libs.append('tk'+version)
991
        libs.append('tcl'+version)
992

993
        if platform in ['aix3', 'aix4']:
994 995
            libs.append('ld')

996 997 998
        # Finally, link with the X11 libraries (not appropriate on cygwin)
        if platform != "cygwin":
            libs.append('X11')
999 1000 1001 1002 1003 1004 1005 1006

        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
                        define_macros=[('WITH_APPINIT', 1)] + defs,
                        include_dirs = include_dirs,
                        libraries = libs,
                        library_dirs = added_lib_dirs,
                        )
        self.extensions.append(ext)
1007

1008
        # XXX handle these, but how to detect?
1009
        # *** Uncomment and edit for PIL (TkImaging) extension only:
1010
        #       -DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \
1011
        # *** Uncomment and edit for TOGL extension only:
1012
        #       -DWITH_TOGL togl.c \
1013
        # *** Uncomment these for TOGL extension only:
1014
        #       -lGL -lGLU -lXext -lXmu \
1015

1016 1017 1018 1019 1020 1021 1022
class PyBuildInstall(install):
    # Suppress the warning about installation into the lib_dynload
    # directory, which is not in sys.path when running Python during
    # installation:
    def initialize_options (self):
        install.initialize_options(self)
        self.warn_dir=0
1023

1024
def main():
1025 1026 1027
    # turn off warnings when deprecated modules are imported
    import warnings
    warnings.filterwarnings("ignore",category=DeprecationWarning)
1028
    setup(name = 'Python standard library',
1029
          version = '%d.%d' % sys.version_info[:2],
1030
          cmdclass = {'build_ext':PyBuildExt, 'install':PyBuildInstall},
1031 1032
          # The struct module is defined here, because build_ext won't be
          # called unless there's at least one extension module defined.
1033 1034 1035 1036
          ext_modules=[Extension('struct', ['structmodule.c'])],

          # Scripts to install
          scripts = ['Tools/scripts/pydoc']
1037
        )
1038

1039 1040 1041
# --install-platlib
if __name__ == '__main__':
    main()