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

4 5
__version__ = "$Revision$"

6
import sys, os, imp, re, optparse
7
from glob import glob
8 9

from distutils import log
10
from distutils import sysconfig
11
from distutils import text_file
12
from distutils.errors import *
13 14
from distutils.core import Extension, setup
from distutils.command.build_ext import build_ext
15
from distutils.command.install import install
16
from distutils.command.install_lib import install_lib
17 18 19 20

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

Michael W. Hudson's avatar
Michael W. Hudson committed
21 22 23 24
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."""
25
    if dir is not None and os.path.isdir(dir) and dir not in dirlist:
Michael W. Hudson's avatar
Michael W. Hudson committed
26 27
        dirlist.insert(0, dir)

28 29 30 31
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.
32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
    '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
52 53
    return None

54
def find_library_file(compiler, libname, std_dirs, paths):
55 56 57
    result = compiler.find_library_file(std_dirs + paths, libname)
    if result is None:
        return None
58

59 60 61 62
    # Check whether the found file is in one of the standard directories
    dirname = os.path.dirname(result)
    for p in std_dirs:
        # Ensure path doesn't end with path separator
63
        p = p.rstrip(os.sep)
64 65
        if p == dirname:
            return [ ]
66

67 68 69 70
    # Otherwise, it must have been in one of the additional directories,
    # so we have to figure out which one.
    for p in paths:
        # Ensure path doesn't end with path separator
71
        p = p.rstrip(os.sep)
72 73 74 75
        if p == dirname:
            return [p]
    else:
        assert False, "Internal error: Path not found in std_dirs or paths"
Tim Peters's avatar
Tim Peters committed
76

77 78 79 80 81
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)
82

Jack Jansen's avatar
Jack Jansen committed
83 84 85 86 87 88 89
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:
90
        log.info("WARNING: multiple copies of %s found"%module)
Jack Jansen's avatar
Jack Jansen committed
91
    return os.path.join(list[0], module)
92

93
class PyBuildExt(build_ext):
94

95 96 97 98
    def __init__(self, dist):
        build_ext.__init__(self, dist)
        self.failed = []

99 100 101
    def build_extensions(self):

        # Detect which modules should be compiled
102
        missing = self.detect_modules()
103 104

        # Remove modules that are present on the disabled list
105 106 107 108 109 110 111 112
        extensions = [ext for ext in self.extensions
                      if ext.name not in disabled_module_list]
        # move ctypes to the end, it depends on other modules
        ext_map = dict((ext.name, i) for i, ext in enumerate(extensions))
        if "_ctypes" in ext_map:
            ctypes = extensions.pop(ext_map["_ctypes"])
            extensions.append(ctypes)
        self.extensions = extensions
113

114 115 116
        # 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')
Guido van Rossum's avatar
Guido van Rossum committed
117 118 119
        if not srcdir:
            # Maybe running on Windows but not using CYGWIN?
            raise ValueError("No source directory; cannot proceed.")
120

121
        # Figure out the location of the source code for extension modules
122 123
        # (This logic is copied in distutils.test.test_sysconfig,
        # so building in a separate directory does not break test_distutils.)
124
        moddir = os.path.join(os.getcwd(), srcdir, 'Modules')
125 126 127 128
        moddir = os.path.normpath(moddir)
        srcdir, tail = os.path.split(moddir)
        srcdir = os.path.normpath(srcdir)
        moddir = os.path.normpath(moddir)
129

Jack Jansen's avatar
Jack Jansen committed
130 131
        moddirlist = [moddir]
        incdirlist = ['./Include']
132

Jack Jansen's avatar
Jack Jansen committed
133 134
        # Platform-dependent module source and include directories
        platform = self.get_platform()
135

136 137
        alldirlist = moddirlist + incdirlist

138 139 140 141
        # Fix up the paths for scripts, too
        self.distribution.scripts = [os.path.join(srcdir, filename)
                                     for filename in self.distribution.scripts]

142 143 144
        # Python header files
        headers = glob("Include/*.h") + ["pyconfig.h"]

145
        for ext in self.extensions[:]:
Jack Jansen's avatar
Jack Jansen committed
146
            ext.sources = [ find_module_file(filename, moddirlist)
147
                            for filename in ext.sources ]
148 149 150
            if ext.depends is not None:
                ext.depends = [find_module_file(filename, alldirlist)
                               for filename in ext.depends]
151 152 153 154 155
            else:
                ext.depends = []
            # re-compile extensions if a header file has been changed
            ext.depends.extend(headers)

Jack Jansen's avatar
Jack Jansen committed
156 157 158
            ext.include_dirs.append( '.' ) # to get config.h
            for incdir in incdirlist:
                ext.include_dirs.append( os.path.join(srcdir, incdir) )
159

160
            # If a module has already been built statically,
161
            # don't build it here
162
            if ext.name in sys.builtin_module_names:
163
                self.extensions.remove(ext)
164

165
        if platform != 'mac':
166 167
            # Parse Modules/Setup and Modules/Setup.local to figure out which
            # modules are turned on in the file.
168
            remove_modules = []
169 170 171 172 173 174 175 176
            for filename in ('Modules/Setup', 'Modules/Setup.local'):
                input = text_file.TextFile(filename, join_lines=1)
                while 1:
                    line = input.readline()
                    if not line: break
                    line = line.split()
                    remove_modules.append(line[0])
                input.close()
Tim Peters's avatar
Tim Peters committed
177

178 179 180
            for ext in self.extensions[:]:
                if ext.name in remove_modules:
                    self.extensions.remove(ext)
181

182 183 184 185 186 187 188 189
        # 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')
        args = {}
        # unfortunately, distutils doesn't let us provide separate C and C++
        # compilers
        if compiler is not None:
190 191
            (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS')
            args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags
192 193
        self.compiler.set_executables(**args)

194 195
        build_ext.build_extensions(self)

196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
        longest = max([len(e.name) for e in self.extensions])
        if self.failed:
            longest = max(longest, max([len(name) for name in self.failed]))

        def print_three_column(lst):
            lst.sort(key=str.lower)
            # guarantee zip() doesn't drop anything
            while len(lst) % 3:
                lst.append("")
            for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]):
                print("%-*s   %-*s   %-*s" % (longest, e, longest, f,
                                              longest, g))

        if missing:
            print()
            print("Failed to find the necessary bits to build these modules:")
            print_three_column(missing)
213 214 215
            print("To find the necessary bits, look in setup.py in"
                  " detect_modules() for the module's name.")
            print()
216 217 218 219 220 221

        if self.failed:
            failed = self.failed[:]
            print()
            print("Failed to build these modules:")
            print_three_column(failed)
222
            print()
223

224 225
    def build_extension(self, ext):

226 227 228 229
        if ext.name == '_ctypes':
            if not self.configure_ctypes(ext):
                return

230 231
        try:
            build_ext.build_extension(self, ext)
232
        except (CCompilerError, DistutilsError) as why:
233 234
            self.announce('WARNING: building of extension "%s" failed: %s' %
                          (ext.name, sys.exc_info()[1]))
235
            self.failed.append(ext.name)
236
            return
237 238 239
        # 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:
240 241 242 243
            self.announce(
                'WARNING: skipping import check for Carbon-based "%s"' %
                ext.name)
            return
244 245 246 247 248 249
        # 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
250 251 252
        ext_filename = os.path.join(
            self.build_lib,
            self.get_ext_filename(self.get_ext_fullname(ext.name)))
253
        try:
Michael W. Hudson's avatar
Michael W. Hudson committed
254
            imp.load_dynamic(ext.name, ext_filename)
255
        except ImportError as why:
256
            self.failed.append(ext.name)
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
            self.announce('*** WARNING: renaming "%s" since importing it'
                          ' failed: %s' % (ext.name, why), level=3)
            assert not self.inplace
            basename, tail = os.path.splitext(ext_filename)
            newname = basename + "_failed" + tail
            if os.path.exists(newname):
                os.remove(newname)
            os.rename(ext_filename, newname)

            # 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.
            # 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)')
277 278
        except:
            exc_type, why, tb = sys.exc_info()
279 280 281
            self.announce('*** WARNING: importing extension "%s" '
                          'failed with %s: %s' % (ext.name, exc_type, why),
                          level=3)
282
            self.failed.append(ext.name)
283

284
    def get_platform(self):
285
        # Get value of sys.platform
Skip Montanaro's avatar
Skip Montanaro committed
286
        for platform in ['cygwin', 'darwin', 'atheos', 'osf1']:
287 288 289
            if sys.platform.startswith(platform):
                return platform
        return sys.platform
290

291
    def detect_modules(self):
292
        # Ensure that /usr/local is always used
Michael W. Hudson's avatar
Michael W. Hudson committed
293 294 295
        add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
        add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')

296
        # Add paths specified in the environment variables LDFLAGS and
297
        # CPPFLAGS for header and library files.
298 299 300
        # We must get the values from the Makefile and not the environment
        # directly since an inconsistently reproducible issue comes up where
        # the environment variable is not set even though the value were passed
301
        # into configure and stored in the Makefile (issue found on OS X 10.3).
302 303 304
        for env_var, arg_name, dir_list in (
                ('LDFLAGS', '-L', self.compiler.library_dirs),
                ('CPPFLAGS', '-I', self.compiler.include_dirs)):
305
            env_val = sysconfig.get_config_var(env_var)
306
            if env_val:
307 308 309 310 311 312 313 314 315
                # To prevent optparse from raising an exception about any
                # options in env_val that is doesn't know about we strip out
                # all double dashes and any dashes followed by a character
                # that is not for the option we are dealing with.
                #
                # Please note that order of the regex is important!  We must
                # strip out double-dashes first so that we don't end up with
                # substituting "--Long" to "-Long" and thus lead to "ong" being
                # used for a library directory.
316 317
                env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1],
                                 ' ', env_val)
318
                parser = optparse.OptionParser()
319 320 321 322
                # Make sure that allowing args interspersed with options is
                # allowed
                parser.allow_interspersed_args = True
                parser.error = lambda msg: None
323 324
                parser.add_option(arg_name, dest="dirs", action="append")
                options = parser.parse_args(env_val.split())[0]
325
                if options.dirs:
Christian Heimes's avatar
Christian Heimes committed
326
                    for directory in reversed(options.dirs):
327
                        add_dir_to_list(dir_list, directory)
328

Michael W. Hudson's avatar
Michael W. Hudson committed
329 330 331 332 333
        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"))
334 335 336 337

        # 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.
338 339 340 341
        lib_dirs = self.compiler.library_dirs + [
            '/lib64', '/usr/lib64',
            '/lib', '/usr/lib',
            ]
342
        inc_dirs = self.compiler.include_dirs + ['/usr/include']
343
        exts = []
344
        missing = []
345

346 347 348
        config_h = sysconfig.get_config_h_filename()
        config_h_vars = sysconfig.parse_config_h(open(config_h))

349
        platform = self.get_platform()
350
        (srcdir,) = sysconfig.get_config_vars('srcdir')
351

352 353 354 355 356 357 358
        # 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)

359 360
        # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
        if platform in ['osf1', 'unixware7', 'openunix8']:
361 362
            lib_dirs += ['/usr/ccs/lib']

363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
        if platform == 'darwin':
            # This should work on any unixy platform ;-)
            # If the user has bothered specifying additional -I and -L flags
            # in OPT and LDFLAGS we might as well use them here.
            #   NOTE: using shlex.split would technically be more correct, but
            # also gives a bootstrap problem. Let's hope nobody uses directories
            # with whitespace in the name to store libraries.
            cflags, ldflags = sysconfig.get_config_vars(
                    'CFLAGS', 'LDFLAGS')
            for item in cflags.split():
                if item.startswith('-I'):
                    inc_dirs.append(item[2:])

            for item in ldflags.split():
                if item.startswith('-L'):
                    lib_dirs.append(item[2:])

380 381
        # Check for MacOS X, which doesn't need libm.a at all
        math_libs = ['m']
Skip Montanaro's avatar
Skip Montanaro committed
382
        if platform in ['darwin', 'mac']:
383
            math_libs = []
384

385 386 387 388 389 390
        # XXX Omitted modules: gl, pure, dl, SGI-specific modules

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

392
        # Some modules that are normally always on:
393
        exts.append( Extension('_weakref', ['_weakref.c']) )
394 395 396 397

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

401
        # math library functions, e.g. sin()
402 403
        exts.append( Extension('math',  ['mathmodule.c'],
                               libraries=math_libs) )
404
        # time operations and variables
405 406
        exts.append( Extension('time', ['timemodule.c'],
                               libraries=math_libs) )
407
        exts.append( Extension('datetime', ['datetimemodule.c', 'timemodule.c'],
408
                               libraries=math_libs) )
409 410
        # fast iterator tools implemented in C
        exts.append( Extension("itertools", ["itertoolsmodule.c"]) )
Christian Heimes's avatar
Christian Heimes committed
411 412
        # random number generator implemented in C
        exts.append( Extension("_random", ["_randommodule.c"]) )
413
        # high-performance collections
414
        exts.append( Extension("_collections", ["_collectionsmodule.c"]) )
415 416
        # bisect
        exts.append( Extension("_bisect", ["_bisectmodule.c"]) )
417
        # heapq
418
        exts.append( Extension("_heapq", ["_heapqmodule.c"]) )
419 420
        # operator.add() and similar goodies
        exts.append( Extension('operator', ['operator.c']) )
421 422
        # _functools
        exts.append( Extension("_functools", ["_functoolsmodule.c"]) )
423 424
        # Memory-based IO accelerator modules
        exts.append( Extension("_bytesio", ["_bytesio.c"]) )
425 426
        # atexit
        exts.append( Extension("atexit", ["atexitmodule.c"]) )
427 428
        # _json speedups
        exts.append( Extension("_json", ["_json.c"]) )
429
        # Python C API test module
430
        exts.append( Extension('_testcapi', ['_testcapimodule.c']) )
431
        # profiler (_lsprof is for cProfile.py)
Armin Rigo's avatar
Armin Rigo committed
432
        exts.append( Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c']) )
433
        # static Unicode character database
434
        exts.append( Extension('unicodedata', ['unicodedata.c']) )
435
        # access to ISO C locale support
436 437 438
        data = open('pyconfig.h').read()
        m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data)
        if m is not None:
439 440 441
            locale_libs = ['intl']
        else:
            locale_libs = []
442 443 444 445
        if platform == 'darwin':
            locale_extra_link_args = ['-framework', 'CoreFoundation']
        else:
            locale_extra_link_args = []
446

447

448
        exts.append( Extension('_locale', ['_localemodule.c'],
449 450
                               libraries=locale_libs,
                               extra_link_args=locale_extra_link_args) )
451 452 453 454 455 456 457

        # 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']) )
458
        if platform not in ['mac']:
459
            # pwd(3)
Tim Peters's avatar
Tim Peters committed
460 461 462
            exts.append( Extension('pwd', ['pwdmodule.c']) )
            # grp(3)
            exts.append( Extension('grp', ['grpmodule.c']) )
463
            # spwd, shadow passwords
464 465
            if (config_h_vars.get('HAVE_GETSPNAM', False) or
                    config_h_vars.get('HAVE_GETSPENT', False)):
466
                exts.append( Extension('spwd', ['spwdmodule.c']) )
467 468 469 470 471
            else:
                missing.append('spwd')
        else:
            missing.extend(['pwd', 'grp', 'spwd'])

472 473 474 475 476 477 478
        # select(2); not on ancient System V
        exts.append( Extension('select', ['selectmodule.c']) )

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

        # Memory-mapped files (also works on Win32).
479
        if platform not in ['atheos', 'mac']:
480
            exts.append( Extension('mmap', ['mmapmodule.c']) )
481 482
        else:
            missing.append('mmap')
483

484
        # Lance Ellinghaus's syslog module
485
        if platform not in ['mac']:
Tim Peters's avatar
Tim Peters committed
486 487
            # syslog daemon interface
            exts.append( Extension('syslog', ['syslogmodule.c']) )
488 489
        else:
            missing.append('syslog')
490 491

        #
492 493
        # Here ends the simple stuff.  From here on, modules need certain
        # libraries, are platform-specific, or present other surprises.
494 495 496 497 498 499
        #

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

500
        # Operations on audio samples
Tim Peters's avatar
Tim Peters committed
501
        # According to #993173, this one should actually work fine on
502 503 504
        # 64-bit platforms.
        exts.append( Extension('audioop', ['audioop.c']) )

505
        # readline
506 507 508 509 510
        do_readline = self.compiler.find_library_file(lib_dirs, 'readline')
        if platform == 'darwin':
            # MacOSX 10.4 has a broken readline. Don't try to build
            # the readline module unless the user has installed a fixed
            # readline package
511
            if find_file('readline/rlconf.h', inc_dirs, []) is None:
512 513
                do_readline = False
        if do_readline:
514 515 516
            if sys.platform == 'darwin':
                # In every directory on the search path search for a dynamic
                # library and then a static library, instead of first looking
Fred Drake's avatar
Fred Drake committed
517
                # for dynamic libraries on the entire path.
518 519 520 521 522 523
                # This way a staticly linked custom readline gets picked up
                # before the (broken) dynamic library in /usr/lib.
                readline_extra_link_args = ('-Wl,-search_paths_first',)
            else:
                readline_extra_link_args = ()

524
            readline_libs = ['readline']
525
            if self.compiler.find_library_file(lib_dirs,
526 527 528
                                                 'ncursesw'):
                readline_libs.append('ncursesw')
            elif self.compiler.find_library_file(lib_dirs,
529 530
                                                 'ncurses'):
                readline_libs.append('ncurses')
531 532
            elif self.compiler.find_library_file(lib_dirs, 'curses'):
                readline_libs.append('curses')
533
            elif self.compiler.find_library_file(lib_dirs +
534 535 536
                                               ['/usr/lib/termcap'],
                                               'termcap'):
                readline_libs.append('termcap')
537
            exts.append( Extension('readline', ['readline.c'],
538
                                   library_dirs=['/usr/lib/termcap'],
539
                                   extra_link_args=readline_extra_link_args,
540
                                   libraries=readline_libs) )
541 542 543
        else:
            missing.append('readline')

544
        if platform not in ['mac']:
545
            # crypt module.
Tim Peters's avatar
Tim Peters committed
546 547 548 549 550 551

            if self.compiler.find_library_file(lib_dirs, 'crypt'):
                libs = ['crypt']
            else:
                libs = []
            exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) )
552 553
        else:
            missing.append('crypt')
554

Skip Montanaro's avatar
Skip Montanaro committed
555 556 557
        # CSV files
        exts.append( Extension('_csv', ['_csv.c']) )

558
        # socket(2)
559
        exts.append( Extension('_socket', ['socketmodule.c'],
560
                               depends = ['socketmodule.h']) )
561
        # Detect SSL support for the socket module (via _ssl)
562 563
        search_for_ssl_incs_in = [
                              '/usr/local/ssl/include',
564 565
                              '/usr/contrib/ssl/include/'
                             ]
566 567
        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
                             search_for_ssl_incs_in
568
                             )
569 570 571 572 573
        if ssl_incs is not None:
            krb5_h = find_file('krb5.h', inc_dirs,
                               ['/usr/kerberos/include'])
            if krb5_h:
                ssl_incs += krb5_h
574
        ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
575 576 577
                                     ['/usr/local/ssl/lib',
                                      '/usr/contrib/ssl/lib/'
                                     ] )
578

579 580
        if (ssl_incs is not None and
            ssl_libs is not None):
581
            exts.append( Extension('_ssl', ['_ssl.c'],
582
                                   include_dirs = ssl_incs,
583
                                   library_dirs = ssl_libs,
584
                                   libraries = ['ssl', 'crypto'],
585
                                   depends = ['socketmodule.h']), )
586 587
        else:
            missing.append('_ssl')
588

589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
        # find out which version of OpenSSL we have
        openssl_ver = 0
        openssl_ver_re = re.compile(
            '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' )
        for ssl_inc_dir in inc_dirs + search_for_ssl_incs_in:
            name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h')
            if os.path.isfile(name):
                try:
                    incfile = open(name, 'r')
                    for line in incfile:
                        m = openssl_ver_re.match(line)
                        if m:
                            openssl_ver = eval(m.group(1))
                            break
                except IOError:
                    pass

            # first version found is what we'll use (as the compiler should)
            if openssl_ver:
                break

610 611 612 613 614 615 616 617 618 619 620 621 622 623
        #print('openssl_ver = 0x%08x' % openssl_ver)

        if ssl_incs is not None and ssl_libs is not None:
            if openssl_ver >= 0x00907000:
                # The _hashlib module wraps optimized implementations
                # of hash functions from the OpenSSL library.
                exts.append( Extension('_hashlib', ['_hashopenssl.c'],
                                       include_dirs = ssl_incs,
                                       library_dirs = ssl_libs,
                                       libraries = ['ssl', 'crypto']) )
            else:
                print("warning: openssl 0x%08x is too old for _hashlib" %
                      openssl_ver)
                missing.append('_hashlib')
624
        else:
625
            missing.append('_hashlib')
626

627
        if openssl_ver < 0x00908000:
628 629 630
            # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash
            exts.append( Extension('_sha256', ['sha256module.c']) )
            exts.append( Extension('_sha512', ['sha512module.c']) )
631

632
        if openssl_ver < 0x00907000:
633 634 635 636
            # no openssl at all, use our own md5 and sha1
            exts.append( Extension('_md5', ['md5module.c']) )
            exts.append( Extension('_sha1', ['sha1module.c']) )

637 638 639
        # 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
640 641
        # dependencies.  The Python module dbm/__init__.py provides an
        # implementation independent wrapper for these; dbm/dumb.py provides
642 643
        # similar functionality (but slower of course) implemented in Python.

644 645
        # Sleepycat^WOracle Berkeley DB interface.
        #  http://www.oracle.com/database/berkeley-db/db/index.html
646
        #
647
        # This requires the Sleepycat^WOracle DB code. The supported versions
648
        # are set below.  Visit the URL above to download
649 650
        # a release.  Most open source OSes come with one or more
        # versions of BerkeleyDB already installed.
651

652 653 654 655
        max_db_ver = (4, 5)  # XXX(gregory.p.smith): 4.6 "works" but seems to
                             # have issues on many platforms.  I've temporarily
                             # disabled 4.6 to see what the odd platform
                             # buildbots say.
656
        min_db_ver = (3, 3)
657 658 659 660 661 662 663 664 665 666 667
        db_setup_debug = False   # verbose debug prints from this script?

        # construct a list of paths to look for the header file in on
        # top of the normal inc_dirs.
        db_inc_paths = [
            '/usr/include/db4',
            '/usr/local/include/db4',
            '/opt/sfw/include/db4',
            '/usr/include/db3',
            '/usr/local/include/db3',
            '/opt/sfw/include/db3',
668 669
            # Fink defaults (http://fink.sourceforge.net/)
            '/sw/include/db4',
670 671 672
            '/sw/include/db3',
        ]
        # 4.x minor number specific paths
673
        for x in range(max_db_ver[1]+1):
674
            db_inc_paths.append('/usr/include/db4%d' % x)
675
            db_inc_paths.append('/usr/include/db4.%d' % x)
676 677 678
            db_inc_paths.append('/usr/local/BerkeleyDB.4.%d/include' % x)
            db_inc_paths.append('/usr/local/include/db4%d' % x)
            db_inc_paths.append('/pkg/db-4.%d/include' % x)
679
            db_inc_paths.append('/opt/db-4.%d/include' % x)
680 681
            # MacPorts default (http://www.macports.org/)
            db_inc_paths.append('/opt/local/include/db4%d' % x)
682
        # 3.x minor number specific paths
683
        for x in (3,):
684 685 686 687
            db_inc_paths.append('/usr/include/db3%d' % x)
            db_inc_paths.append('/usr/local/BerkeleyDB.3.%d/include' % x)
            db_inc_paths.append('/usr/local/include/db3%d' % x)
            db_inc_paths.append('/pkg/db-3.%d/include' % x)
688
            db_inc_paths.append('/opt/db-3.%d/include' % x)
689

690 691 692 693 694 695 696 697
        # Add some common subdirectories for Sleepycat DB to the list,
        # based on the standard include directories. This way DB3/4 gets
        # picked up when it is installed in a non-standard prefix and
        # the user has added that prefix into inc_dirs.
        std_variants = []
        for dn in inc_dirs:
            std_variants.append(os.path.join(dn, 'db3'))
            std_variants.append(os.path.join(dn, 'db4'))
Christian Heimes's avatar
Christian Heimes committed
698
            for x in range(max_db_ver[1]+1):
699 700
                std_variants.append(os.path.join(dn, "db4%d"%x))
                std_variants.append(os.path.join(dn, "db4.%d"%x))
Christian Heimes's avatar
Christian Heimes committed
701
            for x in (3,):
702 703 704 705
                std_variants.append(os.path.join(dn, "db3%d"%x))
                std_variants.append(os.path.join(dn, "db3.%d"%x))

        db_inc_paths = std_variants + db_inc_paths
706
        db_inc_paths = [p for p in db_inc_paths if os.path.exists(p)]
707

708 709 710
        db_ver_inc_map = {}

        class db_found(Exception): pass
711
        try:
712 713
            # See whether there is a Sleepycat header in the standard
            # search path.
714
            for d in inc_dirs + db_inc_paths:
715
                f = os.path.join(d, "db.h")
716
                if db_setup_debug: print("db: looking for db.h in", f)
717 718
                if os.path.exists(f):
                    f = open(f).read()
719
                    m = re.search(r"#define\WDB_VERSION_MAJOR\W(\d+)", f)
720
                    if m:
721 722 723 724 725
                        db_major = int(m.group(1))
                        m = re.search(r"#define\WDB_VERSION_MINOR\W(\d+)", f)
                        db_minor = int(m.group(1))
                        db_ver = (db_major, db_minor)

726 727 728 729 730 731 732 733 734
                        # Avoid 4.6 prior to 4.6.21 due to a BerkeleyDB bug
                        if db_ver == (4, 6):
                            m = re.search(r"#define\WDB_VERSION_PATCH\W(\d+)", f)
                            db_patch = int(m.group(1))
                            if db_patch < 21:
                                print("db.h:", db_ver, "patch", db_patch,
                                      "being ignored (4.6.x must be >= 4.6.21)")
                                continue

735
                        if ( (db_ver not in db_ver_inc_map) and
736 737
                           (db_ver <= max_db_ver and db_ver >= min_db_ver) ):
                            # save the include directory with the db.h version
738
                            # (first occurrence only)
739
                            db_ver_inc_map[db_ver] = d
740
                            if db_setup_debug:
741
                                print("db.h: found", db_ver, "in", d)
742 743
                        else:
                            # we already found a header for this library version
744
                            if db_setup_debug: print("db.h: ignoring", d)
745 746
                    else:
                        # ignore this header, it didn't contain a version number
747 748
                        if db_setup_debug:
                            print("db.h: no version number version in", d)
749

750
            db_found_vers = sorted(db_ver_inc_map.keys())
751 752 753 754 755 756 757

            while db_found_vers:
                db_ver = db_found_vers.pop()
                db_incdir = db_ver_inc_map[db_ver]

                # check lib directories parallel to the location of the header
                db_dirs_to_check = [
758 759
                    db_incdir.replace("include", 'lib64'),
                    db_incdir.replace("include", 'lib'),
760
                ]
761
                db_dirs_to_check = [x for x in db_dirs_to_check if os.path.isdir(x)]
762 763 764 765 766

                # Look for a version specific db-X.Y before an ambiguoius dbX
                # XXX should we -ever- look for a dbX name?  Do any
                # systems really not name their library by version and
                # symlink to more general names?
767 768 769
                for dblib in (('db-%d.%d' % db_ver),
                              ('db%d%d' % db_ver),
                              ('db%d' % db_ver[0])):
770 771 772 773 774 775
                    dblib_file = self.compiler.find_library_file(
                                    db_dirs_to_check + lib_dirs, dblib )
                    if dblib_file:
                        dblib_dir = [ os.path.abspath(os.path.dirname(dblib_file)) ]
                        raise db_found
                    else:
776
                        if db_setup_debug: print("db lib: ", dblib, "not found")
777 778

        except db_found:
779
            if db_setup_debug:
780 781
                print("db lib: using", db_ver, dblib)
                print("db: lib dir", dblib_dir, "inc dir", db_incdir)
782
            db_incs = [db_incdir]
783
            dblibs = [dblib]
784 785 786 787 788 789
            # We add the runtime_library_dirs argument because the
            # BerkeleyDB lib we're linking against often isn't in the
            # system dynamic library search path.  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).
790
            exts.append(Extension('_bsddb', ['_bsddb.c'],
791
                                  depends = ['bsddb.h'],
792 793
                                  library_dirs=dblib_dir,
                                  runtime_library_dirs=dblib_dir,
794 795
                                  include_dirs=db_incs,
                                  libraries=dblibs))
796
        else:
797
            if db_setup_debug: print("db: no appropriate library found")
798 799 800
            db_incs = None
            dblibs = []
            dblib_dir = None
801
            missing.append('_bsddb')
802

803
        # The sqlite interface
804
        sqlite_setup_debug = False   # verbose debug prints from this script?
805 806 807 808 809 810 811 812 813 814 815 816 817 818

        # We hunt for #define SQLITE_VERSION "n.n.n"
        # We need to find >= sqlite version 3.0.8
        sqlite_incdir = sqlite_libdir = None
        sqlite_inc_paths = [ '/usr/include',
                             '/usr/include/sqlite',
                             '/usr/include/sqlite3',
                             '/usr/local/include',
                             '/usr/local/include/sqlite',
                             '/usr/local/include/sqlite3',
                           ]
        MIN_SQLITE_VERSION_NUMBER = (3, 0, 8)
        MIN_SQLITE_VERSION = ".".join([str(x)
                                    for x in MIN_SQLITE_VERSION_NUMBER])
819 820 821 822 823

        # Scan the default include directories before the SQLite specific
        # ones. This allows one to override the copy of sqlite on OSX,
        # where /usr/include contains an old version of sqlite.
        for d in inc_dirs + sqlite_inc_paths:
824 825
            f = os.path.join(d, "sqlite3.h")
            if os.path.exists(f):
826
                if sqlite_setup_debug: print("sqlite: found %s"%f)
827 828 829 830 831 832 833 834 835
                incf = open(f).read()
                m = re.search(
                    r'\s*.*#\s*.*define\s.*SQLITE_VERSION\W*"(.*)"', incf)
                if m:
                    sqlite_version = m.group(1)
                    sqlite_version_tuple = tuple([int(x)
                                        for x in sqlite_version.split(".")])
                    if sqlite_version_tuple >= MIN_SQLITE_VERSION_NUMBER:
                        # we win!
836
                        if sqlite_setup_debug:
837
                            print("%s/sqlite3.h: version %s"%(d, sqlite_version))
838 839 840 841
                        sqlite_incdir = d
                        break
                    else:
                        if sqlite_setup_debug:
842 843
                            print("%s: version %d is too old, need >= %s"%(d,
                                        sqlite_version, MIN_SQLITE_VERSION))
844
                elif sqlite_setup_debug:
845
                    print("sqlite: %s had no SQLITE_VERSION"%(f,))
846 847 848 849 850 851 852 853 854 855 856 857 858

        if sqlite_incdir:
            sqlite_dirs_to_check = [
                os.path.join(sqlite_incdir, '..', 'lib64'),
                os.path.join(sqlite_incdir, '..', 'lib'),
                os.path.join(sqlite_incdir, '..', '..', 'lib64'),
                os.path.join(sqlite_incdir, '..', '..', 'lib'),
            ]
            sqlite_libfile = self.compiler.find_library_file(
                                sqlite_dirs_to_check + lib_dirs, 'sqlite3')
            sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))]

        if sqlite_incdir and sqlite_libdir:
859
            sqlite_srcs = ['_sqlite/cache.c',
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
                '_sqlite/connection.c',
                '_sqlite/cursor.c',
                '_sqlite/microprotocols.c',
                '_sqlite/module.c',
                '_sqlite/prepare_protocol.c',
                '_sqlite/row.c',
                '_sqlite/statement.c',
                '_sqlite/util.c', ]

            sqlite_defines = []
            if sys.platform != "win32":
                sqlite_defines.append(('MODULE_NAME', '"sqlite3"'))
            else:
                sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"'))

875 876 877 878 879 880 881 882 883 884

            if sys.platform == 'darwin':
                # In every directory on the search path search for a dynamic
                # library and then a static library, instead of first looking
                # for dynamic libraries on the entiry path.
                # This way a staticly linked custom sqlite gets picked up
                # before the dynamic library in /usr/lib.
                sqlite_extra_link_args = ('-Wl,-search_paths_first',)
            else:
                sqlite_extra_link_args = ()
885 886 887 888 889 890 891

            exts.append(Extension('_sqlite3', sqlite_srcs,
                                  define_macros=sqlite_defines,
                                  include_dirs=["Modules/_sqlite",
                                                sqlite_incdir],
                                  library_dirs=sqlite_libdir,
                                  runtime_library_dirs=sqlite_libdir,
892
                                  extra_link_args=sqlite_extra_link_args,
893
                                  libraries=["sqlite3",]))
894 895
        else:
            missing.append('_sqlite3')
896

897
        # The standard Unix dbm module:
898
        if platform not in ['cygwin']:
899 900 901 902 903 904
            if find_file("ndbm.h", inc_dirs, []) is not None:
                # Some systems have -lndbm, others don't
                if self.compiler.find_library_file(lib_dirs, 'ndbm'):
                    ndbm_libs = ['ndbm']
                else:
                    ndbm_libs = []
905
                exts.append( Extension('_dbm', ['_dbmmodule.c'],
906
                                       define_macros=[('HAVE_NDBM_H',None)],
907
                                       libraries = ndbm_libs ) )
908 909
            elif (self.compiler.find_library_file(lib_dirs, 'gdbm')
                  and find_file("gdbm/ndbm.h", inc_dirs, []) is not None):
910
                exts.append( Extension('_dbm', ['_dbmmodule.c'],
911
                                       define_macros=[('HAVE_GDBM_NDBM_H',None)],
912 913
                                       libraries = ['gdbm'] ) )
            elif db_incs is not None:
914
                exts.append( Extension('_dbm', ['_dbmmodule.c'],
915 916
                                       library_dirs=dblib_dir,
                                       runtime_library_dirs=dblib_dir,
917
                                       include_dirs=db_incs,
918 919
                                       define_macros=[('HAVE_BERKDB_H',None),
                                                      ('DB_DBM_HSEARCH',None)],
920
                                       libraries=dblibs))
921
            else:
922
                missing.append('_dbm')
923

924 925
        # Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:
        if (self.compiler.find_library_file(lib_dirs, 'gdbm')):
926
            exts.append( Extension('_gdbm', ['_gdbmmodule.c'],
927
                                   libraries = ['gdbm'] ) )
928
        else:
929
            missing.append('_gdbm')
930 931

        # Unix-only modules
932
        if platform not in ['mac', 'win32']:
933 934 935
            # Steen Lumholt's termios module
            exts.append( Extension('termios', ['termios.c']) )
            # Jeremy Hylton's rlimit interface
Tim Peters's avatar
Tim Peters committed
936
            if platform not in ['atheos']:
937
                exts.append( Extension('resource', ['resource.c']) )
938 939
            else:
                missing.append('resource')
940

941
            # Sun yellow pages. Some systems have the functions in libc.
Georg Brandl's avatar
Georg Brandl committed
942
            if platform not in ['cygwin', 'atheos', 'qnx6']:
943 944 945 946 947 948
                if (self.compiler.find_library_file(lib_dirs, 'nsl')):
                    libs = ['nsl']
                else:
                    libs = []
                exts.append( Extension('nis', ['nismodule.c'],
                                       libraries = libs) )
949 950 951 952
            else:
                missing.append('nis')
        else:
            missing.extend(['nis', 'resource', 'termios'])
953

954
        # Curses support, requiring the System V version of curses, often
955
        # provided by the ncurses library.
956
        panel_library = 'panel'
957 958
        if (self.compiler.find_library_file(lib_dirs, 'ncursesw')):
            curses_libs = ['ncursesw']
959 960 961
            # Bug 1464056: If _curses.so links with ncursesw,
            # _curses_panel.so must link with panelw.
            panel_library = 'panelw'
962 963 964
            exts.append( Extension('_curses', ['_cursesmodule.c'],
                                   libraries = curses_libs) )
        elif (self.compiler.find_library_file(lib_dirs, 'ncurses')):
965 966 967
            curses_libs = ['ncurses']
            exts.append( Extension('_curses', ['_cursesmodule.c'],
                                   libraries = curses_libs) )
Fred Drake's avatar
Fred Drake committed
968 969
        elif (self.compiler.find_library_file(lib_dirs, 'curses')
              and platform != 'darwin'):
970 971
                # OSX has an old Berkeley curses, not good enough for
                # the _curses module.
972 973
            if (self.compiler.find_library_file(lib_dirs, 'terminfo')):
                curses_libs = ['curses', 'terminfo']
974
            elif (self.compiler.find_library_file(lib_dirs, 'termcap')):
975
                curses_libs = ['curses', 'termcap']
976 977
            else:
                curses_libs = ['curses']
978

979 980
            exts.append( Extension('_curses', ['_cursesmodule.c'],
                                   libraries = curses_libs) )
981 982
        else:
            missing.append('_curses')
983

984
        # If the curses module is enabled, check for the panel module
985
        if (module_enabled(exts, '_curses') and
986
            self.compiler.find_library_file(lib_dirs, panel_library)):
987
            exts.append( Extension('_curses_panel', ['_curses_panel.c'],
988
                                   libraries = [panel_library] + curses_libs) )
989 990
        else:
            missing.append('_curses_panel')
991

992 993 994 995 996 997 998 999 1000 1001 1002 1003
        # 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/
1004
        zlib_inc = find_file('zlib.h', [], inc_dirs)
1005
        have_zlib = False
1006 1007 1008
        if zlib_inc is not None:
            zlib_h = zlib_inc[0] + '/zlib.h'
            version = '"0.0.0"'
1009
            version_req = '"1.1.3"'
1010 1011 1012 1013 1014
            fp = open(zlib_h)
            while 1:
                line = fp.readline()
                if not line:
                    break
1015
                if line.startswith('#define ZLIB_VERSION'):
1016 1017 1018 1019
                    version = line.split()[2]
                    break
            if version >= version_req:
                if (self.compiler.find_library_file(lib_dirs, 'z')):
1020 1021 1022 1023
                    if sys.platform == "darwin":
                        zlib_extra_link_args = ('-Wl,-search_paths_first',)
                    else:
                        zlib_extra_link_args = ()
1024
                    exts.append( Extension('zlib', ['zlibmodule.c'],
1025 1026
                                           libraries = ['z'],
                                           extra_link_args = zlib_extra_link_args))
1027
                    have_zlib = True
1028 1029 1030 1031 1032 1033
                else:
                    missing.append('zlib')
            else:
                missing.append('zlib')
        else:
            missing.append('zlib')
1034

1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
        # Helper module for various ascii-encoders.  Uses zlib for an optimized
        # crc32 if we have it.  Otherwise binascii uses its own.
        if have_zlib:
            extra_compile_args = ['-DUSE_ZLIB_CRC32']
            libraries = ['z']
            extra_link_args = zlib_extra_link_args
        else:
            extra_compile_args = []
            libraries = []
            extra_link_args = []
        exts.append( Extension('binascii', ['binascii.c'],
                               extra_compile_args = extra_compile_args,
                               libraries = libraries,
                               extra_link_args = extra_link_args) )

1050 1051
        # Gustavo Niemeyer's bz2 module.
        if (self.compiler.find_library_file(lib_dirs, 'bz2')):
1052 1053 1054 1055
            if sys.platform == "darwin":
                bz2_extra_link_args = ('-Wl,-search_paths_first',)
            else:
                bz2_extra_link_args = ()
1056
            exts.append( Extension('bz2', ['bz2module.c'],
1057 1058
                                   libraries = ['bz2'],
                                   extra_link_args = bz2_extra_link_args) )
1059 1060
        else:
            missing.append('bz2')
1061

1062 1063
        # Interface to the Expat XML parser
        #
1064 1065 1066
        # 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
1067 1068
        # Prescod after a prototype by Jack Jansen.  The Expat source
        # is included in Modules/expat/.  Usage of a system
1069 1070 1071 1072
        # shared libexpat.so/expat.dll is not advised.
        #
        # More information on Expat can be found at www.libexpat.org.
        #
1073
        expatinc = os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')
1074
        define_macros = [
1075 1076 1077
            ('HAVE_EXPAT_CONFIG_H', '1'),
        ]

1078 1079 1080 1081 1082 1083 1084 1085 1086
        exts.append(Extension('pyexpat',
                              define_macros = define_macros,
                              include_dirs = [expatinc],
                              sources = ['pyexpat.c',
                                         'expat/xmlparse.c',
                                         'expat/xmlrole.c',
                                         'expat/xmltok.c',
                                         ],
                              ))
1087

1088 1089 1090
        # Fredrik Lundh's cElementTree module.  Note that this also
        # uses expat (via the CAPI hook in pyexpat).

1091
        if os.path.isfile(os.path.join(srcdir, 'Modules', '_elementtree.c')):
1092 1093 1094 1095 1096 1097
            define_macros.append(('USE_PYEXPAT_CAPI', None))
            exts.append(Extension('_elementtree',
                                  define_macros = define_macros,
                                  include_dirs = [expatinc],
                                  sources = ['_elementtree.c'],
                                  ))
1098 1099
        else:
            missing.append('_elementtree')
1100

1101
        # Hye-Shik Chang's CJKCodecs modules.
1102 1103 1104 1105 1106
        exts.append(Extension('_multibytecodec',
                              ['cjkcodecs/multibytecodec.c']))
        for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'):
            exts.append(Extension('_codecs_%s' % loc,
                                  ['cjkcodecs/_codecs_%s.c' % loc]))
1107

1108
        # Thomas Heller's _ctypes module
1109
        self.detect_ctypes(inc_dirs, lib_dirs)
1110

1111 1112 1113
        # _fileio -- supposedly cross platform
        exts.append(Extension('_fileio', ['_fileio.c']))

1114
        # Platform-specific libraries
Hye-Shik Chang's avatar
Hye-Shik Chang committed
1115
        if platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6',
1116
                        'freebsd7', 'freebsd8'):
1117
            exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
1118 1119
        else:
            missing.append('ossaudiodev')
1120

1121 1122 1123 1124 1125 1126 1127 1128
        if sys.platform == 'darwin':
            exts.append(
                       Extension('_gestalt', ['_gestalt.c'],
                       extra_link_args=['-framework', 'Carbon'])
                       )
        else:
            missing.append('_gestalt')

1129 1130 1131 1132
        self.extensions.extend(exts)

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

1134 1135 1136 1137 1138
        if '_tkinter' not in [e.name for e in self.extensions]:
            missing.append('_tkinter')

        return missing

1139 1140 1141 1142 1143
    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 = [
Tim Peters's avatar
Tim Peters committed
1144 1145
            '/System/Library/Frameworks/',
            '/Library/Frameworks',
1146 1147 1148
            join(os.getenv('HOME'), '/Library/Frameworks')
        ]

1149
        # Find the directory that contains the Tcl.framework and Tk.framework
1150 1151 1152
        # bundles.
        # XXX distutils should support -F!
        for F in framework_dirs:
Tim Peters's avatar
Tim Peters committed
1153
            # both Tcl.framework and Tk.framework should be present
1154
            for fw in 'Tcl', 'Tk':
Tim Peters's avatar
Tim Peters committed
1155
                if not exists(join(F, fw + '.framework')):
1156 1157 1158 1159 1160 1161 1162 1163 1164
                    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
Tim Peters's avatar
Tim Peters committed
1165

1166 1167
        # 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
Tim Peters's avatar
Tim Peters committed
1168
        # the -F option to gcc, which specifies a framework lookup path.
1169 1170
        #
        include_dirs = [
Tim Peters's avatar
Tim Peters committed
1171
            join(F, fw + '.framework', H)
1172 1173
            for fw in ('Tcl', 'Tk')
            for H in ('Headers', 'Versions/Current/PrivateHeaders')
1174 1175
        ]

Tim Peters's avatar
Tim Peters committed
1176
        # For 8.4a2, the X11 headers are not included. Rather than include a
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191
        # 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

Tim Peters's avatar
Tim Peters committed
1192

1193
    def detect_tkinter(self, inc_dirs, lib_dirs):
1194
        # The _tkinter module.
1195

1196 1197 1198 1199
        # 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()
1200 1201
        if (platform == 'darwin' and
            self.detect_tkinter_darwin(inc_dirs, lib_dirs)):
Tim Peters's avatar
Tim Peters committed
1202
            return
1203

1204
        # Assume we haven't found any of the libraries or include files
1205 1206
        # The versions with dots are used on Unix, and the versions without
        # dots on Windows, for detection by cygwin.
1207
        tcllib = tklib = tcl_includes = tk_includes = None
1208
        for version in ['8.5', '85', '8.4', '84', '8.3', '83', '8.2',
1209
                        '82', '8.1', '81', '8.0', '80']:
1210 1211
            tklib = self.compiler.find_library_file(lib_dirs, 'tk' + version)
            tcllib = self.compiler.find_library_file(lib_dirs, 'tcl' + version)
1212
            if tklib and tcllib:
1213 1214
                # Exit the loop when we've found the Tcl/Tk libraries
                break
1215

1216
        # Now check for the header files
1217
        if tklib and tcllib:
1218
            # Check for the include files on Debian and {Free,Open}BSD, where
1219
            # they're put in /usr/include/{tcl,tk}X.Y
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
            dotversion = version
            if '.' not in dotversion and "bsd" in sys.platform.lower():
                # OpenBSD and FreeBSD use Tcl/Tk library names like libtcl83.a,
                # but the include subdirs are named like .../include/tcl8.3.
                dotversion = dotversion[:-1] + '.' + dotversion[-1]
            tcl_include_sub = []
            tk_include_sub = []
            for dir in inc_dirs:
                tcl_include_sub += [dir + os.sep + "tcl" + dotversion]
                tk_include_sub += [dir + os.sep + "tk" + dotversion]
            tk_include_sub += tcl_include_sub
            tcl_includes = find_file('tcl.h', inc_dirs, tcl_include_sub)
            tk_includes = find_file('tk.h', inc_dirs, tk_include_sub)
1233

1234
        if (tcllib is None or tklib is None or
1235
            tcl_includes is None or tk_includes is None):
1236
            self.announce("INFO: Can't locate Tcl/Tk libs and/or headers", 2)
1237
            return
1238

1239 1240 1241 1242 1243 1244
        # 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)
1245

1246
        # Check for various platform-specific directories
1247
        if platform == 'sunos5':
1248 1249 1250 1251
            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')
1252
            added_lib_dirs.append('/usr/X11R6/lib64')
1253 1254 1255 1256 1257
            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:
1258
            # Assume default location for X11
1259 1260 1261
            include_dirs.append('/usr/X11/include')
            added_lib_dirs.append('/usr/X11/lib')

1262 1263 1264 1265 1266 1267
        # If Cygwin, then verify that X is installed before proceeding
        if platform == 'cygwin':
            x11_inc = find_file('X11/Xlib.h', [], include_dirs)
            if x11_inc is None:
                return

1268
        # Check for BLT extension
Fred Drake's avatar
Fred Drake committed
1269 1270
        if self.compiler.find_library_file(lib_dirs + added_lib_dirs,
                                           'BLT8.0'):
1271 1272
            defs.append( ('WITH_BLT', 1) )
            libs.append('BLT8.0')
1273 1274 1275 1276
        elif self.compiler.find_library_file(lib_dirs + added_lib_dirs,
                                           'BLT'):
            defs.append( ('WITH_BLT', 1) )
            libs.append('BLT')
1277 1278

        # Add the Tcl/Tk libraries
1279 1280
        libs.append('tk'+ version)
        libs.append('tcl'+ version)
1281

1282
        if platform in ['aix3', 'aix4']:
1283 1284
            libs.append('ld')

1285 1286 1287
        # Finally, link with the X11 libraries (not appropriate on cygwin)
        if platform != "cygwin":
            libs.append('X11')
1288 1289 1290 1291 1292 1293 1294 1295

        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)
1296

1297 1298 1299 1300
##         # Uncomment these lines if you want to play with xxmodule.c
##         ext = Extension('xx', ['xxmodule.c'])
##         self.extensions.append(ext)

1301
        # XXX handle these, but how to detect?
1302
        # *** Uncomment and edit for PIL (TkImaging) extension only:
1303
        #       -DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \
1304
        # *** Uncomment and edit for TOGL extension only:
1305
        #       -DWITH_TOGL togl.c \
1306
        # *** Uncomment these for TOGL extension only:
1307
        #       -lGL -lGLU -lXext -lXmu \
1308

1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334
    def configure_ctypes_darwin(self, ext):
        # Darwin (OS X) uses preconfigured files, in
        # the Modules/_ctypes/libffi_osx directory.
        (srcdir,) = sysconfig.get_config_vars('srcdir')
        ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
                                                  '_ctypes', 'libffi_osx'))
        sources = [os.path.join(ffi_srcdir, p)
                   for p in ['ffi.c',
                             'x86/x86-darwin.S',
                             'x86/x86-ffi_darwin.c',
                             'x86/x86-ffi64.c',
                             'powerpc/ppc-darwin.S',
                             'powerpc/ppc-darwin_closure.S',
                             'powerpc/ppc-ffi_darwin.c',
                             'powerpc/ppc64-darwin_closure.S',
                             ]]

        # Add .S (preprocessed assembly) to C compiler source extensions.
        self.compiler.src_extensions.append('.S')

        include_dirs = [os.path.join(ffi_srcdir, 'include'),
                        os.path.join(ffi_srcdir, 'powerpc')]
        ext.include_dirs.extend(include_dirs)
        ext.sources.extend(sources)
        return True

1335 1336
    def configure_ctypes(self, ext):
        if not self.use_system_libffi:
1337 1338 1339
            if sys.platform == 'darwin':
                return self.configure_ctypes_darwin(ext)

1340 1341 1342 1343 1344 1345
            (srcdir,) = sysconfig.get_config_vars('srcdir')
            ffi_builddir = os.path.join(self.build_temp, 'libffi')
            ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
                                         '_ctypes', 'libffi'))
            ffi_configfile = os.path.join(ffi_builddir, 'fficonfig.py')

1346 1347 1348
            from distutils.dep_util import newer_group

            config_sources = [os.path.join(ffi_srcdir, fname)
1349 1350
                              for fname in os.listdir(ffi_srcdir)
                              if os.path.isfile(os.path.join(ffi_srcdir, fname))]
1351 1352
            if self.force or newer_group(config_sources,
                                         ffi_configfile):
1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
                from distutils.dir_util import mkpath
                mkpath(ffi_builddir)
                config_args = []

                # Pass empty CFLAGS because we'll just append the resulting
                # CFLAGS to Python's; -g or -O2 is to be avoided.
                cmd = "cd %s && env CFLAGS='' '%s/configure' %s" \
                      % (ffi_builddir, ffi_srcdir, " ".join(config_args))

                res = os.system(cmd)
                if res or not os.path.exists(ffi_configfile):
1364
                    print("Failed to configure _ctypes module")
1365 1366 1367
                    return False

            fficonfig = {}
1368 1369 1370 1371 1372 1373
            fp = open(ffi_configfile)
            try:
                script = fp.read()
            finally:
                fp.close()
            exec(script, globals(), fficonfig)
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
            ffi_srcdir = os.path.join(fficonfig['ffi_srcdir'], 'src')

            # Add .S (preprocessed assembly) to C compiler source extensions.
            self.compiler.src_extensions.append('.S')

            include_dirs = [os.path.join(ffi_builddir, 'include'),
                            ffi_builddir, ffi_srcdir]
            extra_compile_args = fficonfig['ffi_cflags'].split()

            ext.sources.extend(fficonfig['ffi_sources'])
            ext.include_dirs.extend(include_dirs)
            ext.extra_compile_args.extend(extra_compile_args)
        return True

    def detect_ctypes(self, inc_dirs, lib_dirs):
        self.use_system_libffi = False
        include_dirs = []
        extra_compile_args = []
1392
        extra_link_args = []
1393 1394 1395 1396 1397
        sources = ['_ctypes/_ctypes.c',
                   '_ctypes/callbacks.c',
                   '_ctypes/callproc.c',
                   '_ctypes/stgdict.c',
                   '_ctypes/cfield.c',
1398
                   '_ctypes/malloc_closure.c']
1399 1400 1401 1402
        depends = ['_ctypes/ctypes.h']

        if sys.platform == 'darwin':
            sources.append('_ctypes/darwin/dlfcn_simple.c')
1403
            extra_compile_args.append('-DMACOSX')
1404 1405 1406 1407
            include_dirs.append('_ctypes/darwin')
# XXX Is this still needed?
##            extra_link_args.extend(['-read_only_relocs', 'warning'])

1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
        elif sys.platform == 'sunos5':
            # XXX This shouldn't be necessary; it appears that some
            # of the assembler code is non-PIC (i.e. it has relocations
            # when it shouldn't. The proper fix would be to rewrite
            # the assembler code to be PIC.
            # This only works with GCC; the Sun compiler likely refuses
            # this option. If you want to compile ctypes with the Sun
            # compiler, please research a proper solution, instead of
            # finding some -z option for the Sun compiler.
            extra_link_args.append('-mimpure-text')

1419
        elif sys.platform.startswith('hp-ux'):
1420 1421
            extra_link_args.append('-fPIC')

1422 1423 1424
        ext = Extension('_ctypes',
                        include_dirs=include_dirs,
                        extra_compile_args=extra_compile_args,
1425
                        extra_link_args=extra_link_args,
1426
                        libraries=[],
1427 1428 1429 1430 1431 1432
                        sources=sources,
                        depends=depends)
        ext_test = Extension('_ctypes_test',
                             sources=['_ctypes/_ctypes_test.c'])
        self.extensions.extend([ext, ext_test])

1433 1434 1435
        if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
            return

1436 1437 1438 1439 1440
        if sys.platform == 'darwin':
            # OS X 10.5 comes with libffi.dylib; the include files are
            # in /usr/include/ffi
            inc_dirs.append('/usr/include/ffi')

1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464
        ffi_inc = find_file('ffi.h', [], inc_dirs)
        if ffi_inc is not None:
            ffi_h = ffi_inc[0] + '/ffi.h'
            fp = open(ffi_h)
            while 1:
                line = fp.readline()
                if not line:
                    ffi_inc = None
                    break
                if line.startswith('#define LIBFFI_H'):
                    break
        ffi_lib = None
        if ffi_inc is not None:
            for lib_name in ('ffi_convenience', 'ffi_pic', 'ffi'):
                if (self.compiler.find_library_file(lib_dirs, lib_name)):
                    ffi_lib = lib_name
                    break

        if ffi_inc and ffi_lib:
            ext.include_dirs.extend(ffi_inc)
            ext.libraries.append(ffi_lib)
            self.use_system_libffi = True


1465 1466 1467 1468 1469 1470 1471
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
1472

1473 1474 1475 1476 1477 1478 1479 1480 1481 1482
class PyBuildInstallLib(install_lib):
    # Do exactly what install_lib does but make sure correct access modes get
    # set on installed directories and files. All installed files with get
    # mode 644 unless they are a shared library in which case they will get
    # mode 755. All installed directories will get mode 755.

    so_ext = sysconfig.get_config_var("SO")

    def install(self):
        outfiles = install_lib.install(self)
1483 1484
        self.set_file_modes(outfiles, 0o644, 0o755)
        self.set_dir_modes(self.install_dir, 0o755)
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
        return outfiles

    def set_file_modes(self, files, defaultMode, sharedLibMode):
        if not self.is_chmod_supported(): return
        if not files: return

        for filename in files:
            if os.path.islink(filename): continue
            mode = defaultMode
            if filename.endswith(self.so_ext): mode = sharedLibMode
            log.info("changing mode of %s to %o", filename, mode)
            if not self.dry_run: os.chmod(filename, mode)

    def set_dir_modes(self, dirname, mode):
        if not self.is_chmod_supported(): return
1500
        os.walk(dirname, self.set_dir_modes_visitor, mode)
1501 1502 1503 1504 1505 1506 1507 1508 1509

    def set_dir_modes_visitor(self, mode, dirname, names):
        if os.path.islink(dirname): return
        log.info("changing mode of %s to %o", dirname, mode)
        if not self.dry_run: os.chmod(dirname, mode)

    def is_chmod_supported(self):
        return hasattr(os, 'chmod')

Guido van Rossum's avatar
Guido van Rossum committed
1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
SUMMARY = """
Python is an interpreted, interactive, object-oriented programming
language. It is often compared to Tcl, Perl, Scheme or Java.

Python combines remarkable power with very clear syntax. It has
modules, classes, exceptions, very high level dynamic data types, and
dynamic typing. There are interfaces to many system calls and
libraries, as well as to various windowing systems (X11, Motif, Tk,
Mac, MFC). New built-in modules are easily written in C or C++. Python
is also usable as an extension language for applications that need a
programmable interface.

The Python implementation is portable: it runs on many brands of UNIX,
on Windows, DOS, OS/2, Mac, Amiga... If your favorite system isn't
listed here, it may still be supported, if there's a C compiler for
it. Ask around on comp.lang.python -- or just try compiling Python
yourself.
"""

CLASSIFIERS = """
Development Status :: 3 - Alpha
Development Status :: 6 - Mature
License :: OSI Approved :: Python Software Foundation License
Natural Language :: English
Programming Language :: C
Programming Language :: Python
Topic :: Software Development
"""

1539
def main():
1540 1541 1542
    # turn off warnings when deprecated modules are imported
    import warnings
    warnings.filterwarnings("ignore",category=DeprecationWarning)
Guido van Rossum's avatar
Guido van Rossum committed
1543 1544 1545 1546 1547 1548 1549 1550 1551
    setup(# PyPI Metadata (PEP 301)
          name = "Python",
          version = sys.version.split()[0],
          url = "http://www.python.org/%s" % sys.version[:3],
          maintainer = "Guido van Rossum and the Python community",
          maintainer_email = "python-dev@python.org",
          description = "A high-level object-oriented programming language",
          long_description = SUMMARY.strip(),
          license = "PSF license",
1552
          classifiers = [x for x in CLASSIFIERS.split("\n") if x],
Guido van Rossum's avatar
Guido van Rossum committed
1553 1554 1555
          platforms = ["Many"],

          # Build info
1556 1557
          cmdclass = {'build_ext':PyBuildExt, 'install':PyBuildInstall,
                      'install_lib':PyBuildInstallLib},
1558 1559
          # The struct module is defined here, because build_ext won't be
          # called unless there's at least one extension module defined.
1560
          ext_modules=[Extension('_struct', ['_struct.c'])],
1561 1562

          # Scripts to install
1563
          scripts = ['Tools/scripts/pydoc', 'Tools/scripts/idle',
1564
                     'Tools/scripts/2to3',
1565
                     'Lib/smtpd.py']
1566
        )
1567

1568 1569 1570
# --install-platlib
if __name__ == '__main__':
    main()