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

4
import sys, os, imp, re, optparse
5
from glob import glob
6
import sysconfig
7 8

from distutils import log
9
from distutils import text_file
Marc-André Lemburg's avatar
Marc-André Lemburg committed
10
from distutils.errors import *
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
11 12
from distutils.core import Extension, setup
from distutils.command.build_ext import build_ext
13
from distutils.command.install import install
14
from distutils.command.install_lib import install_lib
15
from distutils.command.build_scripts import build_scripts
16
from distutils.spawn import find_executable
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
17

18 19 20
# Were we compiled --with-pydebug or with #define Py_DEBUG?
COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
21 22 23
# This global variable is used to hold the list of modules to be disabled.
disabled_module_list = []

24 25 26 27
# File which contains the directory for shared mods (for sys.path fixup
# when running from the build dir, see Modules/getpath.c)
_BUILDDIR_COOKIE = "pybuilddir.txt"

Michael W. Hudson's avatar
Michael W. Hudson committed
28
def add_dir_to_list(dirlist, dir):
29 30 31
    """Add the directory 'dir' to the list 'dirlist' (after any relative
    directories) if:

Michael W. Hudson's avatar
Michael W. Hudson committed
32
    1) 'dir' is not already in 'dirlist'
33 34 35 36 37 38 39
    2) 'dir' actually exists, and is a directory.
    """
    if dir is None or not os.path.isdir(dir) or dir in dirlist:
        return
    for i, path in enumerate(dirlist):
        if not os.path.isabs(path):
            dirlist.insert(i + 1, dir)
40 41
            return
    dirlist.insert(0, dir)
Michael W. Hudson's avatar
Michael W. Hudson committed
42

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
def macosx_sdk_root():
    """
    Return the directory of the current OSX SDK,
    or '/' if no SDK was specified.
    """
    cflags = sysconfig.get_config_var('CFLAGS')
    m = re.search(r'-isysroot\s+(\S+)', cflags)
    if m is None:
        sysroot = '/'
    else:
        sysroot = m.group(1)
    return sysroot

def is_macosx_sdk_path(path):
    """
    Returns True if 'path' can be located in an OSX SDK
    """
60
    return (path.startswith('/usr/') and not path.startswith('/usr/local')) or path.startswith('/System/')
61

62 63 64 65
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.
66

67 68 69 70 71 72
    '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.
    """
73 74 75 76 77
    if sys.platform == 'darwin':
        # Honor the MacOSX SDK setting when one was specified.
        # An SDK is a directory with the same structure as a real
        # system, but with only header files and libraries.
        sysroot = macosx_sdk_root()
78 79 80 81

    # Check the standard locations
    for dir in std_dirs:
        f = os.path.join(dir, filename)
82 83 84 85

        if sys.platform == 'darwin' and is_macosx_sdk_path(dir):
            f = os.path.join(sysroot, dir[1:], filename)

86 87 88 89 90
        if os.path.exists(f): return []

    # Check the additional directories
    for dir in paths:
        f = os.path.join(dir, filename)
91 92 93 94

        if sys.platform == 'darwin' and is_macosx_sdk_path(dir):
            f = os.path.join(sysroot, dir[1:], filename)

95 96 97 98
        if os.path.exists(f):
            return [dir]

    # Not found anywhere
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
99 100
    return None

101
def find_library_file(compiler, libname, std_dirs, paths):
102 103 104
    result = compiler.find_library_file(std_dirs + paths, libname)
    if result is None:
        return None
105

106 107 108
    if sys.platform == 'darwin':
        sysroot = macosx_sdk_root()

109 110 111 112
    # 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
113
        p = p.rstrip(os.sep)
114 115 116 117 118

        if sys.platform == 'darwin' and is_macosx_sdk_path(p):
            if os.path.join(sysroot, p[1:]) == dirname:
                return [ ]

119 120
        if p == dirname:
            return [ ]
121

122 123 124 125
    # 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
126
        p = p.rstrip(os.sep)
127 128 129 130 131

        if sys.platform == 'darwin' and is_macosx_sdk_path(p):
            if os.path.join(sysroot, p[1:]) == dirname:
                return [ p ]

132 133 134 135
        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
136

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
137 138 139 140 141
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)
142

Jack Jansen's avatar
Jack Jansen committed
143 144 145 146 147 148 149
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:
150
        log.info("WARNING: multiple copies of %s found"%module)
Jack Jansen's avatar
Jack Jansen committed
151
    return os.path.join(list[0], module)
152

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
153
class PyBuildExt(build_ext):
154

155 156 157 158
    def __init__(self, dist):
        build_ext.__init__(self, dist)
        self.failed = []

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
159 160 161
    def build_extensions(self):

        # Detect which modules should be compiled
162 163 164 165 166 167 168
        old_so = self.compiler.shared_lib_extension
        # Workaround PEP 3149 stuff
        self.compiler.shared_lib_extension = os.environ.get("SO", ".so")
        try:
            missing = self.detect_modules()
        finally:
            self.compiler.shared_lib_extension = old_so
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
169 170

        # Remove modules that are present on the disabled list
171 172 173 174 175 176 177 178
        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
179

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
180
        # Fix up the autodetected modules, prefixing all the source files
181 182
        # with Modules/.
        srcdir = sysconfig.get_config_var('srcdir')
Guido van Rossum's avatar
Guido van Rossum committed
183 184 185
        if not srcdir:
            # Maybe running on Windows but not using CYGWIN?
            raise ValueError("No source directory; cannot proceed.")
186
        srcdir = os.path.abspath(srcdir)
187
        moddirlist = [os.path.join(srcdir, 'Modules')]
188

Jack Jansen's avatar
Jack Jansen committed
189 190
        # Platform-dependent module source and include directories
        platform = self.get_platform()
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
191

192 193 194 195
        # Fix up the paths for scripts, too
        self.distribution.scripts = [os.path.join(srcdir, filename)
                                     for filename in self.distribution.scripts]

196
        # Python header files
197
        headers = [sysconfig.get_config_h_filename()]
198
        headers += glob(os.path.join(sysconfig.get_path('include'), "*.h"))
199

200
        for ext in self.extensions[:]:
Jack Jansen's avatar
Jack Jansen committed
201
            ext.sources = [ find_module_file(filename, moddirlist)
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
202
                            for filename in ext.sources ]
203
            if ext.depends is not None:
204
                ext.depends = [find_module_file(filename, moddirlist)
205
                               for filename in ext.depends]
206 207 208 209 210
            else:
                ext.depends = []
            # re-compile extensions if a header file has been changed
            ext.depends.extend(headers)

211
            # If a module has already been built statically,
212
            # don't build it here
213
            if ext.name in sys.builtin_module_names:
214
                self.extensions.remove(ext)
215

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
        # Parse Modules/Setup and Modules/Setup.local to figure out which
        # modules are turned on in the file.
        remove_modules = []
        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()

        for ext in self.extensions[:]:
            if ext.name in remove_modules:
                self.extensions.remove(ext)
231

232 233 234 235 236 237 238 239
        # 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:
240 241
            (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS')
            args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags
242
        self.compiler.set_executables(**args)
243

244 245 246 247 248 249
        # Not only do we write the builddir cookie, but we manually install
        # the shared modules directory if it isn't already in sys.path.
        # Otherwise trying to import the extensions after building them
        # will fail.
        with open(_BUILDDIR_COOKIE, "wb") as f:
            f.write(self.build_lib.encode('utf-8', 'surrogateescape'))
250
        abs_build_lib = os.path.join(os.getcwd(), self.build_lib)
251 252 253
        if abs_build_lib not in sys.path:
            sys.path.append(abs_build_lib)

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
254 255
        build_ext.build_extensions(self)

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
        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()
Benjamin Peterson's avatar
Benjamin Peterson committed
271 272
            print("Python build finished, but the necessary bits to build "
                   "these modules were not found:")
273
            print_three_column(missing)
274 275 276
            print("To find the necessary bits, look in setup.py in"
                  " detect_modules() for the module's name.")
            print()
277 278 279 280 281 282

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

Marc-André Lemburg's avatar
Marc-André Lemburg committed
285 286
    def build_extension(self, ext):

287 288 289 290
        if ext.name == '_ctypes':
            if not self.configure_ctypes(ext):
                return

Marc-André Lemburg's avatar
Marc-André Lemburg committed
291 292
        try:
            build_ext.build_extension(self, ext)
293
        except (CCompilerError, DistutilsError) as why:
Marc-André Lemburg's avatar
Marc-André Lemburg committed
294 295
            self.announce('WARNING: building of extension "%s" failed: %s' %
                          (ext.name, sys.exc_info()[1]))
296
            self.failed.append(ext.name)
297
            return
298 299 300
        # 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:
301 302 303 304
            self.announce(
                'WARNING: skipping import check for Carbon-based "%s"' %
                ext.name)
            return
305 306

        if self.get_platform() == 'darwin' and (
Benjamin Peterson's avatar
Benjamin Peterson committed
307
                sys.maxsize > 2**32 and '-arch' in ext.extra_link_args):
308 309 310 311 312 313 314 315 316 317
            # Don't bother doing an import check when an extension was
            # build with an explicit '-arch' flag on OSX. That's currently
            # only used to build 32-bit only extensions in a 4-way
            # universal build and loading 32-bit code into a 64-bit
            # process will fail.
            self.announce(
                'WARNING: skipping import check for "%s"' %
                ext.name)
            return

318 319 320 321 322 323
        # 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
Fix for  
Michael W. Hudson committed
324 325 326
        ext_filename = os.path.join(
            self.build_lib,
            self.get_ext_filename(self.get_ext_fullname(ext.name)))
327 328 329 330 331 332

        # If the build directory didn't exist when setup.py was
        # started, sys.path_importer_cache has a negative result
        # cached.  Clear that cache before trying to import.
        sys.path_importer_cache.clear()

333
        try:
Michael W. Hudson's avatar
Fix for  
Michael W. Hudson committed
334
            imp.load_dynamic(ext.name, ext_filename)
335
        except ImportError as why:
336
            self.failed.append(ext.name)
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
            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)')
357 358
        except:
            exc_type, why, tb = sys.exc_info()
359 360 361
            self.announce('*** WARNING: importing extension "%s" '
                          'failed with %s: %s' % (ext.name, exc_type, why),
                          level=3)
362
            self.failed.append(ext.name)
363

364
    def get_platform(self):
365
        # Get value of sys.platform
366 367
        if sys.platform.startswith('osf1'):
            return 'osf1'
368
        return sys.platform
369

370 371 372
    def add_multiarch_paths(self):
        # Debian/Ubuntu multiarch support.
        # https://wiki.ubuntu.com/MultiarchSpec
373 374
        if not find_executable('dpkg-architecture'):
            return
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
        tmpfile = os.path.join(self.build_temp, 'multiarch')
        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)
        ret = os.system(
            'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
            tmpfile)
        try:
            if ret >> 8 == 0:
                with open(tmpfile) as fp:
                    multiarch_path_component = fp.readline().strip()
                add_dir_to_list(self.compiler.library_dirs,
                                '/usr/lib/' + multiarch_path_component)
                add_dir_to_list(self.compiler.include_dirs,
                                '/usr/include/' + multiarch_path_component)
        finally:
            os.unlink(tmpfile)

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
392
    def detect_modules(self):
393 394 395
        # Ensure that /usr/local is always used, but the local build
        # directories (i.e. '.' and 'Include') must be first.  See issue
        # 10520.
396 397
        add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
        add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
398
        self.add_multiarch_paths()
Michael W. Hudson's avatar
Michael W. Hudson committed
399

400
        # Add paths specified in the environment variables LDFLAGS and
401
        # CPPFLAGS for header and library files.
402 403 404
        # 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
405
        # into configure and stored in the Makefile (issue found on OS X 10.3).
406
        for env_var, arg_name, dir_list in (
407 408 409
                ('LDFLAGS', '-R', self.compiler.runtime_library_dirs),
                ('LDFLAGS', '-L', self.compiler.library_dirs),
                ('CPPFLAGS', '-I', self.compiler.include_dirs)):
410
            env_val = sysconfig.get_config_var(env_var)
411
            if env_val:
412
                # To prevent optparse from raising an exception about any
Skip Montanaro's avatar
Skip Montanaro committed
413
                # options in env_val that it doesn't know about we strip out
414 415 416 417 418 419 420
                # 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.
421 422
                env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1],
                                 ' ', env_val)
423
                parser = optparse.OptionParser()
424 425 426 427
                # Make sure that allowing args interspersed with options is
                # allowed
                parser.allow_interspersed_args = True
                parser.error = lambda msg: None
428 429
                parser.add_option(arg_name, dest="dirs", action="append")
                options = parser.parse_args(env_val.split())[0]
430
                if options.dirs:
Christian Heimes's avatar
Christian Heimes committed
431
                    for directory in reversed(options.dirs):
432
                        add_dir_to_list(dir_list, directory)
433

Ronald Oussoren's avatar
Ronald Oussoren committed
434 435 436 437 438 439
        if os.path.normpath(sys.prefix) != '/usr' \
                and not sysconfig.get_config_var('PYTHONFRAMEWORK'):
            # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework
            # (PYTHONFRAMEWORK is set) to avoid # linking problems when
            # building a framework with different architectures than
            # the one that is currently installed (issue #7473)
440
            add_dir_to_list(self.compiler.library_dirs,
Michael W. Hudson's avatar
Fix for  
Michael W. Hudson committed
441
                            sysconfig.get_config_var("LIBDIR"))
442
            add_dir_to_list(self.compiler.include_dirs,
Michael W. Hudson's avatar
Fix for  
Michael W. Hudson committed
443
                            sysconfig.get_config_var("INCLUDEDIR"))
444 445 446 447

        # 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.
448
        lib_dirs = self.compiler.library_dirs + [
449 450 451
            '/lib64', '/usr/lib64',
            '/lib', '/usr/lib',
            ]
452
        inc_dirs = self.compiler.include_dirs + ['/usr/include']
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
453
        exts = []
454
        missing = []
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
455

456
        config_h = sysconfig.get_config_h_filename()
457 458
        with open(config_h) as file:
            config_h_vars = sysconfig.parse_config_h(file)
459

460
        platform = self.get_platform()
461
        srcdir = sysconfig.get_config_var('srcdir')
462

463 464
        # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
        if platform in ['osf1', 'unixware7', 'openunix8']:
465 466
            lib_dirs += ['/usr/ccs/lib']

467 468 469 470
        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.
471 472 473 474
            #
            # 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.
475 476 477 478 479 480 481 482 483 484
            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:])

485 486
        # Check for MacOS X, which doesn't need libm.a at all
        math_libs = ['m']
487
        if platform == 'darwin':
488
            math_libs = []
489

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
490 491 492 493 494 495
        # XXX Omitted modules: gl, pure, dl, SGI-specific modules

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

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
497 498 499
        # array objects
        exts.append( Extension('array', ['arraymodule.c']) )
        # complex math library functions
500 501
        exts.append( Extension('cmath', ['cmathmodule.c', '_math.c'],
                               depends=['_math.h'],
502
                               libraries=math_libs) )
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
503
        # math library functions, e.g. sin()
504
        exts.append( Extension('math',  ['mathmodule.c', '_math.c'],
505
                               depends=['_math.h'],
506
                               libraries=math_libs) )
507 508 509 510 511 512 513

        # time libraries: librt may be needed for clock_gettime()
        time_libs = []
        lib = sysconfig.get_config_var('TIMEMODULE_LIB')
        if lib:
            time_libs.append(lib)

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
514
        # time operations and variables
515
        exts.append( Extension('time', ['timemodule.c'],
516
                               libraries=time_libs) )
517
        exts.append( Extension('_datetime', ['_datetimemodule.c']) )
Christian Heimes's avatar
Christian Heimes committed
518 519
        # random number generator implemented in C
        exts.append( Extension("_random", ["_randommodule.c"]) )
520 521
        # bisect
        exts.append( Extension("_bisect", ["_bisectmodule.c"]) )
522
        # heapq
523
        exts.append( Extension("_heapq", ["_heapqmodule.c"]) )
524 525
        # C-optimized pickle replacement
        exts.append( Extension("_pickle", ["_pickle.c"]) )
526 527
        # atexit
        exts.append( Extension("atexit", ["atexitmodule.c"]) )
528 529
        # _json speedups
        exts.append( Extension("_json", ["_json.c"]) )
Marc-André Lemburg's avatar
Marc-André Lemburg committed
530
        # Python C API test module
531 532
        exts.append( Extension('_testcapi', ['_testcapimodule.c'],
                               depends=['testcapi_long.h']) )
533 534
        # Python PEP-3118 (buffer protocol) test module
        exts.append( Extension('_testbuffer', ['_testbuffer.c']) )
Fred Drake's avatar
Fred Drake committed
535
        # profiler (_lsprof is for cProfile.py)
Armin Rigo's avatar
Armin Rigo committed
536
        exts.append( Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c']) )
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
537
        # static Unicode character database
538
        exts.append( Extension('unicodedata', ['unicodedata.c']) )
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
539 540 541 542 543 544

        # 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)
545 546 547 548 549
        libs = []
        if (config_h_vars.get('FLOCK_NEEDS_LIBBSD', False)):
            # May be necessary on AIX for flock function
            libs = ['bsd']
        exts.append( Extension('fcntl', ['fcntlmodule.c'], libraries=libs) )
550 551 552 553 554 555 556 557
        # pwd(3)
        exts.append( Extension('pwd', ['pwdmodule.c']) )
        # grp(3)
        exts.append( Extension('grp', ['grpmodule.c']) )
        # spwd, shadow passwords
        if (config_h_vars.get('HAVE_GETSPNAM', False) or
                config_h_vars.get('HAVE_GETSPENT', False)):
            exts.append( Extension('spwd', ['spwdmodule.c']) )
558
        else:
559
            missing.append('spwd')
560

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
561 562 563 564 565 566 567
        # 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).
568
        exts.append( Extension('mmap', ['mmapmodule.c']) )
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
569

570
        # Lance Ellinghaus's syslog module
571 572
        # syslog daemon interface
        exts.append( Extension('syslog', ['syslogmodule.c']) )
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
573 574

        #
575 576
        # Here ends the simple stuff.  From here on, modules need certain
        # libraries, are platform-specific, or present other surprises.
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
577 578 579 580 581 582
        #

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

583
        # Operations on audio samples
Tim Peters's avatar
Tim Peters committed
584
        # According to #993173, this one should actually work fine on
585 586 587
        # 64-bit platforms.
        exts.append( Extension('audioop', ['audioop.c']) )

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
588
        # readline
589
        do_readline = self.compiler.find_library_file(lib_dirs, 'readline')
590 591 592 593 594 595 596 597
        readline_termcap_library = ""
        curses_library = ""
        # Determine if readline is already linked against curses or tinfo.
        if do_readline and find_executable('ldd'):
            # Cannot use os.popen here in py3k.
            tmpfile = os.path.join(self.build_temp, 'readline_termcap_lib')
            if not os.path.exists(self.build_temp):
                os.makedirs(self.build_temp)
598 599
            ret = os.system("ldd %s > %s" % (do_readline, tmpfile))
            if ret >> 8 == 0:
600 601 602 603 604 605 606 607 608 609 610
                with open(tmpfile) as fp:
                    for ln in fp:
                        if 'curses' in ln:
                            readline_termcap_library = re.sub(
                                r'.*lib(n?cursesw?)\.so.*', r'\1', ln
                            ).rstrip()
                            break
                        # termcap interface split out from ncurses
                        if 'tinfo' in ln:
                            readline_termcap_library = 'tinfo'
                            break
611 612 613 614 615
            os.unlink(tmpfile)
        # Issue 7384: If readline is already linked against curses,
        # use the same library for the readline and curses modules.
        if 'curses' in readline_termcap_library:
            curses_library = readline_termcap_library
616
        elif self.compiler.find_library_file(lib_dirs, 'ncursesw'):
617
            curses_library = 'ncursesw'
618
        elif self.compiler.find_library_file(lib_dirs, 'ncurses'):
619
            curses_library = 'ncurses'
620
        elif self.compiler.find_library_file(lib_dirs, 'curses'):
621 622
            curses_library = 'curses'

623 624
        if platform == 'darwin':
            os_release = int(os.uname()[2].split('.')[0])
625 626 627
            dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
            if dep_target and dep_target.split('.') < ['10', '5']:
                os_release = 8
628 629 630 631 632 633
            if os_release < 9:
                # MacOSX 10.4 has a broken readline. Don't try to build
                # the readline module unless the user has installed a fixed
                # readline package
                if find_file('readline/rlconf.h', inc_dirs, []) is None:
                    do_readline = False
634
        if do_readline:
635
            if platform == 'darwin' and os_release < 9:
636 637
                # 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
638
                # for dynamic libraries on the entire path.
639
                # This way a staticly linked custom readline gets picked up
640
                # before the (possibly broken) dynamic library in /usr/lib.
641 642 643 644
                readline_extra_link_args = ('-Wl,-search_paths_first',)
            else:
                readline_extra_link_args = ()

645
            readline_libs = ['readline']
646 647 648 649
            if readline_termcap_library:
                pass # Issue 7384: Already linked against curses or tinfo.
            elif curses_library:
                readline_libs.append(curses_library)
650
            elif self.compiler.find_library_file(lib_dirs +
651 652
                                                     ['/usr/lib/termcap'],
                                                     'termcap'):
653
                readline_libs.append('termcap')
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
654
            exts.append( Extension('readline', ['readline.c'],
Marc-André Lemburg's avatar
Marc-André Lemburg committed
655
                                   library_dirs=['/usr/lib/termcap'],
656
                                   extra_link_args=readline_extra_link_args,
657
                                   libraries=readline_libs) )
658 659 660
        else:
            missing.append('readline')

661
        # crypt module.
Tim Peters's avatar
Tim Peters committed
662

663
        if self.compiler.find_library_file(lib_dirs, 'crypt'):
664
            libs = ['crypt']
665
        else:
666
            libs = []
667
        exts.append( Extension('_crypt', ['_cryptmodule.c'], libraries=libs) )
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
668

Skip Montanaro's avatar
Skip Montanaro committed
669 670 671
        # CSV files
        exts.append( Extension('_csv', ['_csv.c']) )

672 673 674
        # POSIX subprocess module helper.
        exts.append( Extension('_posixsubprocess', ['_posixsubprocess.c']) )

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
675
        # socket(2)
676
        exts.append( Extension('_socket', ['socketmodule.c'],
677
                               depends = ['socketmodule.h']) )
678
        # Detect SSL support for the socket module (via _ssl)
679 680
        search_for_ssl_incs_in = [
                              '/usr/local/ssl/include',
681 682
                              '/usr/contrib/ssl/include/'
                             ]
683 684
        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
                             search_for_ssl_incs_in
685
                             )
686 687 688 689 690
        if ssl_incs is not None:
            krb5_h = find_file('krb5.h', inc_dirs,
                               ['/usr/kerberos/include'])
            if krb5_h:
                ssl_incs += krb5_h
691
        ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
692 693 694
                                     ['/usr/local/ssl/lib',
                                      '/usr/contrib/ssl/lib/'
                                     ] )
695

696 697
        if (ssl_incs is not None and
            ssl_libs is not None):
698
            exts.append( Extension('_ssl', ['_ssl.c'],
699
                                   include_dirs = ssl_incs,
700
                                   library_dirs = ssl_libs,
701
                                   libraries = ['ssl', 'crypto'],
702
                                   depends = ['socketmodule.h']), )
703 704
        else:
            missing.append('_ssl')
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
705

706 707 708 709 710
        # 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]+)' )

711 712 713 714 715 716 717 718
        # look for the openssl version header on the compiler search path.
        opensslv_h = find_file('openssl/opensslv.h', [],
                inc_dirs + search_for_ssl_incs_in)
        if opensslv_h:
            name = os.path.join(opensslv_h[0], 'openssl/opensslv.h')
            if sys.platform == 'darwin' and is_macosx_sdk_path(name):
                name = os.path.join(macosx_sdk_root(), name[1:])
            try:
719 720 721 722 723
                with open(name, 'r') as incfile:
                    for line in incfile:
                        m = openssl_ver_re.match(line)
                        if m:
                            openssl_ver = eval(m.group(1))
724 725 726
            except IOError as msg:
                print("IOError while reading opensshv.h:", msg)
                pass
727

728
        #print('openssl_ver = 0x%08x' % openssl_ver)
729 730 731 732
        min_openssl_ver = 0x00907000
        have_any_openssl = ssl_incs is not None and ssl_libs is not None
        have_usable_openssl = (have_any_openssl and
                               openssl_ver >= min_openssl_ver)
733

734 735
        if have_any_openssl:
            if have_usable_openssl:
736 737 738
                # The _hashlib module wraps optimized implementations
                # of hash functions from the OpenSSL library.
                exts.append( Extension('_hashlib', ['_hashopenssl.c'],
Gregory P. Smith's avatar
Gregory P. Smith committed
739
                                       depends = ['hashlib.h'],
740 741 742 743 744 745 746
                                       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')
Gregory P. Smith's avatar
Gregory P. Smith committed
747

748 749
        min_sha2_openssl_ver = 0x00908000
        if COMPILED_WITH_PYDEBUG or openssl_ver < min_sha2_openssl_ver:
750
            # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash
Gregory P. Smith's avatar
Gregory P. Smith committed
751 752 753 754
            exts.append( Extension('_sha256', ['sha256module.c'],
                                   depends=['hashlib.h']) )
            exts.append( Extension('_sha512', ['sha512module.c'],
                                   depends=['hashlib.h']) )
Gregory P. Smith's avatar
Gregory P. Smith committed
755

756
        if COMPILED_WITH_PYDEBUG or not have_usable_openssl:
757
            # no openssl at all, use our own md5 and sha1
Gregory P. Smith's avatar
Gregory P. Smith committed
758 759 760 761
            exts.append( Extension('_md5', ['md5module.c'],
                                   depends=['hashlib.h']) )
            exts.append( Extension('_sha1', ['sha1module.c'],
                                   depends=['hashlib.h']) )
762

763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
        # 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 dbm/__init__.py provides an
        # implementation independent wrapper for these; dbm/dumb.py provides
        # similar functionality (but slower of course) implemented in Python.

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

778
        max_db_ver = (5, 1)
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
        min_db_ver = (3, 3)
        db_setup_debug = False   # verbose debug prints from this script?

        def allow_db_ver(db_ver):
            """Returns a boolean if the given BerkeleyDB version is acceptable.

            Args:
              db_ver: A tuple of the version to verify.
            """
            if not (min_db_ver <= db_ver <= max_db_ver):
                return False
            return True

        def gen_db_minor_ver_nums(major):
            if major == 4:
                for x in range(max_db_ver[1]+1):
                    if allow_db_ver((4, x)):
                        yield x
            elif major == 3:
                for x in (3,):
                    if allow_db_ver((3, x)):
                        yield x
            else:
                raise ValueError("unknown major BerkeleyDB version", major)

        # 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',
            # Fink defaults (http://fink.sourceforge.net/)
            '/sw/include/db4',
            '/sw/include/db3',
        ]
        # 4.x minor number specific paths
        for x in gen_db_minor_ver_nums(4):
            db_inc_paths.append('/usr/include/db4%d' % x)
            db_inc_paths.append('/usr/include/db4.%d' % x)
            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)
            db_inc_paths.append('/opt/db-4.%d/include' % x)
            # MacPorts default (http://www.macports.org/)
            db_inc_paths.append('/opt/local/include/db4%d' % x)
        # 3.x minor number specific paths
        for x in gen_db_minor_ver_nums(3):
            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)
            db_inc_paths.append('/opt/db-3.%d/include' % x)

        # 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'))
            for x in gen_db_minor_ver_nums(4):
                std_variants.append(os.path.join(dn, "db4%d"%x))
                std_variants.append(os.path.join(dn, "db4.%d"%x))
            for x in gen_db_minor_ver_nums(3):
                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
        db_inc_paths = [p for p in db_inc_paths if os.path.exists(p)]

        db_ver_inc_map = {}

855 856 857
        if sys.platform == 'darwin':
            sysroot = macosx_sdk_root()

858 859 860 861 862 863
        class db_found(Exception): pass
        try:
            # See whether there is a Sleepycat header in the standard
            # search path.
            for d in inc_dirs + db_inc_paths:
                f = os.path.join(d, "db.h")
864 865 866
                if sys.platform == 'darwin' and is_macosx_sdk_path(d):
                    f = os.path.join(sysroot, d[1:], "db.h")

867 868
                if db_setup_debug: print("db: looking for db.h in", f)
                if os.path.exists(f):
869 870
                    with open(f, 'rb') as file:
                        f = file.read()
871
                    m = re.search(br"#define\WDB_VERSION_MAJOR\W(\d+)", f)
872 873
                    if m:
                        db_major = int(m.group(1))
874
                        m = re.search(br"#define\WDB_VERSION_MINOR\W(\d+)", f)
875 876 877 878 879
                        db_minor = int(m.group(1))
                        db_ver = (db_major, db_minor)

                        # Avoid 4.6 prior to 4.6.21 due to a BerkeleyDB bug
                        if db_ver == (4, 6):
880
                            m = re.search(br"#define\WDB_VERSION_PATCH\W(\d+)", f)
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
                            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

                        if ( (db_ver not in db_ver_inc_map) and
                            allow_db_ver(db_ver) ):
                            # save the include directory with the db.h version
                            # (first occurrence only)
                            db_ver_inc_map[db_ver] = d
                            if db_setup_debug:
                                print("db.h: found", db_ver, "in", d)
                        else:
                            # we already found a header for this library version
                            if db_setup_debug: print("db.h: ignoring", d)
                    else:
                        # ignore this header, it didn't contain a version number
                        if db_setup_debug:
                            print("db.h: no version number version in", d)

            db_found_vers = list(db_ver_inc_map.keys())
            db_found_vers.sort()

            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 = [
                    db_incdir.replace("include", 'lib64'),
                    db_incdir.replace("include", 'lib'),
                ]
914 915 916 917 918 919 920 921 922 923 924 925 926 927

                if sys.platform != 'darwin':
                    db_dirs_to_check = list(filter(os.path.isdir, db_dirs_to_check))

                else:
                    # Same as other branch, but takes OSX SDK into account
                    tmp = []
                    for dn in db_dirs_to_check:
                        if is_macosx_sdk_path(dn):
                            if os.path.isdir(os.path.join(sysroot, dn[1:])):
                                tmp.append(dn)
                        else:
                            if os.path.isdir(dn):
                                tmp.append(dn)
928
                    db_dirs_to_check = tmp
929 930

                    db_dirs_to_check = tmp
931

932
                # Look for a version specific db-X.Y before an ambiguous dbX
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958
                # 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?
                for dblib in (('db-%d.%d' % db_ver),
                              ('db%d%d' % db_ver),
                              ('db%d' % db_ver[0])):
                    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:
                        if db_setup_debug: print("db lib: ", dblib, "not found")

        except db_found:
            if db_setup_debug:
                print("bsddb using BerkeleyDB lib:", db_ver, dblib)
                print("bsddb lib dir:", dblib_dir, " inc dir:", db_incdir)
            db_incs = [db_incdir]
            dblibs = [dblib]
        else:
            if db_setup_debug: print("db: no appropriate library found")
            db_incs = None
            dblibs = []
            dblib_dir = None

959
        # The sqlite interface
960
        sqlite_setup_debug = False   # verbose debug prints from this script?
961 962 963 964 965 966 967 968 969 970 971 972 973 974

        # 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])
975 976 977 978

        # 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.
979 980 981
        if sys.platform == 'darwin':
            sysroot = macosx_sdk_root()

982
        for d in inc_dirs + sqlite_inc_paths:
983
            f = os.path.join(d, "sqlite3.h")
984 985 986 987

            if sys.platform == 'darwin' and is_macosx_sdk_path(d):
                f = os.path.join(sysroot, d[1:], "sqlite3.h")

988
            if os.path.exists(f):
989
                if sqlite_setup_debug: print("sqlite: found %s"%f)
990 991
                with open(f) as file:
                    incf = file.read()
992 993 994 995 996 997 998 999
                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!
1000
                        if sqlite_setup_debug:
1001
                            print("%s/sqlite3.h: version %s"%(d, sqlite_version))
1002 1003 1004 1005
                        sqlite_incdir = d
                        break
                    else:
                        if sqlite_setup_debug:
1006 1007
                            print("%s: version %d is too old, need >= %s"%(d,
                                        sqlite_version, MIN_SQLITE_VERSION))
1008
                elif sqlite_setup_debug:
1009
                    print("sqlite: %s had no SQLITE_VERSION"%(f,))
1010 1011 1012 1013 1014 1015 1016 1017

        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'),
            ]
1018
            sqlite_libfile = self.compiler.find_library_file(
1019
                                sqlite_dirs_to_check + lib_dirs, 'sqlite3')
Benjamin Peterson's avatar
Benjamin Peterson committed
1020 1021
            if sqlite_libfile:
                sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))]
1022 1023

        if sqlite_incdir and sqlite_libdir:
1024
            sqlite_srcs = ['_sqlite/cache.c',
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
                '_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\\"'))

1040 1041 1042 1043
            # Enable support for loadable extensions in the sqlite3 module
            # if --enable-loadable-sqlite-extensions configure option is used.
            if '--enable-loadable-sqlite-extensions' not in sysconfig.get_config_var("CONFIG_ARGS"):
                sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1"))
1044 1045 1046 1047

            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
1048 1049
                # for dynamic libraries on the entire path.
                # This way a statically linked custom sqlite gets picked up
1050 1051 1052 1053
                # before the dynamic library in /usr/lib.
                sqlite_extra_link_args = ('-Wl,-search_paths_first',)
            else:
                sqlite_extra_link_args = ()
1054

1055 1056 1057 1058 1059 1060
            include_dirs = ["Modules/_sqlite"]
            # Only include the directory where sqlite was found if it does
            # not already exist in set include directories, otherwise you
            # can end up with a bad search path order.
            if sqlite_incdir not in self.compiler.include_dirs:
                include_dirs.append(sqlite_incdir)
1061 1062
            exts.append(Extension('_sqlite3', sqlite_srcs,
                                  define_macros=sqlite_defines,
1063
                                  include_dirs=include_dirs,
1064 1065
                                  library_dirs=sqlite_libdir,
                                  runtime_library_dirs=sqlite_libdir,
1066
                                  extra_link_args=sqlite_extra_link_args,
1067
                                  libraries=["sqlite3",]))
1068 1069
        else:
            missing.append('_sqlite3')
1070

1071
        dbm_order = ['gdbm']
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1072
        # The standard Unix dbm module:
1073
        if platform not in ['cygwin']:
1074 1075
            config_args = [arg.strip("'")
                           for arg in sysconfig.get_config_var("CONFIG_ARGS").split()]
1076
            dbm_args = [arg for arg in config_args
1077 1078
                        if arg.startswith('--with-dbmliborder=')]
            if dbm_args:
1079
                dbm_order = [arg.split('=')[-1] for arg in dbm_args][-1].split(":")
1080
            else:
1081
                dbm_order = "ndbm:gdbm:bdb".split(":")
1082 1083 1084 1085 1086
            dbmext = None
            for cand in dbm_order:
                if cand == "ndbm":
                    if find_file("ndbm.h", inc_dirs, []) is not None:
                        # Some systems have -lndbm, others don't
1087
                        if self.compiler.find_library_file(lib_dirs,
1088
                                                               'ndbm'):
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
                            ndbm_libs = ['ndbm']
                        else:
                            ndbm_libs = []
                        print("building dbm using ndbm")
                        dbmext = Extension('_dbm', ['_dbmmodule.c'],
                                           define_macros=[
                                               ('HAVE_NDBM_H',None),
                                               ],
                                           libraries=ndbm_libs)
                        break

                elif cand == "gdbm":
1101
                    if self.compiler.find_library_file(lib_dirs, 'gdbm'):
1102
                        gdbm_libs = ['gdbm']
1103
                        if self.compiler.find_library_file(lib_dirs,
1104
                                                               'gdbm_compat'):
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
                            gdbm_libs.append('gdbm_compat')
                        if find_file("gdbm/ndbm.h", inc_dirs, []) is not None:
                            print("building dbm using gdbm")
                            dbmext = Extension(
                                '_dbm', ['_dbmmodule.c'],
                                define_macros=[
                                    ('HAVE_GDBM_NDBM_H', None),
                                    ],
                                libraries = gdbm_libs)
                            break
                        if find_file("gdbm-ndbm.h", inc_dirs, []) is not None:
                            print("building dbm using gdbm")
                            dbmext = Extension(
                                '_dbm', ['_dbmmodule.c'],
                                define_macros=[
                                    ('HAVE_GDBM_DASH_NDBM_H', None),
                                    ],
                                libraries = gdbm_libs)
                            break
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
                elif cand == "bdb":
                    if db_incs is not None:
                        print("building dbm using bdb")
                        dbmext = Extension('_dbm', ['_dbmmodule.c'],
                                           library_dirs=dblib_dir,
                                           runtime_library_dirs=dblib_dir,
                                           include_dirs=db_incs,
                                           define_macros=[
                                               ('HAVE_BERKDB_H', None),
                                               ('DB_DBM_HSEARCH', None),
                                               ],
                                           libraries=dblibs)
1136 1137 1138
                        break
            if dbmext is not None:
                exts.append(dbmext)
1139
            else:
1140
                missing.append('_dbm')
1141

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1142
        # Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:
1143
        if ('gdbm' in dbm_order and
1144
            self.compiler.find_library_file(lib_dirs, 'gdbm')):
1145
            exts.append( Extension('_gdbm', ['_gdbmmodule.c'],
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1146
                                   libraries = ['gdbm'] ) )
1147
        else:
1148
            missing.append('_gdbm')
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1149 1150

        # Unix-only modules
1151
        if platform != 'win32':
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1152 1153 1154
            # Steen Lumholt's termios module
            exts.append( Extension('termios', ['termios.c']) )
            # Jeremy Hylton's rlimit interface
1155
            exts.append( Extension('resource', ['resource.c']) )
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1156

1157
            # Sun yellow pages. Some systems have the functions in libc.
1158 1159
            if (platform not in ['cygwin', 'qnx6'] and
                find_file('rpcsvc/yp_prot.h', inc_dirs, []) is not None):
1160
                if (self.compiler.find_library_file(lib_dirs, 'nsl')):
1161 1162 1163 1164 1165
                    libs = ['nsl']
                else:
                    libs = []
                exts.append( Extension('nis', ['nismodule.c'],
                                       libraries = libs) )
1166 1167 1168 1169
            else:
                missing.append('nis')
        else:
            missing.extend(['nis', 'resource', 'termios'])
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1170

1171 1172
        # Curses support, requiring the System V version of curses, often
        # provided by the ncurses library.
1173
        curses_defines = []
1174 1175
        curses_includes = []
        panel_library = 'panel'
1176 1177
        if curses_library == 'ncursesw':
            curses_defines.append(('HAVE_NCURSESW', '1'))
1178 1179 1180 1181
            curses_includes.append('/usr/include/ncursesw')
            # Bug 1464056: If _curses.so links with ncursesw,
            # _curses_panel.so must link with panelw.
            panel_library = 'panelw'
1182

1183 1184
        if curses_library.startswith('ncurses'):
            curses_libs = [curses_library]
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1185
            exts.append( Extension('_curses', ['_cursesmodule.c'],
1186
                                   include_dirs=curses_includes,
1187
                                   define_macros=curses_defines,
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1188
                                   libraries = curses_libs) )
1189
        elif curses_library == 'curses' and platform != 'darwin':
1190 1191
                # OSX has an old Berkeley curses, not good enough for
                # the _curses module.
1192
            if (self.compiler.find_library_file(lib_dirs, 'terminfo')):
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1193
                curses_libs = ['curses', 'terminfo']
1194
            elif (self.compiler.find_library_file(lib_dirs, 'termcap')):
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1195
                curses_libs = ['curses', 'termcap']
1196 1197
            else:
                curses_libs = ['curses']
1198

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1199
            exts.append( Extension('_curses', ['_cursesmodule.c'],
1200
                                   define_macros=curses_defines,
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1201
                                   libraries = curses_libs) )
1202 1203
        else:
            missing.append('_curses')
1204

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1205
        # If the curses module is enabled, check for the panel module
1206
        if (module_enabled(exts, '_curses') and
1207
            self.compiler.find_library_file(lib_dirs, panel_library)):
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1208
            exts.append( Extension('_curses_panel', ['_curses_panel.c'],
1209
                                   include_dirs=curses_includes,
1210
                                   libraries = [panel_library] + curses_libs) )
1211 1212
        else:
            missing.append('_curses_panel')
1213

1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
        # 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/
1226
        zlib_inc = find_file('zlib.h', [], inc_dirs)
1227
        have_zlib = False
1228 1229 1230
        if zlib_inc is not None:
            zlib_h = zlib_inc[0] + '/zlib.h'
            version = '"0.0.0"'
1231
            version_req = '"1.1.3"'
1232 1233 1234 1235 1236 1237 1238 1239
            with open(zlib_h) as fp:
                while 1:
                    line = fp.readline()
                    if not line:
                        break
                    if line.startswith('#define ZLIB_VERSION'):
                        version = line.split()[2]
                        break
1240
            if version >= version_req:
1241
                if (self.compiler.find_library_file(lib_dirs, 'z')):
1242 1243 1244 1245
                    if sys.platform == "darwin":
                        zlib_extra_link_args = ('-Wl,-search_paths_first',)
                    else:
                        zlib_extra_link_args = ()
1246
                    exts.append( Extension('zlib', ['zlibmodule.c'],
1247 1248
                                           libraries = ['z'],
                                           extra_link_args = zlib_extra_link_args))
1249
                    have_zlib = True
1250 1251 1252 1253 1254 1255
                else:
                    missing.append('zlib')
            else:
                missing.append('zlib')
        else:
            missing.append('zlib')
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1256

1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
        # 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) )

1272
        # Gustavo Niemeyer's bz2 module.
1273
        if (self.compiler.find_library_file(lib_dirs, 'bz2')):
1274 1275 1276 1277
            if sys.platform == "darwin":
                bz2_extra_link_args = ('-Wl,-search_paths_first',)
            else:
                bz2_extra_link_args = ()
1278
            exts.append( Extension('_bz2', ['_bz2module.c'],
1279 1280
                                   libraries = ['bz2'],
                                   extra_link_args = bz2_extra_link_args) )
1281
        else:
1282
            missing.append('_bz2')
1283

1284 1285 1286 1287 1288 1289 1290
        # LZMA compression support.
        if self.compiler.find_library_file(lib_dirs, 'lzma'):
            exts.append( Extension('_lzma', ['_lzmamodule.c'],
                                   libraries = ['lzma']) )
        else:
            missing.append('_lzma')

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1291 1292
        # Interface to the Expat XML parser
        #
1293 1294 1295 1296 1297
        # 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.  The Expat source is included in Modules/expat/.  Usage
        # of a system shared libexpat.so is possible with --with-system-expat
Benjamin Peterson's avatar
typo  
Benjamin Peterson committed
1298
        # configure option.
1299 1300 1301
        #
        # More information on Expat can be found at www.libexpat.org.
        #
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
        if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"):
            expat_inc = []
            define_macros = []
            expat_lib = ['expat']
            expat_sources = []
        else:
            expat_inc = [os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')]
            define_macros = [
                ('HAVE_EXPAT_CONFIG_H', '1'),
            ]
            expat_lib = []
            expat_sources = ['expat/xmlparse.c',
                             'expat/xmlrole.c',
                             'expat/xmltok.c']
1316

1317 1318
        exts.append(Extension('pyexpat',
                              define_macros = define_macros,
1319 1320 1321
                              include_dirs = expat_inc,
                              libraries = expat_lib,
                              sources = ['pyexpat.c'] + expat_sources
1322
                              ))
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1323

1324 1325 1326
        # Fredrik Lundh's cElementTree module.  Note that this also
        # uses expat (via the CAPI hook in pyexpat).

1327
        if os.path.isfile(os.path.join(srcdir, 'Modules', '_elementtree.c')):
1328 1329 1330
            define_macros.append(('USE_PYEXPAT_CAPI', None))
            exts.append(Extension('_elementtree',
                                  define_macros = define_macros,
1331 1332
                                  include_dirs = expat_inc,
                                  libraries = expat_lib,
1333 1334
                                  sources = ['_elementtree.c'],
                                  ))
1335 1336
        else:
            missing.append('_elementtree')
1337

1338
        # Hye-Shik Chang's CJKCodecs modules.
1339 1340 1341 1342 1343
        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]))
1344

1345 1346 1347
        # Stefan Krah's _decimal module
        exts.append(self._decimal_ext())

1348
        # Thomas Heller's _ctypes module
1349
        self.detect_ctypes(inc_dirs, lib_dirs)
1350

1351 1352 1353 1354 1355 1356
        # Richard Oudkerk's multiprocessing module
        if platform == 'win32':             # Windows
            macros = dict()
            libraries = ['ws2_32']

        elif platform == 'darwin':          # Mac OSX
1357
            macros = dict()
1358 1359 1360
            libraries = []

        elif platform == 'cygwin':          # Cygwin
1361
            macros = dict()
1362
            libraries = []
Benjamin Peterson's avatar
Benjamin Peterson committed
1363

1364
        elif platform in ('freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'freebsd8'):
Benjamin Peterson's avatar
Benjamin Peterson committed
1365 1366
            # FreeBSD's P1003.1b semaphore support is very experimental
            # and has many known problems. (as of June 2008)
1367
            macros = dict()
Benjamin Peterson's avatar
Benjamin Peterson committed
1368 1369
            libraries = []

1370
        elif platform.startswith('openbsd'):
1371
            macros = dict()
1372 1373
            libraries = []

1374
        elif platform.startswith('netbsd'):
1375
            macros = dict()
1376 1377
            libraries = []

1378
        else:                                   # Linux and other unices
1379
            macros = dict()
1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390
            libraries = ['rt']

        if platform == 'win32':
            multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c',
                                     '_multiprocessing/semaphore.c',
                                     '_multiprocessing/win32_functions.c'
                                   ]

        else:
            multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c',
                                   ]
1391 1392
            if (sysconfig.get_config_var('HAVE_SEM_OPEN') and not
                sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED')):
1393 1394
                multiprocessing_srcs.append('_multiprocessing/semaphore.c')

Jesse Noller's avatar
Jesse Noller committed
1395 1396 1397 1398 1399 1400
        if sysconfig.get_config_var('WITH_THREAD'):
            exts.append ( Extension('_multiprocessing', multiprocessing_srcs,
                                    define_macros=list(macros.items()),
                                    include_dirs=["Modules/_multiprocessing"]))
        else:
            missing.append('_multiprocessing')
1401
        # End multiprocessing
1402

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1403
        # Platform-specific libraries
1404
        if platform.startswith(('linux', 'freebsd', 'gnukfreebsd')):
1405
            exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
1406 1407
        else:
            missing.append('ossaudiodev')
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1408

1409 1410 1411 1412 1413
        if sys.platform == 'darwin':
            exts.append(
                       Extension('_gestalt', ['_gestalt.c'],
                       extra_link_args=['-framework', 'Carbon'])
                       )
1414 1415 1416 1417 1418 1419
            exts.append(
                       Extension('_scproxy', ['_scproxy.c'],
                       extra_link_args=[
                           '-framework', 'SystemConfiguration',
                           '-framework', 'CoreFoundation',
                        ]))
1420

1421 1422 1423 1424
        self.extensions.extend(exts)

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

1426 1427 1428 1429 1430
        if '_tkinter' not in [e.name for e in self.extensions]:
            missing.append('_tkinter')

        return missing

1431 1432 1433 1434 1435
    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
1436
            '/Library/Frameworks',
1437
            '/System/Library/Frameworks/',
1438 1439 1440
            join(os.getenv('HOME'), '/Library/Frameworks')
        ]

1441 1442
        sysroot = macosx_sdk_root()

1443
        # Find the directory that contains the Tcl.framework and Tk.framework
1444 1445 1446
        # bundles.
        # XXX distutils should support -F!
        for F in framework_dirs:
Tim Peters's avatar
Tim Peters committed
1447
            # both Tcl.framework and Tk.framework should be present
1448 1449


1450
            for fw in 'Tcl', 'Tk':
1451 1452 1453 1454 1455 1456
                if is_macosx_sdk_path(F):
                    if not exists(join(sysroot, F[1:], fw + '.framework')):
                        break
                else:
                    if not exists(join(F, fw + '.framework')):
                        break
1457 1458 1459 1460 1461 1462 1463 1464
            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
1465

1466 1467
        # 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
1468
        # the -F option to gcc, which specifies a framework lookup path.
1469 1470
        #
        include_dirs = [
Tim Peters's avatar
Tim Peters committed
1471
            join(F, fw + '.framework', H)
1472 1473
            for fw in ('Tcl', 'Tk')
            for H in ('Headers', 'Versions/Current/PrivateHeaders')
1474 1475
        ]

Tim Peters's avatar
Tim Peters committed
1476
        # For 8.4a2, the X11 headers are not included. Rather than include a
1477 1478 1479 1480 1481
        # 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']

1482 1483 1484 1485 1486
        # All existing framework builds of Tcl/Tk don't support 64-bit
        # architectures.
        cflags = sysconfig.get_config_vars('CFLAGS')[0]
        archs = re.findall('-arch\s+(\w+)', cflags)

1487 1488 1489 1490 1491 1492
        tmpfile = os.path.join(self.build_temp, 'tk.arch')
        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)

        # Note: cannot use os.popen or subprocess here, that
        # requires extensions that are not available here.
1493 1494 1495 1496
        if is_macosx_sdk_path(F):
            os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(os.path.join(sysroot, F[1:]), tmpfile))
        else:
            os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(F, tmpfile))
1497 1498 1499 1500 1501 1502 1503

        with open(tmpfile) as fp:
            detected_archs = []
            for ln in fp:
                a = ln.split()[-1]
                if a in archs:
                    detected_archs.append(ln.split()[-1])
1504 1505 1506 1507 1508
        os.unlink(tmpfile)

        for a in detected_archs:
            frameworks.append('-arch')
            frameworks.append(a)
1509

1510 1511 1512 1513
        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
                        define_macros=[('WITH_APPINIT', 1)],
                        include_dirs = include_dirs,
                        libraries = [],
1514
                        extra_compile_args = frameworks[2:],
1515 1516 1517 1518 1519
                        extra_link_args = frameworks,
                        )
        self.extensions.append(ext)
        return 1

Tim Peters's avatar
Tim Peters committed
1520

1521
    def detect_tkinter(self, inc_dirs, lib_dirs):
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1522
        # The _tkinter module.
1523

1524 1525 1526 1527
        # 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()
1528 1529
        if (platform == 'darwin' and
            self.detect_tkinter_darwin(inc_dirs, lib_dirs)):
Tim Peters's avatar
Tim Peters committed
1530
            return
1531

1532
        # Assume we haven't found any of the libraries or include files
1533 1534
        # The versions with dots are used on Unix, and the versions without
        # dots on Windows, for detection by cygwin.
1535
        tcllib = tklib = tcl_includes = tk_includes = None
1536 1537
        for version in ['8.6', '86', '8.5', '85', '8.4', '84', '8.3', '83',
                        '8.2', '82', '8.1', '81', '8.0', '80']:
1538
            tklib = self.compiler.find_library_file(lib_dirs,
1539
                                                        'tk' + version)
1540
            tcllib = self.compiler.find_library_file(lib_dirs,
1541
                                                         'tcl' + version)
1542
            if tklib and tcllib:
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1543 1544
                # Exit the loop when we've found the Tcl/Tk libraries
                break
1545

1546
        # Now check for the header files
1547
        if tklib and tcllib:
1548
            # Check for the include files on Debian and {Free,Open}BSD, where
1549
            # they're put in /usr/include/{tcl,tk}X.Y
1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562
            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)
1563

1564
        if (tcllib is None or tklib is None or
1565
            tcl_includes is None or tk_includes is None):
1566
            self.announce("INFO: Can't locate Tcl/Tk libs and/or headers", 2)
1567
            return
1568

1569 1570 1571 1572 1573 1574
        # 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)
1575

1576
        # Check for various platform-specific directories
1577
        if platform == 'sunos5':
1578 1579 1580 1581
            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')
1582
            added_lib_dirs.append('/usr/X11R6/lib64')
1583 1584 1585 1586 1587
            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:
1588
            # Assume default location for X11
1589 1590 1591
            include_dirs.append('/usr/X11/include')
            added_lib_dirs.append('/usr/X11/lib')

1592 1593 1594 1595 1596 1597
        # 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

1598
        # Check for BLT extension
1599
        if self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1600
                                               'BLT8.0'):
1601 1602
            defs.append( ('WITH_BLT', 1) )
            libs.append('BLT8.0')
1603
        elif self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1604
                                                'BLT'):
1605 1606
            defs.append( ('WITH_BLT', 1) )
            libs.append('BLT')
1607 1608

        # Add the Tcl/Tk libraries
1609 1610
        libs.append('tk'+ version)
        libs.append('tcl'+ version)
1611

1612
        if platform in ['aix3', 'aix4']:
1613 1614
            libs.append('ld')

1615 1616 1617
        # Finally, link with the X11 libraries (not appropriate on cygwin)
        if platform != "cygwin":
            libs.append('X11')
1618 1619 1620 1621 1622 1623 1624 1625

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

1627 1628 1629
##         # Uncomment these lines if you want to play with xxmodule.c
##         ext = Extension('xx', ['xxmodule.c'])
##         self.extensions.append(ext)
Antoine Pitrou's avatar
Antoine Pitrou committed
1630 1631 1632 1633
        if 'd' not in sys.abiflags:
            ext = Extension('xxlimited', ['xxlimited.c'],
                            define_macros=[('Py_LIMITED_API', 1)])
            self.extensions.append(ext)
1634

1635
        # XXX handle these, but how to detect?
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1636
        # *** Uncomment and edit for PIL (TkImaging) extension only:
1637
        #       -DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1638
        # *** Uncomment and edit for TOGL extension only:
1639
        #       -DWITH_TOGL togl.c \
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1640
        # *** Uncomment these for TOGL extension only:
1641
        #       -lGL -lGLU -lXext -lXmu \
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
1642

1643 1644 1645
    def configure_ctypes_darwin(self, ext):
        # Darwin (OS X) uses preconfigured files, in
        # the Modules/_ctypes/libffi_osx directory.
1646
        srcdir = sysconfig.get_config_var('srcdir')
1647 1648 1649 1650
        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',
1651
                             'x86/darwin64.S',
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
                             '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.
1662
        self.compiler.src_extensions.append('.S')
1663 1664 1665 1666 1667 1668 1669

        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

1670 1671
    def configure_ctypes(self, ext):
        if not self.use_system_libffi:
1672 1673 1674
            if sys.platform == 'darwin':
                return self.configure_ctypes_darwin(ext)

1675
            srcdir = sysconfig.get_config_var('srcdir')
1676 1677 1678 1679 1680
            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')

1681 1682 1683
            from distutils.dep_util import newer_group

            config_sources = [os.path.join(ffi_srcdir, fname)
1684 1685
                              for fname in os.listdir(ffi_srcdir)
                              if os.path.isfile(os.path.join(ffi_srcdir, fname))]
1686 1687
            if self.force or newer_group(config_sources,
                                         ffi_configfile):
1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698
                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):
1699
                    print("Failed to configure _ctypes module")
1700 1701 1702
                    return False

            fficonfig = {}
1703 1704
            with open(ffi_configfile) as f:
                exec(f.read(), globals(), fficonfig)
1705 1706

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

            include_dirs = [os.path.join(ffi_builddir, 'include'),
1710 1711
                            ffi_builddir,
                            os.path.join(ffi_srcdir, 'src')]
1712 1713
            extra_compile_args = fficonfig['ffi_cflags'].split()

1714 1715
            ext.sources.extend(os.path.join(ffi_srcdir, f) for f in
                               fficonfig['ffi_sources'])
1716 1717 1718 1719 1720 1721 1722 1723
            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 = []
1724
        extra_link_args = []
1725 1726 1727 1728
        sources = ['_ctypes/_ctypes.c',
                   '_ctypes/callbacks.c',
                   '_ctypes/callproc.c',
                   '_ctypes/stgdict.c',
1729
                   '_ctypes/cfield.c']
1730 1731 1732
        depends = ['_ctypes/ctypes.h']

        if sys.platform == 'darwin':
1733
            sources.append('_ctypes/malloc_closure.c')
1734
            sources.append('_ctypes/darwin/dlfcn_simple.c')
1735
            extra_compile_args.append('-DMACOSX')
1736 1737 1738 1739
            include_dirs.append('_ctypes/darwin')
# XXX Is this still needed?
##            extra_link_args.extend(['-read_only_relocs', 'warning'])

1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750
        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')

1751
        elif sys.platform.startswith('hp-ux'):
1752 1753
            extra_link_args.append('-fPIC')

1754 1755 1756
        ext = Extension('_ctypes',
                        include_dirs=include_dirs,
                        extra_compile_args=extra_compile_args,
1757
                        extra_link_args=extra_link_args,
1758
                        libraries=[],
1759 1760 1761 1762 1763 1764
                        sources=sources,
                        depends=depends)
        ext_test = Extension('_ctypes_test',
                             sources=['_ctypes/_ctypes_test.c'])
        self.extensions.extend([ext, ext_test])

1765 1766 1767
        if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
            return

1768 1769 1770 1771 1772
        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')

1773
        ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
1774
        if not ffi_inc or ffi_inc[0] == '':
1775
            ffi_inc = find_file('ffi.h', [], inc_dirs)
1776 1777
        if ffi_inc is not None:
            ffi_h = ffi_inc[0] + '/ffi.h'
1778 1779 1780 1781 1782 1783 1784 1785
            with open(ffi_h) as fp:
                while 1:
                    line = fp.readline()
                    if not line:
                        ffi_inc = None
                        break
                    if line.startswith('#define LIBFFI_H'):
                        break
1786 1787 1788
        ffi_lib = None
        if ffi_inc is not None:
            for lib_name in ('ffi_convenience', 'ffi_pic', 'ffi'):
1789
                if (self.compiler.find_library_file(lib_dirs, lib_name)):
1790 1791 1792 1793 1794 1795 1796 1797
                    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

1798
    def _decimal_ext(self):
1799 1800 1801 1802 1803 1804 1805 1806
        extra_compile_args = []
        undef_macros=['NDEBUG']
        if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"):
            include_dirs = []
            libraries = ['mpdec']
            sources = ['_decimal/_decimal.c']
            depends = ['_decimal/docstrings.h']
        else:
1807 1808 1809 1810 1811
            srcdir = sysconfig.get_config_var('srcdir')
            include_dirs = [os.path.abspath(os.path.join(srcdir,
                                                         'Modules',
                                                         '_decimal',
                                                         'libmpdec'))]
1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849
            libraries = []
            sources = [
              '_decimal/_decimal.c',
              '_decimal/libmpdec/basearith.c',
              '_decimal/libmpdec/constants.c',
              '_decimal/libmpdec/context.c',
              '_decimal/libmpdec/convolute.c',
              '_decimal/libmpdec/crt.c',
              '_decimal/libmpdec/difradix2.c',
              '_decimal/libmpdec/fnt.c',
              '_decimal/libmpdec/fourstep.c',
              '_decimal/libmpdec/io.c',
              '_decimal/libmpdec/memory.c',
              '_decimal/libmpdec/mpdecimal.c',
              '_decimal/libmpdec/numbertheory.c',
              '_decimal/libmpdec/sixstep.c',
              '_decimal/libmpdec/transpose.c',
              ]
            depends = [
              '_decimal/docstrings.h',
              '_decimal/libmpdec/basearith.h',
              '_decimal/libmpdec/bits.h',
              '_decimal/libmpdec/constants.h',
              '_decimal/libmpdec/convolute.h',
              '_decimal/libmpdec/crt.h',
              '_decimal/libmpdec/difradix2.h',
              '_decimal/libmpdec/fnt.h',
              '_decimal/libmpdec/fourstep.h',
              '_decimal/libmpdec/io.h',
              '_decimal/libmpdec/memory.h',
              '_decimal/libmpdec/mpdecimal.h',
              '_decimal/libmpdec/numbertheory.h',
              '_decimal/libmpdec/sixstep.h',
              '_decimal/libmpdec/transpose.h',
              '_decimal/libmpdec/typearith.h',
              '_decimal/libmpdec/umodarith.h',
              ]

1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911
        config = {
          'x64':     [('CONFIG_64','1'), ('ASM','1')],
          'uint128': [('CONFIG_64','1'), ('ANSI','1'), ('HAVE_UINT128_T','1')],
          'ansi64':  [('CONFIG_64','1'), ('ANSI','1')],
          'ppro':    [('CONFIG_32','1'), ('PPRO','1'), ('ASM','1')],
          'ansi32':  [('CONFIG_32','1'), ('ANSI','1')],
          'ansi-legacy': [('CONFIG_32','1'), ('ANSI','1'),
                          ('LEGACY_COMPILER','1')],
          'universal':   [('UNIVERSAL','1')]
        }

        platform = self.get_platform()
        cc = sysconfig.get_config_var('CC')
        sizeof_size_t = sysconfig.get_config_var('SIZEOF_SIZE_T')
        machine = os.environ.get('PYTHON_DECIMAL_WITH_MACHINE')

        if machine:
            # Override automatic configuration to facilitate testing.
            define_macros = config[machine]
        elif platform == 'darwin':
            # Universal here means: build with the same options Python
            # was built with.
            define_macros = config['universal']
        elif sizeof_size_t == 8:
            if sysconfig.get_config_var('HAVE_GCC_ASM_FOR_X64'):
                define_macros = config['x64']
            elif sysconfig.get_config_var('HAVE_GCC_UINT128_T'):
                define_macros = config['uint128']
            else:
                define_macros = config['ansi64']
        elif sizeof_size_t == 4:
            ppro = sysconfig.get_config_var('HAVE_GCC_ASM_FOR_X87')
            if ppro and ('gcc' in cc or 'clang' in cc) and \
               not 'sunos' in platform:
                # solaris: problems with register allocation.
                # icc >= 11.0 works as well.
                define_macros = config['ppro']
            else:
                define_macros = config['ansi32']
        else:
            raise DistutilsError("_decimal: unsupported architecture")

        # Workarounds for toolchain bugs:
        if sysconfig.get_config_var('HAVE_IPA_PURE_CONST_BUG'):
            # Some versions of gcc miscompile inline asm:
            # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46491
            # http://gcc.gnu.org/ml/gcc/2010-11/msg00366.html
            extra_compile_args.append('-fno-ipa-pure-const')
        if sysconfig.get_config_var('HAVE_GLIBC_MEMMOVE_BUG'):
            # _FORTIFY_SOURCE wrappers for memmove and bcopy are incorrect:
            # http://sourceware.org/ml/libc-alpha/2010-12/msg00009.html
            undef_macros.append('_FORTIFY_SOURCE')

        # Faster version without thread local contexts:
        if not sysconfig.get_config_var('WITH_THREAD'):
            define_macros.append(('WITHOUT_THREADS', 1))

        # Uncomment for extra functionality:
        #define_macros.append(('EXTRA_FUNCTIONALITY', 1))
        ext = Extension (
            '_decimal',
            include_dirs=include_dirs,
1912
            libraries=libraries,
1913 1914 1915 1916 1917 1918 1919
            define_macros=define_macros,
            undef_macros=undef_macros,
            extra_compile_args=extra_compile_args,
            sources=sources,
            depends=depends
        )
        return ext
1920

1921 1922 1923 1924 1925 1926 1927
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
1928

1929 1930 1931 1932 1933 1934 1935
    # Customize subcommands to not install an egg-info file for Python
    sub_commands = [('install_lib', install.has_lib),
                    ('install_headers', install.has_headers),
                    ('install_scripts', install.has_scripts),
                    ('install_data', install.has_data)]


1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
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)
1946 1947
        self.set_file_modes(outfiles, 0o644, 0o755)
        self.set_dir_modes(self.install_dir, 0o755)
1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962
        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
1963 1964 1965 1966 1967
        for dirpath, dirnames, fnames in os.walk(dirname):
            if os.path.islink(dirpath):
                continue
            log.info("changing mode of %s to %o", dirpath, mode)
            if not self.dry_run: os.chmod(dirpath, mode)
1968 1969 1970 1971

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

1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990
class PyBuildScripts(build_scripts):
    def copy_scripts(self):
        outfiles, updated_files = build_scripts.copy_scripts(self)
        fullversion = '-{0[0]}.{0[1]}'.format(sys.version_info)
        minoronly = '.{0[1]}'.format(sys.version_info)
        newoutfiles = []
        newupdated_files = []
        for filename in outfiles:
            if filename.endswith('2to3'):
                newfilename = filename + fullversion
            else:
                newfilename = filename + minoronly
            log.info('renaming {} to {}'.format(filename, newfilename))
            os.rename(filename, newfilename)
            newoutfiles.append(newfilename)
            if filename in updated_files:
                newupdated_files.append(newfilename)
        return newoutfiles, newupdated_files

Guido van Rossum's avatar
Guido van Rossum committed
1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
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 :: 6 - Mature
License :: OSI Approved :: Python Software Foundation License
Natural Language :: English
Programming Language :: C
Programming Language :: Python
Topic :: Software Development
"""

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
2019
def main():
2020 2021 2022
    # turn off warnings when deprecated modules are imported
    import warnings
    warnings.filterwarnings("ignore",category=DeprecationWarning)
Guido van Rossum's avatar
Guido van Rossum committed
2023 2024 2025 2026 2027 2028 2029 2030 2031
    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",
2032
          classifiers = [x for x in CLASSIFIERS.split("\n") if x],
Guido van Rossum's avatar
Guido van Rossum committed
2033 2034 2035
          platforms = ["Many"],

          # Build info
2036 2037 2038 2039
          cmdclass = {'build_ext': PyBuildExt,
                      'build_scripts': PyBuildScripts,
                      'install': PyBuildInstall,
                      'install_lib': PyBuildInstallLib},
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
2040 2041
          # The struct module is defined here, because build_ext won't be
          # called unless there's at least one extension module defined.
2042
          ext_modules=[Extension('_struct', ['_struct.c'])],
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
2043

2044 2045 2046
          # If you change the scripts installed here, you also need to
          # check the PyBuildScripts command above, and change the links
          # created by the bininstall target in Makefile.pre.in
2047
          scripts = ["Tools/scripts/pydoc3", "Tools/scripts/idle3",
2048
                     "Tools/scripts/2to3", "Tools/scripts/pysetup3"]
Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
2049
        )
2050

Andrew M. Kuchling's avatar
Andrew M. Kuchling committed
2051 2052 2053
# --install-platlib
if __name__ == '__main__':
    main()