1# Autodetecting setup.py script for building the Python extensions
2#
3
4__version__ = "$Revision$"
5
6import sys, os, imp, re, optparse
7from glob import glob
8from platform import machine as platform_machine
9import sysconfig
10
11from distutils import log
12from distutils import text_file
13from distutils.errors import *
14from distutils.core import Extension, setup
15from distutils.command.build_ext import build_ext
16from distutils.command.install import install
17from distutils.command.install_lib import install_lib
18from distutils.command.build_scripts import build_scripts
19from distutils.spawn import find_executable
20
21cross_compiling = "_PYTHON_HOST_PLATFORM" in os.environ
22
23def get_platform():
24    # cross build
25    if "_PYTHON_HOST_PLATFORM" in os.environ:
26        return os.environ["_PYTHON_HOST_PLATFORM"]
27    # Get value of sys.platform
28    if sys.platform.startswith('osf1'):
29        return 'osf1'
30    return sys.platform
31host_platform = get_platform()
32
33# Were we compiled --with-pydebug or with #define Py_DEBUG?
34COMPILED_WITH_PYDEBUG = ('--with-pydebug' in sysconfig.get_config_var("CONFIG_ARGS"))
35
36# This global variable is used to hold the list of modules to be disabled.
37disabled_module_list = ["_bsddb", "_sqlite3", "_tkinter", "gdbm", "mpz", "nis"]
38
39def add_dir_to_list(dirlist, dir):
40    """Add the directory 'dir' to the list 'dirlist' (at the front) if
41    1) 'dir' is not already in 'dirlist'
42    2) 'dir' actually exists, and is a directory."""
43    if dir is not None and dir not in dirlist:
44        if host_platform == 'darwin' and is_macosx_sdk_path(dir):
45            # If in a macOS SDK path, check relative to the SDK root
46            dir_exists = os.path.isdir(
47                os.path.join(macosx_sdk_root(), dir[1:]))
48        else:
49            dir_exists = os.path.isdir(dir)
50        if dir_exists:
51            dirlist.insert(0, dir)
52
53MACOS_SDK_ROOT = None
54
55def macosx_sdk_root():
56    """Return the directory of the current macOS SDK.
57
58    If no SDK was explicitly configured, call the compiler to find which
59    include files paths are being searched by default.  Use '/' if the
60    compiler is searching /usr/include (meaning system header files are
61    installed) or use the root of an SDK if that is being searched.
62    (The SDK may be supplied via Xcode or via the Command Line Tools).
63    The SDK paths used by Apple-supplied tool chains depend on the
64    setting of various variables; see the xcrun man page for more info.
65    """
66    global MACOS_SDK_ROOT
67
68    # If already called, return cached result.
69    if MACOS_SDK_ROOT:
70        return MACOS_SDK_ROOT
71
72    cflags = sysconfig.get_config_var('CFLAGS')
73    m = re.search(r'-isysroot\s+(\S+)', cflags)
74    if m is not None:
75        MACOS_SDK_ROOT = m.group(1)
76    else:
77        MACOS_SDK_ROOT = '/'
78        cc = sysconfig.get_config_var('CC')
79        tmpfile = '/tmp/setup_sdk_root.%d' % os.getpid()
80        try:
81            os.unlink(tmpfile)
82        except:
83            pass
84        ret = os.system('%s -E -v - </dev/null 2>%s 1>/dev/null' % (cc, tmpfile))
85        in_incdirs = False
86        try:
87            if ret >> 8 == 0:
88                with open(tmpfile) as fp:
89                    for line in fp.readlines():
90                        if line.startswith("#include <...>"):
91                            in_incdirs = True
92                        elif line.startswith("End of search list"):
93                            in_incdirs = False
94                        elif in_incdirs:
95                            line = line.strip()
96                            if line == '/usr/include':
97                                MACOS_SDK_ROOT = '/'
98                            elif line.endswith(".sdk/usr/include"):
99                                MACOS_SDK_ROOT = line[:-12]
100        finally:
101            os.unlink(tmpfile)
102
103    return MACOS_SDK_ROOT
104
105def is_macosx_sdk_path(path):
106    """
107    Returns True if 'path' can be located in an OSX SDK
108    """
109    return ( (path.startswith('/usr/') and not path.startswith('/usr/local'))
110                or path.startswith('/System/')
111                or path.startswith('/Library/') )
112
113def find_file(filename, std_dirs, paths):
114    """Searches for the directory where a given file is located,
115    and returns a possibly-empty list of additional directories, or None
116    if the file couldn't be found at all.
117
118    'filename' is the name of a file, such as readline.h or libcrypto.a.
119    'std_dirs' is the list of standard system directories; if the
120        file is found in one of them, no additional directives are needed.
121    'paths' is a list of additional locations to check; if the file is
122        found in one of them, the resulting list will contain the directory.
123    """
124    if host_platform == 'darwin':
125        # Honor the MacOSX SDK setting when one was specified.
126        # An SDK is a directory with the same structure as a real
127        # system, but with only header files and libraries.
128        sysroot = macosx_sdk_root()
129
130    # Check the standard locations
131    for dir in std_dirs:
132        f = os.path.join(dir, filename)
133
134        if host_platform == 'darwin' and is_macosx_sdk_path(dir):
135            f = os.path.join(sysroot, dir[1:], filename)
136
137        if os.path.exists(f): return []
138
139    # Check the additional directories
140    for dir in paths:
141        f = os.path.join(dir, filename)
142
143        if host_platform == 'darwin' and is_macosx_sdk_path(dir):
144            f = os.path.join(sysroot, dir[1:], filename)
145
146        if os.path.exists(f):
147            return [dir]
148
149    # Not found anywhere
150    return None
151
152def find_library_file(compiler, libname, std_dirs, paths):
153    result = compiler.find_library_file(std_dirs + paths, libname)
154    if result is None:
155        return None
156
157    if host_platform == 'darwin':
158        sysroot = macosx_sdk_root()
159
160    # Check whether the found file is in one of the standard directories
161    dirname = os.path.dirname(result)
162    for p in std_dirs:
163        # Ensure path doesn't end with path separator
164        p = p.rstrip(os.sep)
165
166        if host_platform == 'darwin' and is_macosx_sdk_path(p):
167            # Note that, as of Xcode 7, Apple SDKs may contain textual stub
168            # libraries with .tbd extensions rather than the normal .dylib
169            # shared libraries installed in /.  The Apple compiler tool
170            # chain handles this transparently but it can cause problems
171            # for programs that are being built with an SDK and searching
172            # for specific libraries.  Distutils find_library_file() now
173            # knows to also search for and return .tbd files.  But callers
174            # of find_library_file need to keep in mind that the base filename
175            # of the returned SDK library file might have a different extension
176            # from that of the library file installed on the running system,
177            # for example:
178            #   /Applications/Xcode.app/Contents/Developer/Platforms/
179            #       MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/
180            #       usr/lib/libedit.tbd
181            # vs
182            #   /usr/lib/libedit.dylib
183            if os.path.join(sysroot, p[1:]) == dirname:
184                return [ ]
185
186        if p == dirname:
187            return [ ]
188
189    # Otherwise, it must have been in one of the additional directories,
190    # so we have to figure out which one.
191    for p in paths:
192        # Ensure path doesn't end with path separator
193        p = p.rstrip(os.sep)
194
195        if host_platform == 'darwin' and is_macosx_sdk_path(p):
196            if os.path.join(sysroot, p[1:]) == dirname:
197                return [ p ]
198
199        if p == dirname:
200            return [p]
201    else:
202        assert False, "Internal error: Path not found in std_dirs or paths"
203
204def module_enabled(extlist, modname):
205    """Returns whether the module 'modname' is present in the list
206    of extensions 'extlist'."""
207    extlist = [ext for ext in extlist if ext.name == modname]
208    return len(extlist)
209
210def find_module_file(module, dirlist):
211    """Find a module in a set of possible folders. If it is not found
212    return the unadorned filename"""
213    list = find_file(module, [], dirlist)
214    if not list:
215        return module
216    if len(list) > 1:
217        log.info("WARNING: multiple copies of %s found"%module)
218    return os.path.join(list[0], module)
219
220class PyBuildExt(build_ext):
221
222    def __init__(self, dist):
223        build_ext.__init__(self, dist)
224        self.failed = []
225
226    def build_extensions(self):
227
228        # Detect which modules should be compiled
229        missing = self.detect_modules()
230
231        # Remove modules that are present on the disabled list
232        extensions = [ext for ext in self.extensions
233                      if ext.name not in disabled_module_list]
234        # move ctypes to the end, it depends on other modules
235        ext_map = dict((ext.name, i) for i, ext in enumerate(extensions))
236        if "_ctypes" in ext_map:
237            ctypes = extensions.pop(ext_map["_ctypes"])
238            extensions.append(ctypes)
239        self.extensions = extensions
240
241        # Fix up the autodetected modules, prefixing all the source files
242        # with Modules/ and adding Python's include directory to the path.
243        (srcdir,) = sysconfig.get_config_vars('srcdir')
244        if not srcdir:
245            # Maybe running on Windows but not using CYGWIN?
246            raise ValueError("No source directory; cannot proceed.")
247        srcdir = os.path.abspath(srcdir)
248        moddirlist = [os.path.join(srcdir, 'Modules')]
249
250        # Platform-dependent module source and include directories
251        incdirlist = []
252
253        if host_platform == 'darwin' and ("--disable-toolbox-glue" not in
254            sysconfig.get_config_var("CONFIG_ARGS")):
255            # Mac OS X also includes some mac-specific modules
256            macmoddir = os.path.join(srcdir, 'Mac/Modules')
257            moddirlist.append(macmoddir)
258            incdirlist.append(os.path.join(srcdir, 'Mac/Include'))
259
260        # Fix up the paths for scripts, too
261        self.distribution.scripts = [os.path.join(srcdir, filename)
262                                     for filename in self.distribution.scripts]
263
264        # Python header files
265        headers = [sysconfig.get_config_h_filename()]
266        headers += glob(os.path.join(sysconfig.get_path('include'), "*.h"))
267        for ext in self.extensions[:]:
268            ext.sources = [ find_module_file(filename, moddirlist)
269                            for filename in ext.sources ]
270            if ext.depends is not None:
271                ext.depends = [find_module_file(filename, moddirlist)
272                               for filename in ext.depends]
273            else:
274                ext.depends = []
275            # re-compile extensions if a header file has been changed
276            ext.depends.extend(headers)
277
278            # platform specific include directories
279            ext.include_dirs.extend(incdirlist)
280
281            # If a module has already been built statically,
282            # don't build it here
283            if ext.name in sys.builtin_module_names:
284                self.extensions.remove(ext)
285
286        # Parse Modules/Setup and Modules/Setup.local to figure out which
287        # modules are turned on in the file.
288        remove_modules = []
289        for filename in ('Modules/Setup', 'Modules/Setup.local'):
290            input = text_file.TextFile(filename, join_lines=1)
291            while 1:
292                line = input.readline()
293                if not line: break
294                line = line.split()
295                remove_modules.append(line[0])
296            input.close()
297
298        for ext in self.extensions[:]:
299            if ext.name in remove_modules:
300                self.extensions.remove(ext)
301
302        # When you run "make CC=altcc" or something similar, you really want
303        # those environment variables passed into the setup.py phase.  Here's
304        # a small set of useful ones.
305        compiler = os.environ.get('CC')
306        args = {}
307        # unfortunately, distutils doesn't let us provide separate C and C++
308        # compilers
309        if compiler is not None:
310            (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS')
311            args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags
312        self.compiler.set_executables(**args)
313
314        build_ext.build_extensions(self)
315
316        longest = 0
317        if self.extensions:
318            longest = max([len(e.name) for e in self.extensions])
319        if self.failed:
320            longest = max(longest, max([len(name) for name in self.failed]))
321
322        def print_three_column(lst):
323            lst.sort(key=str.lower)
324            # guarantee zip() doesn't drop anything
325            while len(lst) % 3:
326                lst.append("")
327            for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]):
328                print "%-*s   %-*s   %-*s" % (longest, e, longest, f,
329                                              longest, g)
330
331        if missing:
332            print
333            print ("Python build finished, but the necessary bits to build "
334                   "these modules were not found:")
335            print_three_column(missing)
336            print ("To find the necessary bits, look in setup.py in"
337                   " detect_modules() for the module's name.")
338            print
339
340        if self.failed:
341            failed = self.failed[:]
342            print
343            print "Failed to build these modules:"
344            print_three_column(failed)
345            print
346
347    def build_extension(self, ext):
348
349        if ext.name == '_ctypes':
350            if not self.configure_ctypes(ext):
351                return
352
353        try:
354            build_ext.build_extension(self, ext)
355        except (CCompilerError, DistutilsError), why:
356            self.announce('WARNING: building of extension "%s" failed: %s' %
357                          (ext.name, sys.exc_info()[1]))
358            self.failed.append(ext.name)
359            return
360        # Workaround for Mac OS X: The Carbon-based modules cannot be
361        # reliably imported into a command-line Python
362        if 'Carbon' in ext.extra_link_args:
363            self.announce(
364                'WARNING: skipping import check for Carbon-based "%s"' %
365                ext.name)
366            return
367
368        if host_platform == 'darwin' and (
369                sys.maxint > 2**32 and '-arch' in ext.extra_link_args):
370            # Don't bother doing an import check when an extension was
371            # build with an explicit '-arch' flag on OSX. That's currently
372            # only used to build 32-bit only extensions in a 4-way
373            # universal build and loading 32-bit code into a 64-bit
374            # process will fail.
375            self.announce(
376                'WARNING: skipping import check for "%s"' %
377                ext.name)
378            return
379
380        # Workaround for Cygwin: Cygwin currently has fork issues when many
381        # modules have been imported
382        if host_platform == 'cygwin':
383            self.announce('WARNING: skipping import check for Cygwin-based "%s"'
384                % ext.name)
385            return
386        ext_filename = os.path.join(
387            self.build_lib,
388            self.get_ext_filename(self.get_ext_fullname(ext.name)))
389
390        # Don't try to load extensions for cross builds
391        if cross_compiling:
392            return
393
394        try:
395            imp.load_dynamic(ext.name, ext_filename)
396        except ImportError, why:
397            self.failed.append(ext.name)
398            self.announce('*** WARNING: renaming "%s" since importing it'
399                          ' failed: %s' % (ext.name, why), level=3)
400            assert not self.inplace
401            basename, tail = os.path.splitext(ext_filename)
402            newname = basename + "_failed" + tail
403            if os.path.exists(newname):
404                os.remove(newname)
405            os.rename(ext_filename, newname)
406
407            # XXX -- This relies on a Vile HACK in
408            # distutils.command.build_ext.build_extension().  The
409            # _built_objects attribute is stored there strictly for
410            # use here.
411            # If there is a failure, _built_objects may not be there,
412            # so catch the AttributeError and move on.
413            try:
414                for filename in self._built_objects:
415                    os.remove(filename)
416            except AttributeError:
417                self.announce('unable to remove files (ignored)')
418        except:
419            exc_type, why, tb = sys.exc_info()
420            self.announce('*** WARNING: importing extension "%s" '
421                          'failed with %s: %s' % (ext.name, exc_type, why),
422                          level=3)
423            self.failed.append(ext.name)
424
425    def add_multiarch_paths(self):
426        # Debian/Ubuntu multiarch support.
427        # https://wiki.ubuntu.com/MultiarchSpec
428        cc = sysconfig.get_config_var('CC')
429        tmpfile = os.path.join(self.build_temp, 'multiarch')
430        if not os.path.exists(self.build_temp):
431            os.makedirs(self.build_temp)
432        ret = os.system(
433            '%s -print-multiarch > %s 2> /dev/null' % (cc, tmpfile))
434        multiarch_path_component = ''
435        try:
436            if ret >> 8 == 0:
437                with open(tmpfile) as fp:
438                    multiarch_path_component = fp.readline().strip()
439        finally:
440            os.unlink(tmpfile)
441
442        if multiarch_path_component != '':
443            add_dir_to_list(self.compiler.library_dirs,
444                            '/usr/lib/' + multiarch_path_component)
445            add_dir_to_list(self.compiler.include_dirs,
446                            '/usr/include/' + multiarch_path_component)
447            return
448
449        if not find_executable('dpkg-architecture'):
450            return
451        opt = ''
452        if cross_compiling:
453            opt = '-t' + sysconfig.get_config_var('HOST_GNU_TYPE')
454        tmpfile = os.path.join(self.build_temp, 'multiarch')
455        if not os.path.exists(self.build_temp):
456            os.makedirs(self.build_temp)
457        ret = os.system(
458            'dpkg-architecture %s -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
459            (opt, tmpfile))
460        try:
461            if ret >> 8 == 0:
462                with open(tmpfile) as fp:
463                    multiarch_path_component = fp.readline().strip()
464                add_dir_to_list(self.compiler.library_dirs,
465                                '/usr/lib/' + multiarch_path_component)
466                add_dir_to_list(self.compiler.include_dirs,
467                                '/usr/include/' + multiarch_path_component)
468        finally:
469            os.unlink(tmpfile)
470
471    def add_gcc_paths(self):
472        gcc = sysconfig.get_config_var('CC')
473        tmpfile = os.path.join(self.build_temp, 'gccpaths')
474        if not os.path.exists(self.build_temp):
475            os.makedirs(self.build_temp)
476        ret = os.system('%s -E -v - </dev/null 2>%s 1>/dev/null' % (gcc, tmpfile))
477        is_gcc = False
478        in_incdirs = False
479        inc_dirs = []
480        lib_dirs = []
481        try:
482            if ret >> 8 == 0:
483                with open(tmpfile) as fp:
484                    for line in fp.readlines():
485                        if line.startswith("gcc version"):
486                            is_gcc = True
487                        elif line.startswith("#include <...>"):
488                            in_incdirs = True
489                        elif line.startswith("End of search list"):
490                            in_incdirs = False
491                        elif is_gcc and line.startswith("LIBRARY_PATH"):
492                            for d in line.strip().split("=")[1].split(":"):
493                                d = os.path.normpath(d)
494                                if '/gcc/' not in d:
495                                    add_dir_to_list(self.compiler.library_dirs,
496                                                    d)
497                        elif is_gcc and in_incdirs and '/gcc/' not in line:
498                            add_dir_to_list(self.compiler.include_dirs,
499                                            line.strip())
500        finally:
501            os.unlink(tmpfile)
502
503    def detect_modules(self):
504        # Ensure that /usr/local is always used
505        if not cross_compiling:
506            add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
507            add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
508        if cross_compiling:
509            self.add_gcc_paths()
510        self.add_multiarch_paths()
511
512        # Add paths specified in the environment variables LDFLAGS and
513        # CPPFLAGS for header and library files.
514        # We must get the values from the Makefile and not the environment
515        # directly since an inconsistently reproducible issue comes up where
516        # the environment variable is not set even though the value were passed
517        # into configure and stored in the Makefile (issue found on OS X 10.3).
518        for env_var, arg_name, dir_list in (
519                ('LDFLAGS', '-R', self.compiler.runtime_library_dirs),
520                ('LDFLAGS', '-L', self.compiler.library_dirs),
521                ('CPPFLAGS', '-I', self.compiler.include_dirs)):
522            env_val = sysconfig.get_config_var(env_var)
523            if env_val:
524                # To prevent optparse from raising an exception about any
525                # options in env_val that it doesn't know about we strip out
526                # all double dashes and any dashes followed by a character
527                # that is not for the option we are dealing with.
528                #
529                # Please note that order of the regex is important!  We must
530                # strip out double-dashes first so that we don't end up with
531                # substituting "--Long" to "-Long" and thus lead to "ong" being
532                # used for a library directory.
533                env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1],
534                                 ' ', env_val)
535                parser = optparse.OptionParser()
536                # Make sure that allowing args interspersed with options is
537                # allowed
538                parser.allow_interspersed_args = True
539                parser.error = lambda msg: None
540                parser.add_option(arg_name, dest="dirs", action="append")
541                options = parser.parse_args(env_val.split())[0]
542                if options.dirs:
543                    for directory in reversed(options.dirs):
544                        add_dir_to_list(dir_list, directory)
545
546        if os.path.normpath(sys.prefix) != '/usr' \
547                and not sysconfig.get_config_var('PYTHONFRAMEWORK'):
548            # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework
549            # (PYTHONFRAMEWORK is set) to avoid # linking problems when
550            # building a framework with different architectures than
551            # the one that is currently installed (issue #7473)
552            add_dir_to_list(self.compiler.library_dirs,
553                            sysconfig.get_config_var("LIBDIR"))
554            add_dir_to_list(self.compiler.include_dirs,
555                            sysconfig.get_config_var("INCLUDEDIR"))
556
557        try:
558            have_unicode = unicode
559        except NameError:
560            have_unicode = 0
561
562        # lib_dirs and inc_dirs are used to search for files;
563        # if a file is found in one of those directories, it can
564        # be assumed that no additional -I,-L directives are needed.
565        inc_dirs = self.compiler.include_dirs[:]
566        lib_dirs = self.compiler.library_dirs[:]
567        if not cross_compiling:
568            for d in (
569                '/usr/include',
570                ):
571                add_dir_to_list(inc_dirs, d)
572            for d in (
573                '/lib64', '/usr/lib64',
574                '/lib', '/usr/lib',
575                ):
576                add_dir_to_list(lib_dirs, d)
577        exts = []
578        missing = []
579
580        config_h = sysconfig.get_config_h_filename()
581        config_h_vars = sysconfig.parse_config_h(open(config_h))
582
583        srcdir = sysconfig.get_config_var('srcdir')
584
585        # Check for AtheOS which has libraries in non-standard locations
586        if host_platform == 'atheos':
587            lib_dirs += ['/system/libs', '/atheos/autolnk/lib']
588            lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep)
589            inc_dirs += ['/system/include', '/atheos/autolnk/include']
590            inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep)
591
592        # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
593        if host_platform in ['osf1', 'unixware7', 'openunix8']:
594            lib_dirs += ['/usr/ccs/lib']
595
596        # HP-UX11iv3 keeps files in lib/hpux folders.
597        if host_platform == 'hp-ux11':
598            lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32']
599
600        if host_platform == 'darwin':
601            # This should work on any unixy platform ;-)
602            # If the user has bothered specifying additional -I and -L flags
603            # in OPT and LDFLAGS we might as well use them here.
604            #   NOTE: using shlex.split would technically be more correct, but
605            # also gives a bootstrap problem. Let's hope nobody uses directories
606            # with whitespace in the name to store libraries.
607            cflags, ldflags = sysconfig.get_config_vars(
608                    'CFLAGS', 'LDFLAGS')
609            for item in cflags.split():
610                if item.startswith('-I'):
611                    inc_dirs.append(item[2:])
612
613            for item in ldflags.split():
614                if item.startswith('-L'):
615                    lib_dirs.append(item[2:])
616
617        # Check for MacOS X, which doesn't need libm.a at all
618        math_libs = ['m']
619        if host_platform in ['darwin', 'beos']:
620            math_libs = []
621
622        # XXX Omitted modules: gl, pure, dl, SGI-specific modules
623
624        #
625        # The following modules are all pretty straightforward, and compile
626        # on pretty much any POSIXish platform.
627        #
628
629        # Some modules that are normally always on:
630        #exts.append( Extension('_weakref', ['_weakref.c']) )
631
632        # array objects
633        exts.append( Extension('array', ['arraymodule.c']) )
634
635        shared_math = 'Modules/_math.o'
636        # complex math library functions
637        exts.append( Extension('cmath', ['cmathmodule.c'],
638                               extra_objects=[shared_math],
639                               depends=['_math.h', shared_math],
640                               libraries=math_libs) )
641        # math library functions, e.g. sin()
642        exts.append( Extension('math',  ['mathmodule.c'],
643                               extra_objects=[shared_math],
644                               depends=['_math.h', shared_math],
645                               libraries=math_libs) )
646        # fast string operations implemented in C
647        exts.append( Extension('strop', ['stropmodule.c']) )
648        # time operations and variables
649        exts.append( Extension('time', ['timemodule.c'],
650                               libraries=math_libs) )
651        exts.append( Extension('datetime', ['datetimemodule.c', 'timemodule.c'],
652                               libraries=math_libs) )
653        # fast iterator tools implemented in C
654        exts.append( Extension("itertools", ["itertoolsmodule.c"]) )
655        # code that will be builtins in the future, but conflict with the
656        #  current builtins
657        exts.append( Extension('future_builtins', ['future_builtins.c']) )
658        # random number generator implemented in C
659        exts.append( Extension("_random", ["_randommodule.c"]) )
660        # high-performance collections
661        exts.append( Extension("_collections", ["_collectionsmodule.c"]) )
662        # bisect
663        exts.append( Extension("_bisect", ["_bisectmodule.c"]) )
664        # heapq
665        exts.append( Extension("_heapq", ["_heapqmodule.c"]) )
666        # operator.add() and similar goodies
667        exts.append( Extension('operator', ['operator.c']) )
668        # Python 3.1 _io library
669        exts.append( Extension("_io",
670            ["_io/bufferedio.c", "_io/bytesio.c", "_io/fileio.c",
671             "_io/iobase.c", "_io/_iomodule.c", "_io/stringio.c", "_io/textio.c"],
672             depends=["_io/_iomodule.h"], include_dirs=["Modules/_io"]))
673        # _functools
674        exts.append( Extension("_functools", ["_functoolsmodule.c"]) )
675        # _json speedups
676        exts.append( Extension("_json", ["_json.c"]) )
677        # Python C API test module
678        exts.append( Extension('_testcapi', ['_testcapimodule.c'],
679                               depends=['testcapi_long.h']) )
680        # profilers (_lsprof is for cProfile.py)
681        exts.append( Extension('_hotshot', ['_hotshot.c']) )
682        exts.append( Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c']) )
683        # static Unicode character database
684        if have_unicode:
685            exts.append( Extension('unicodedata', ['unicodedata.c']) )
686        else:
687            missing.append('unicodedata')
688        # access to ISO C locale support
689        data = open('pyconfig.h').read()
690        m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data)
691        if m is not None:
692            locale_libs = ['intl']
693        else:
694            locale_libs = []
695        if host_platform == 'darwin':
696            locale_extra_link_args = ['-framework', 'CoreFoundation']
697        else:
698            locale_extra_link_args = []
699
700
701        exts.append( Extension('_locale', ['_localemodule.c'],
702                               libraries=locale_libs,
703                               extra_link_args=locale_extra_link_args) )
704
705        # Modules with some UNIX dependencies -- on by default:
706        # (If you have a really backward UNIX, select and socket may not be
707        # supported...)
708
709        # fcntl(2) and ioctl(2)
710        libs = []
711        if (config_h_vars.get('FLOCK_NEEDS_LIBBSD', False)):
712            # May be necessary on AIX for flock function
713            libs = ['bsd']
714        exts.append( Extension('fcntl', ['fcntlmodule.c'], libraries=libs) )
715        # pwd(3)
716        exts.append( Extension('pwd', ['pwdmodule.c']) )
717        # grp(3)
718        exts.append( Extension('grp', ['grpmodule.c']) )
719        # spwd, shadow passwords
720        if (config_h_vars.get('HAVE_GETSPNAM', False) or
721                config_h_vars.get('HAVE_GETSPENT', False)):
722            exts.append( Extension('spwd', ['spwdmodule.c']) )
723        else:
724            missing.append('spwd')
725
726        # select(2); not on ancient System V
727        exts.append( Extension('select', ['selectmodule.c']) )
728
729        # Fred Drake's interface to the Python parser
730        exts.append( Extension('parser', ['parsermodule.c']) )
731
732        # cStringIO and cPickle
733        exts.append( Extension('cStringIO', ['cStringIO.c']) )
734        exts.append( Extension('cPickle', ['cPickle.c']) )
735
736        # Memory-mapped files (also works on Win32).
737        if host_platform not in ['atheos']:
738            exts.append( Extension('mmap', ['mmapmodule.c']) )
739        else:
740            missing.append('mmap')
741
742        # Lance Ellinghaus's syslog module
743        # syslog daemon interface
744        exts.append( Extension('syslog', ['syslogmodule.c']) )
745
746        # George Neville-Neil's timing module:
747        # Deprecated in PEP 4 http://www.python.org/peps/pep-0004.html
748        # http://mail.python.org/pipermail/python-dev/2006-January/060023.html
749        #exts.append( Extension('timing', ['timingmodule.c']) )
750
751        #
752        # Here ends the simple stuff.  From here on, modules need certain
753        # libraries, are platform-specific, or present other surprises.
754        #
755
756        # Multimedia modules
757        # These don't work for 64-bit platforms!!!
758        # These represent audio samples or images as strings:
759
760        # Operations on audio samples
761        # According to #993173, this one should actually work fine on
762        # 64-bit platforms.
763        exts.append( Extension('audioop', ['audioop.c']) )
764
765        # Disabled on 64-bit platforms
766        if sys.maxsize != 9223372036854775807L:
767            # Operations on images
768            exts.append( Extension('imageop', ['imageop.c']) )
769        else:
770            missing.extend(['imageop'])
771
772        # readline
773        do_readline = self.compiler.find_library_file(lib_dirs, 'readline')
774        readline_termcap_library = ""
775        curses_library = ""
776        # Determine if readline is already linked against curses or tinfo.
777        if do_readline and find_executable('ldd'):
778            fp = os.popen("ldd %s" % do_readline)
779            ldd_output = fp.readlines()
780            ret = fp.close()
781            if ret is None or ret >> 8 == 0:
782                for ln in ldd_output:
783                    if 'curses' in ln:
784                        readline_termcap_library = re.sub(
785                            r'.*lib(n?cursesw?)\.so.*', r'\1', ln
786                        ).rstrip()
787                        break
788                    if 'tinfo' in ln: # termcap interface split out from ncurses
789                        readline_termcap_library = 'tinfo'
790                        break
791        # Issue 7384: If readline is already linked against curses,
792        # use the same library for the readline and curses modules.
793        if 'curses' in readline_termcap_library:
794            curses_library = readline_termcap_library
795        elif self.compiler.find_library_file(lib_dirs, 'ncursesw'):
796            curses_library = 'ncursesw'
797        elif self.compiler.find_library_file(lib_dirs, 'ncurses'):
798            curses_library = 'ncurses'
799        elif self.compiler.find_library_file(lib_dirs, 'curses'):
800            curses_library = 'curses'
801
802        if host_platform == 'darwin':
803            os_release = int(os.uname()[2].split('.')[0])
804            dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
805            if (dep_target and
806                    (tuple(int(n) for n in dep_target.split('.')[0:2])
807                        < (10, 5) ) ):
808                os_release = 8
809            if os_release < 9:
810                # MacOSX 10.4 has a broken readline. Don't try to build
811                # the readline module unless the user has installed a fixed
812                # readline package
813                if find_file('readline/rlconf.h', inc_dirs, []) is None:
814                    do_readline = False
815        if do_readline:
816            if host_platform == 'darwin' and os_release < 9:
817                # In every directory on the search path search for a dynamic
818                # library and then a static library, instead of first looking
819                # for dynamic libraries on the entire path.
820                # This way a statically linked custom readline gets picked up
821                # before the (possibly broken) dynamic library in /usr/lib.
822                readline_extra_link_args = ('-Wl,-search_paths_first',)
823            else:
824                readline_extra_link_args = ()
825
826            readline_libs = ['readline']
827            if readline_termcap_library:
828                pass # Issue 7384: Already linked against curses or tinfo.
829            elif curses_library:
830                readline_libs.append(curses_library)
831            elif self.compiler.find_library_file(lib_dirs +
832                                                     ['/usr/lib/termcap'],
833                                                     'termcap'):
834                readline_libs.append('termcap')
835            exts.append( Extension('readline', ['readline.c'],
836                                   library_dirs=['/usr/lib/termcap'],
837                                   extra_link_args=readline_extra_link_args,
838                                   libraries=readline_libs) )
839        else:
840            missing.append('readline')
841
842        # crypt module.
843
844        if self.compiler.find_library_file(lib_dirs, 'crypt'):
845            libs = ['crypt']
846        else:
847            libs = []
848        exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) )
849
850        # CSV files
851        exts.append( Extension('_csv', ['_csv.c']) )
852
853        # socket(2)
854        exts.append( Extension('_socket', ['socketmodule.c', 'timemodule.c'],
855                               depends=['socketmodule.h'],
856                               libraries=math_libs) )
857        # Detect SSL support for the socket module (via _ssl)
858        search_for_ssl_incs_in = [
859                              '/usr/local/ssl/include',
860                              '/usr/contrib/ssl/include/'
861                             ]
862        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
863                             search_for_ssl_incs_in
864                             )
865        if ssl_incs is not None:
866            krb5_h = find_file('krb5.h', inc_dirs,
867                               ['/usr/kerberos/include'])
868            if krb5_h:
869                ssl_incs += krb5_h
870        ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
871                                     ['/usr/local/ssl/lib',
872                                      '/usr/contrib/ssl/lib/'
873                                     ] )
874
875        if (ssl_incs is not None and
876            ssl_libs is not None):
877            exts.append( Extension('_ssl', ['_ssl.c'],
878                                   include_dirs = ssl_incs,
879                                   library_dirs = ssl_libs,
880                                   libraries = ['ssl', 'crypto'],
881                                   depends = ['socketmodule.h']), )
882        else:
883            missing.append('_ssl')
884
885        # find out which version of OpenSSL we have
886        openssl_ver = 0
887        openssl_ver_re = re.compile(
888            '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' )
889
890        # look for the openssl version header on the compiler search path.
891        opensslv_h = find_file('openssl/opensslv.h', [],
892                inc_dirs + search_for_ssl_incs_in)
893        if opensslv_h:
894            name = os.path.join(opensslv_h[0], 'openssl/opensslv.h')
895            if host_platform == 'darwin' and is_macosx_sdk_path(name):
896                name = os.path.join(macosx_sdk_root(), name[1:])
897            try:
898                incfile = open(name, 'r')
899                for line in incfile:
900                    m = openssl_ver_re.match(line)
901                    if m:
902                        openssl_ver = eval(m.group(1))
903            except IOError, msg:
904                print "IOError while reading opensshv.h:", msg
905                pass
906
907        min_openssl_ver = 0x00907000
908        have_any_openssl = ssl_incs is not None and ssl_libs is not None
909        have_usable_openssl = (have_any_openssl and
910                               openssl_ver >= min_openssl_ver)
911
912        if have_any_openssl:
913            if have_usable_openssl:
914                # The _hashlib module wraps optimized implementations
915                # of hash functions from the OpenSSL library.
916                exts.append( Extension('_hashlib', ['_hashopenssl.c'],
917                                       include_dirs = ssl_incs,
918                                       library_dirs = ssl_libs,
919                                       libraries = ['ssl', 'crypto']) )
920            else:
921                print ("warning: openssl 0x%08x is too old for _hashlib" %
922                       openssl_ver)
923                missing.append('_hashlib')
924        if COMPILED_WITH_PYDEBUG or not have_usable_openssl:
925            # The _sha module implements the SHA1 hash algorithm.
926            exts.append( Extension('_sha', ['shamodule.c']) )
927            # The _md5 module implements the RSA Data Security, Inc. MD5
928            # Message-Digest Algorithm, described in RFC 1321.  The
929            # necessary files md5.c and md5.h are included here.
930            exts.append( Extension('_md5',
931                            sources = ['md5module.c', 'md5.c'],
932                            depends = ['md5.h']) )
933
934        min_sha2_openssl_ver = 0x00908000
935        if COMPILED_WITH_PYDEBUG or openssl_ver < min_sha2_openssl_ver:
936            # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash
937            exts.append( Extension('_sha256', ['sha256module.c']) )
938            exts.append( Extension('_sha512', ['sha512module.c']) )
939
940        # Modules that provide persistent dictionary-like semantics.  You will
941        # probably want to arrange for at least one of them to be available on
942        # your machine, though none are defined by default because of library
943        # dependencies.  The Python module anydbm.py provides an
944        # implementation independent wrapper for these; dumbdbm.py provides
945        # similar functionality (but slower of course) implemented in Python.
946
947        # Sleepycat^WOracle Berkeley DB interface.
948        #  http://www.oracle.com/database/berkeley-db/db/index.html
949        #
950        # This requires the Sleepycat^WOracle DB code. The supported versions
951        # are set below.  Visit the URL above to download
952        # a release.  Most open source OSes come with one or more
953        # versions of BerkeleyDB already installed.
954
955        max_db_ver = (5, 3)
956        min_db_ver = (4, 3)
957        db_setup_debug = False   # verbose debug prints from this script?
958
959        def allow_db_ver(db_ver):
960            """Returns a boolean if the given BerkeleyDB version is acceptable.
961
962            Args:
963              db_ver: A tuple of the version to verify.
964            """
965            if not (min_db_ver <= db_ver <= max_db_ver):
966                return False
967            # Use this function to filter out known bad configurations.
968            if (4, 6) == db_ver[:2]:
969                # BerkeleyDB 4.6.x is not stable on many architectures.
970                arch = platform_machine()
971                if arch not in ('i386', 'i486', 'i586', 'i686',
972                                'x86_64', 'ia64'):
973                    return False
974            return True
975
976        def gen_db_minor_ver_nums(major):
977            if major == 5:
978                for x in range(max_db_ver[1]+1):
979                    if allow_db_ver((5, x)):
980                        yield x
981            elif major == 4:
982                for x in range(9):
983                    if allow_db_ver((4, x)):
984                        yield x
985            elif major == 3:
986                for x in (3,):
987                    if allow_db_ver((3, x)):
988                        yield x
989            else:
990                raise ValueError("unknown major BerkeleyDB version", major)
991
992        # construct a list of paths to look for the header file in on
993        # top of the normal inc_dirs.
994        db_inc_paths = [
995            '/usr/include/db4',
996            '/usr/local/include/db4',
997            '/opt/sfw/include/db4',
998            '/usr/include/db3',
999            '/usr/local/include/db3',
1000            '/opt/sfw/include/db3',
1001            # Fink defaults (http://fink.sourceforge.net/)
1002            '/sw/include/db4',
1003            '/sw/include/db3',
1004        ]
1005        # 4.x minor number specific paths
1006        for x in gen_db_minor_ver_nums(4):
1007            db_inc_paths.append('/usr/include/db4%d' % x)
1008            db_inc_paths.append('/usr/include/db4.%d' % x)
1009            db_inc_paths.append('/usr/local/BerkeleyDB.4.%d/include' % x)
1010            db_inc_paths.append('/usr/local/include/db4%d' % x)
1011            db_inc_paths.append('/pkg/db-4.%d/include' % x)
1012            db_inc_paths.append('/opt/db-4.%d/include' % x)
1013            # MacPorts default (http://www.macports.org/)
1014            db_inc_paths.append('/opt/local/include/db4%d' % x)
1015        # 3.x minor number specific paths
1016        for x in gen_db_minor_ver_nums(3):
1017            db_inc_paths.append('/usr/include/db3%d' % x)
1018            db_inc_paths.append('/usr/local/BerkeleyDB.3.%d/include' % x)
1019            db_inc_paths.append('/usr/local/include/db3%d' % x)
1020            db_inc_paths.append('/pkg/db-3.%d/include' % x)
1021            db_inc_paths.append('/opt/db-3.%d/include' % x)
1022
1023        if cross_compiling:
1024            db_inc_paths = []
1025
1026        # Add some common subdirectories for Sleepycat DB to the list,
1027        # based on the standard include directories. This way DB3/4 gets
1028        # picked up when it is installed in a non-standard prefix and
1029        # the user has added that prefix into inc_dirs.
1030        std_variants = []
1031        for dn in inc_dirs:
1032            std_variants.append(os.path.join(dn, 'db3'))
1033            std_variants.append(os.path.join(dn, 'db4'))
1034            for x in gen_db_minor_ver_nums(4):
1035                std_variants.append(os.path.join(dn, "db4%d"%x))
1036                std_variants.append(os.path.join(dn, "db4.%d"%x))
1037            for x in gen_db_minor_ver_nums(3):
1038                std_variants.append(os.path.join(dn, "db3%d"%x))
1039                std_variants.append(os.path.join(dn, "db3.%d"%x))
1040
1041        db_inc_paths = std_variants + db_inc_paths
1042        db_inc_paths = [p for p in db_inc_paths if os.path.exists(p)]
1043
1044        db_ver_inc_map = {}
1045
1046        if host_platform == 'darwin':
1047            sysroot = macosx_sdk_root()
1048
1049        class db_found(Exception): pass
1050        try:
1051            # See whether there is a Sleepycat header in the standard
1052            # search path.
1053            for d in inc_dirs + db_inc_paths:
1054                f = os.path.join(d, "db.h")
1055
1056                if host_platform == 'darwin' and is_macosx_sdk_path(d):
1057                    f = os.path.join(sysroot, d[1:], "db.h")
1058
1059                if db_setup_debug: print "db: looking for db.h in", f
1060                if os.path.exists(f):
1061                    f = open(f).read()
1062                    m = re.search(r"#define\WDB_VERSION_MAJOR\W(\d+)", f)
1063                    if m:
1064                        db_major = int(m.group(1))
1065                        m = re.search(r"#define\WDB_VERSION_MINOR\W(\d+)", f)
1066                        db_minor = int(m.group(1))
1067                        db_ver = (db_major, db_minor)
1068
1069                        # Avoid 4.6 prior to 4.6.21 due to a BerkeleyDB bug
1070                        if db_ver == (4, 6):
1071                            m = re.search(r"#define\WDB_VERSION_PATCH\W(\d+)", f)
1072                            db_patch = int(m.group(1))
1073                            if db_patch < 21:
1074                                print "db.h:", db_ver, "patch", db_patch,
1075                                print "being ignored (4.6.x must be >= 4.6.21)"
1076                                continue
1077
1078                        if ( (db_ver not in db_ver_inc_map) and
1079                            allow_db_ver(db_ver) ):
1080                            # save the include directory with the db.h version
1081                            # (first occurrence only)
1082                            db_ver_inc_map[db_ver] = d
1083                            if db_setup_debug:
1084                                print "db.h: found", db_ver, "in", d
1085                        else:
1086                            # we already found a header for this library version
1087                            if db_setup_debug: print "db.h: ignoring", d
1088                    else:
1089                        # ignore this header, it didn't contain a version number
1090                        if db_setup_debug:
1091                            print "db.h: no version number version in", d
1092
1093            db_found_vers = db_ver_inc_map.keys()
1094            db_found_vers.sort()
1095
1096            while db_found_vers:
1097                db_ver = db_found_vers.pop()
1098                db_incdir = db_ver_inc_map[db_ver]
1099
1100                # check lib directories parallel to the location of the header
1101                db_dirs_to_check = [
1102                    db_incdir.replace("include", 'lib64'),
1103                    db_incdir.replace("include", 'lib'),
1104                ]
1105
1106                if host_platform != 'darwin':
1107                    db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check)
1108
1109                else:
1110                    # Same as other branch, but takes OSX SDK into account
1111                    tmp = []
1112                    for dn in db_dirs_to_check:
1113                        if is_macosx_sdk_path(dn):
1114                            if os.path.isdir(os.path.join(sysroot, dn[1:])):
1115                                tmp.append(dn)
1116                        else:
1117                            if os.path.isdir(dn):
1118                                tmp.append(dn)
1119                    db_dirs_to_check = tmp
1120
1121                # Look for a version specific db-X.Y before an ambiguous dbX
1122                # XXX should we -ever- look for a dbX name?  Do any
1123                # systems really not name their library by version and
1124                # symlink to more general names?
1125                for dblib in (('db-%d.%d' % db_ver),
1126                              ('db%d%d' % db_ver),
1127                              ('db%d' % db_ver[0])):
1128                    dblib_file = self.compiler.find_library_file(
1129                                    db_dirs_to_check + lib_dirs, dblib )
1130                    if dblib_file:
1131                        dblib_dir = [ os.path.abspath(os.path.dirname(dblib_file)) ]
1132                        raise db_found
1133                    else:
1134                        if db_setup_debug: print "db lib: ", dblib, "not found"
1135
1136        except db_found:
1137            if db_setup_debug:
1138                print "bsddb using BerkeleyDB lib:", db_ver, dblib
1139                print "bsddb lib dir:", dblib_dir, " inc dir:", db_incdir
1140            db_incs = [db_incdir]
1141            dblibs = [dblib]
1142            # We add the runtime_library_dirs argument because the
1143            # BerkeleyDB lib we're linking against often isn't in the
1144            # system dynamic library search path.  This is usually
1145            # correct and most trouble free, but may cause problems in
1146            # some unusual system configurations (e.g. the directory
1147            # is on an NFS server that goes away).
1148            exts.append(Extension('_bsddb', ['_bsddb.c'],
1149                                  depends = ['bsddb.h'],
1150                                  library_dirs=dblib_dir,
1151                                  runtime_library_dirs=dblib_dir,
1152                                  include_dirs=db_incs,
1153                                  libraries=dblibs))
1154        else:
1155            if db_setup_debug: print "db: no appropriate library found"
1156            db_incs = None
1157            dblibs = []
1158            dblib_dir = None
1159            missing.append('_bsddb')
1160
1161        # The sqlite interface
1162        sqlite_setup_debug = False   # verbose debug prints from this script?
1163
1164        # We hunt for #define SQLITE_VERSION "n.n.n"
1165        # We need to find >= sqlite version 3.0.8
1166        sqlite_incdir = sqlite_libdir = None
1167        sqlite_inc_paths = [ '/usr/include',
1168                             '/usr/include/sqlite',
1169                             '/usr/include/sqlite3',
1170                             '/usr/local/include',
1171                             '/usr/local/include/sqlite',
1172                             '/usr/local/include/sqlite3',
1173                           ]
1174        if cross_compiling:
1175            sqlite_inc_paths = []
1176        MIN_SQLITE_VERSION_NUMBER = (3, 0, 8)
1177        MIN_SQLITE_VERSION = ".".join([str(x)
1178                                    for x in MIN_SQLITE_VERSION_NUMBER])
1179
1180        # Scan the default include directories before the SQLite specific
1181        # ones. This allows one to override the copy of sqlite on OSX,
1182        # where /usr/include contains an old version of sqlite.
1183        if host_platform == 'darwin':
1184            sysroot = macosx_sdk_root()
1185
1186        for d_ in inc_dirs + sqlite_inc_paths:
1187            d = d_
1188            if host_platform == 'darwin' and is_macosx_sdk_path(d):
1189                d = os.path.join(sysroot, d[1:])
1190
1191            f = os.path.join(d, "sqlite3.h")
1192            if os.path.exists(f):
1193                if sqlite_setup_debug: print "sqlite: found %s"%f
1194                incf = open(f).read()
1195                m = re.search(
1196                    r'\s*.*#\s*.*define\s.*SQLITE_VERSION\W*"([\d\.]*)"', incf)
1197                if m:
1198                    sqlite_version = m.group(1)
1199                    sqlite_version_tuple = tuple([int(x)
1200                                        for x in sqlite_version.split(".")])
1201                    if sqlite_version_tuple >= MIN_SQLITE_VERSION_NUMBER:
1202                        # we win!
1203                        if sqlite_setup_debug:
1204                            print "%s/sqlite3.h: version %s"%(d, sqlite_version)
1205                        sqlite_incdir = d
1206                        break
1207                    else:
1208                        if sqlite_setup_debug:
1209                            print "%s: version %d is too old, need >= %s"%(d,
1210                                        sqlite_version, MIN_SQLITE_VERSION)
1211                elif sqlite_setup_debug:
1212                    print "sqlite: %s had no SQLITE_VERSION"%(f,)
1213
1214        if sqlite_incdir:
1215            sqlite_dirs_to_check = [
1216                os.path.join(sqlite_incdir, '..', 'lib64'),
1217                os.path.join(sqlite_incdir, '..', 'lib'),
1218                os.path.join(sqlite_incdir, '..', '..', 'lib64'),
1219                os.path.join(sqlite_incdir, '..', '..', 'lib'),
1220            ]
1221            sqlite_libfile = self.compiler.find_library_file(
1222                                sqlite_dirs_to_check + lib_dirs, 'sqlite3')
1223            if sqlite_libfile:
1224                sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))]
1225
1226        if sqlite_incdir and sqlite_libdir:
1227            sqlite_srcs = ['_sqlite/cache.c',
1228                '_sqlite/connection.c',
1229                '_sqlite/cursor.c',
1230                '_sqlite/microprotocols.c',
1231                '_sqlite/module.c',
1232                '_sqlite/prepare_protocol.c',
1233                '_sqlite/row.c',
1234                '_sqlite/statement.c',
1235                '_sqlite/util.c', ]
1236
1237            sqlite_defines = []
1238            if host_platform != "win32":
1239                sqlite_defines.append(('MODULE_NAME', '"sqlite3"'))
1240            else:
1241                sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"'))
1242
1243            # Comment this out if you want the sqlite3 module to be able to load extensions.
1244            sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1"))
1245
1246            if host_platform == 'darwin':
1247                # In every directory on the search path search for a dynamic
1248                # library and then a static library, instead of first looking
1249                # for dynamic libraries on the entire path.
1250                # This way a statically linked custom sqlite gets picked up
1251                # before the dynamic library in /usr/lib.
1252                sqlite_extra_link_args = ('-Wl,-search_paths_first',)
1253            else:
1254                sqlite_extra_link_args = ()
1255
1256            exts.append(Extension('_sqlite3', sqlite_srcs,
1257                                  define_macros=sqlite_defines,
1258                                  include_dirs=["Modules/_sqlite",
1259                                                sqlite_incdir],
1260                                  library_dirs=sqlite_libdir,
1261                                  extra_link_args=sqlite_extra_link_args,
1262                                  libraries=["sqlite3",]))
1263        else:
1264            missing.append('_sqlite3')
1265
1266        # Look for Berkeley db 1.85.   Note that it is built as a different
1267        # module name so it can be included even when later versions are
1268        # available.  A very restrictive search is performed to avoid
1269        # accidentally building this module with a later version of the
1270        # underlying db library.  May BSD-ish Unixes incorporate db 1.85
1271        # symbols into libc and place the include file in /usr/include.
1272        #
1273        # If the better bsddb library can be built (db_incs is defined)
1274        # we do not build this one.  Otherwise this build will pick up
1275        # the more recent berkeleydb's db.h file first in the include path
1276        # when attempting to compile and it will fail.
1277        f = "/usr/include/db.h"
1278
1279        if host_platform == 'darwin':
1280            if is_macosx_sdk_path(f):
1281                sysroot = macosx_sdk_root()
1282                f = os.path.join(sysroot, f[1:])
1283
1284        if os.path.exists(f):
1285            data = open(f).read()
1286            m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data)
1287            if m is not None:
1288                # bingo - old version used hash file format version 2
1289                ### XXX this should be fixed to not be platform-dependent
1290                ### but I don't have direct access to an osf1 platform and
1291                ### seemed to be muffing the search somehow
1292                libraries = host_platform == "osf1" and ['db'] or None
1293                if libraries is not None:
1294                    exts.append(Extension('bsddb185', ['bsddbmodule.c'],
1295                                          libraries=libraries))
1296                else:
1297                    exts.append(Extension('bsddb185', ['bsddbmodule.c']))
1298            else:
1299                missing.append('bsddb185')
1300        else:
1301            missing.append('bsddb185')
1302
1303        dbm_order = ['gdbm']
1304        # The standard Unix dbm module:
1305        if host_platform not in ['cygwin']:
1306            config_args = [arg.strip("'")
1307                           for arg in sysconfig.get_config_var("CONFIG_ARGS").split()]
1308            dbm_args = [arg for arg in config_args
1309                        if arg.startswith('--with-dbmliborder=')]
1310            if dbm_args:
1311                dbm_order = [arg.split('=')[-1] for arg in dbm_args][-1].split(":")
1312            else:
1313                dbm_order = "ndbm:gdbm:bdb".split(":")
1314            dbmext = None
1315            for cand in dbm_order:
1316                if cand == "ndbm":
1317                    if find_file("ndbm.h", inc_dirs, []) is not None:
1318                        # Some systems have -lndbm, others have -lgdbm_compat,
1319                        # others don't have either
1320                        if self.compiler.find_library_file(lib_dirs,
1321                                                               'ndbm'):
1322                            ndbm_libs = ['ndbm']
1323                        elif self.compiler.find_library_file(lib_dirs,
1324                                                             'gdbm_compat'):
1325                            ndbm_libs = ['gdbm_compat']
1326                        else:
1327                            ndbm_libs = []
1328                        print "building dbm using ndbm"
1329                        dbmext = Extension('dbm', ['dbmmodule.c'],
1330                                           define_macros=[
1331                                               ('HAVE_NDBM_H',None),
1332                                               ],
1333                                           libraries=ndbm_libs)
1334                        break
1335
1336                elif cand == "gdbm":
1337                    if self.compiler.find_library_file(lib_dirs, 'gdbm'):
1338                        gdbm_libs = ['gdbm']
1339                        if self.compiler.find_library_file(lib_dirs,
1340                                                               'gdbm_compat'):
1341                            gdbm_libs.append('gdbm_compat')
1342                        if find_file("gdbm/ndbm.h", inc_dirs, []) is not None:
1343                            print "building dbm using gdbm"
1344                            dbmext = Extension(
1345                                'dbm', ['dbmmodule.c'],
1346                                define_macros=[
1347                                    ('HAVE_GDBM_NDBM_H', None),
1348                                    ],
1349                                libraries = gdbm_libs)
1350                            break
1351                        if find_file("gdbm-ndbm.h", inc_dirs, []) is not None:
1352                            print "building dbm using gdbm"
1353                            dbmext = Extension(
1354                                'dbm', ['dbmmodule.c'],
1355                                define_macros=[
1356                                    ('HAVE_GDBM_DASH_NDBM_H', None),
1357                                    ],
1358                                libraries = gdbm_libs)
1359                            break
1360                elif cand == "bdb":
1361                    if db_incs is not None:
1362                        print "building dbm using bdb"
1363                        dbmext = Extension('dbm', ['dbmmodule.c'],
1364                                           library_dirs=dblib_dir,
1365                                           runtime_library_dirs=dblib_dir,
1366                                           include_dirs=db_incs,
1367                                           define_macros=[
1368                                               ('HAVE_BERKDB_H', None),
1369                                               ('DB_DBM_HSEARCH', None),
1370                                               ],
1371                                           libraries=dblibs)
1372                        break
1373            if dbmext is not None:
1374                exts.append(dbmext)
1375            else:
1376                missing.append('dbm')
1377
1378        # Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:
1379        if ('gdbm' in dbm_order and
1380            self.compiler.find_library_file(lib_dirs, 'gdbm')):
1381            exts.append( Extension('gdbm', ['gdbmmodule.c'],
1382                                   libraries = ['gdbm'] ) )
1383        else:
1384            missing.append('gdbm')
1385
1386        # Unix-only modules
1387        if host_platform not in ['win32']:
1388            # Steen Lumholt's termios module
1389            exts.append( Extension('termios', ['termios.c']) )
1390            # Jeremy Hylton's rlimit interface
1391            if host_platform not in ['atheos']:
1392                exts.append( Extension('resource', ['resource.c']) )
1393            else:
1394                missing.append('resource')
1395
1396            nis = self._detect_nis(inc_dirs, lib_dirs)
1397            if nis is not None:
1398                exts.append(nis)
1399            else:
1400                missing.append('nis')
1401
1402        # Curses support, requiring the System V version of curses, often
1403        # provided by the ncurses library.
1404        panel_library = 'panel'
1405        curses_incs = None
1406        if curses_library.startswith('ncurses'):
1407            if curses_library == 'ncursesw':
1408                # Bug 1464056: If _curses.so links with ncursesw,
1409                # _curses_panel.so must link with panelw.
1410                panel_library = 'panelw'
1411            curses_libs = [curses_library]
1412            curses_incs = find_file('curses.h', inc_dirs,
1413                                    [os.path.join(d, 'ncursesw') for d in inc_dirs])
1414            exts.append( Extension('_curses', ['_cursesmodule.c'],
1415                                   include_dirs = curses_incs,
1416                                   libraries = curses_libs) )
1417        elif curses_library == 'curses' and host_platform != 'darwin':
1418                # OSX has an old Berkeley curses, not good enough for
1419                # the _curses module.
1420            if (self.compiler.find_library_file(lib_dirs, 'terminfo')):
1421                curses_libs = ['curses', 'terminfo']
1422            elif (self.compiler.find_library_file(lib_dirs, 'termcap')):
1423                curses_libs = ['curses', 'termcap']
1424            else:
1425                curses_libs = ['curses']
1426
1427            exts.append( Extension('_curses', ['_cursesmodule.c'],
1428                                   libraries = curses_libs) )
1429        else:
1430            missing.append('_curses')
1431
1432        # If the curses module is enabled, check for the panel module
1433        if (module_enabled(exts, '_curses') and
1434            self.compiler.find_library_file(lib_dirs, panel_library)):
1435            exts.append( Extension('_curses_panel', ['_curses_panel.c'],
1436                                   include_dirs = curses_incs,
1437                                   libraries = [panel_library] + curses_libs) )
1438        else:
1439            missing.append('_curses_panel')
1440
1441        # Andrew Kuchling's zlib module.  Note that some versions of zlib
1442        # 1.1.3 have security problems.  See CERT Advisory CA-2002-07:
1443        # http://www.cert.org/advisories/CA-2002-07.html
1444        #
1445        # zlib 1.1.4 is fixed, but at least one vendor (RedHat) has decided to
1446        # patch its zlib 1.1.3 package instead of upgrading to 1.1.4.  For
1447        # now, we still accept 1.1.3, because we think it's difficult to
1448        # exploit this in Python, and we'd rather make it RedHat's problem
1449        # than our problem <wink>.
1450        #
1451        # You can upgrade zlib to version 1.1.4 yourself by going to
1452        # http://www.gzip.org/zlib/
1453        zlib_inc = find_file('zlib.h', [], inc_dirs)
1454        have_zlib = False
1455        if zlib_inc is not None:
1456            zlib_h = zlib_inc[0] + '/zlib.h'
1457            version = '"0.0.0"'
1458            version_req = '"1.1.3"'
1459            if host_platform == 'darwin' and is_macosx_sdk_path(zlib_h):
1460                zlib_h = os.path.join(macosx_sdk_root(), zlib_h[1:])
1461            fp = open(zlib_h)
1462            while 1:
1463                line = fp.readline()
1464                if not line:
1465                    break
1466                if line.startswith('#define ZLIB_VERSION'):
1467                    version = line.split()[2]
1468                    break
1469            if version >= version_req:
1470                if (self.compiler.find_library_file(lib_dirs, 'z')):
1471                    if host_platform == "darwin":
1472                        zlib_extra_link_args = ('-Wl,-search_paths_first',)
1473                    else:
1474                        zlib_extra_link_args = ()
1475                    exts.append( Extension('zlib', ['zlibmodule.c'],
1476                                           libraries = ['z'],
1477                                           extra_link_args = zlib_extra_link_args))
1478                    have_zlib = True
1479                else:
1480                    missing.append('zlib')
1481            else:
1482                missing.append('zlib')
1483        else:
1484            missing.append('zlib')
1485
1486        # Helper module for various ascii-encoders.  Uses zlib for an optimized
1487        # crc32 if we have it.  Otherwise binascii uses its own.
1488        if have_zlib:
1489            extra_compile_args = ['-DUSE_ZLIB_CRC32']
1490            libraries = ['z']
1491            extra_link_args = zlib_extra_link_args
1492        else:
1493            extra_compile_args = []
1494            libraries = []
1495            extra_link_args = []
1496        exts.append( Extension('binascii', ['binascii.c'],
1497                               extra_compile_args = extra_compile_args,
1498                               libraries = libraries,
1499                               extra_link_args = extra_link_args) )
1500
1501        # Gustavo Niemeyer's bz2 module.
1502        if (self.compiler.find_library_file(lib_dirs, 'bz2')):
1503            if host_platform == "darwin":
1504                bz2_extra_link_args = ('-Wl,-search_paths_first',)
1505            else:
1506                bz2_extra_link_args = ()
1507            exts.append( Extension('bz2', ['bz2module.c'],
1508                                   libraries = ['bz2'],
1509                                   extra_link_args = bz2_extra_link_args) )
1510        else:
1511            missing.append('bz2')
1512
1513        # Interface to the Expat XML parser
1514        #
1515        # Expat was written by James Clark and is now maintained by a group of
1516        # developers on SourceForge; see www.libexpat.org for more information.
1517        # The pyexpat module was written by Paul Prescod after a prototype by
1518        # Jack Jansen.  The Expat source is included in Modules/expat/.  Usage
1519        # of a system shared libexpat.so is possible with --with-system-expat
1520        # configure option.
1521        #
1522        # More information on Expat can be found at www.libexpat.org.
1523        #
1524        if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"):
1525            expat_inc = []
1526            define_macros = []
1527            expat_lib = ['expat']
1528            expat_sources = []
1529            expat_depends = []
1530        else:
1531            expat_inc = [os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')]
1532            define_macros = [
1533                ('HAVE_EXPAT_CONFIG_H', '1'),
1534                # bpo-30947: Python uses best available entropy sources to
1535                # call XML_SetHashSalt(), expat entropy sources are not needed
1536                ('XML_POOR_ENTROPY', '1'),
1537            ]
1538            expat_lib = []
1539            expat_sources = ['expat/xmlparse.c',
1540                             'expat/xmlrole.c',
1541                             'expat/xmltok.c']
1542            expat_depends = ['expat/ascii.h',
1543                             'expat/asciitab.h',
1544                             'expat/expat.h',
1545                             'expat/expat_config.h',
1546                             'expat/expat_external.h',
1547                             'expat/internal.h',
1548                             'expat/latin1tab.h',
1549                             'expat/utf8tab.h',
1550                             'expat/xmlrole.h',
1551                             'expat/xmltok.h',
1552                             'expat/xmltok_impl.h'
1553                             ]
1554
1555        exts.append(Extension('pyexpat',
1556                              define_macros = define_macros,
1557                              include_dirs = expat_inc,
1558                              libraries = expat_lib,
1559                              sources = ['pyexpat.c'] + expat_sources,
1560                              depends = expat_depends,
1561                              ))
1562
1563        # Fredrik Lundh's cElementTree module.  Note that this also
1564        # uses expat (via the CAPI hook in pyexpat).
1565
1566        if os.path.isfile(os.path.join(srcdir, 'Modules', '_elementtree.c')):
1567            define_macros.append(('USE_PYEXPAT_CAPI', None))
1568            exts.append(Extension('_elementtree',
1569                                  define_macros = define_macros,
1570                                  include_dirs = expat_inc,
1571                                  libraries = expat_lib,
1572                                  sources = ['_elementtree.c'],
1573                                  depends = ['pyexpat.c'] + expat_sources +
1574                                      expat_depends,
1575                                  ))
1576        else:
1577            missing.append('_elementtree')
1578
1579        # Hye-Shik Chang's CJKCodecs modules.
1580        if have_unicode:
1581            exts.append(Extension('_multibytecodec',
1582                                  ['cjkcodecs/multibytecodec.c']))
1583            for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'):
1584                exts.append(Extension('_codecs_%s' % loc,
1585                                      ['cjkcodecs/_codecs_%s.c' % loc]))
1586        else:
1587            missing.append('_multibytecodec')
1588            for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'):
1589                missing.append('_codecs_%s' % loc)
1590
1591        # Dynamic loading module
1592        if sys.maxint == 0x7fffffff:
1593            # This requires sizeof(int) == sizeof(long) == sizeof(char*)
1594            dl_inc = find_file('dlfcn.h', [], inc_dirs)
1595            if (dl_inc is not None) and (host_platform not in ['atheos']):
1596                exts.append( Extension('dl', ['dlmodule.c']) )
1597            else:
1598                missing.append('dl')
1599        else:
1600            missing.append('dl')
1601
1602        # Thomas Heller's _ctypes module
1603        self.detect_ctypes(inc_dirs, lib_dirs)
1604
1605        # Richard Oudkerk's multiprocessing module
1606        if host_platform == 'win32':             # Windows
1607            macros = dict()
1608            libraries = ['ws2_32']
1609
1610        elif host_platform == 'darwin':          # Mac OSX
1611            macros = dict()
1612            libraries = []
1613
1614        elif host_platform == 'cygwin':          # Cygwin
1615            macros = dict()
1616            libraries = []
1617
1618        elif host_platform.startswith('dragonfly'):
1619            macros = dict()
1620            libraries = ['pthread']
1621
1622        elif host_platform in ('freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'freebsd8'):
1623            # FreeBSD's P1003.1b semaphore support is very experimental
1624            # and has many known problems. (as of June 2008)
1625            macros = dict()
1626            libraries = []
1627
1628        elif host_platform.startswith('openbsd'):
1629            macros = dict()
1630            libraries = []
1631
1632        elif host_platform.startswith('netbsd'):
1633            macros = dict()
1634            libraries = []
1635
1636        else:                                   # Linux and other unices
1637            macros = dict()
1638            libraries = ['rt']
1639
1640        if host_platform == 'win32':
1641            multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c',
1642                                     '_multiprocessing/semaphore.c',
1643                                     '_multiprocessing/pipe_connection.c',
1644                                     '_multiprocessing/socket_connection.c',
1645                                     '_multiprocessing/win32_functions.c'
1646                                   ]
1647
1648        else:
1649            multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c',
1650                                     '_multiprocessing/socket_connection.c'
1651                                   ]
1652            if (sysconfig.get_config_var('HAVE_SEM_OPEN') and not
1653                sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED')):
1654                multiprocessing_srcs.append('_multiprocessing/semaphore.c')
1655
1656        if sysconfig.get_config_var('WITH_THREAD'):
1657            exts.append ( Extension('_multiprocessing', multiprocessing_srcs,
1658                                    define_macros=macros.items(),
1659                                    include_dirs=["Modules/_multiprocessing"]))
1660        else:
1661            missing.append('_multiprocessing')
1662
1663        # End multiprocessing
1664
1665
1666        # Platform-specific libraries
1667        if host_platform == 'linux2':
1668            # Linux-specific modules
1669            exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) )
1670        else:
1671            missing.append('linuxaudiodev')
1672
1673# Initial backport of https://hg.python.org/cpython/rev/50f1922bc1d5
1674
1675        if any(sys.platform.startswith(prefix)
1676               for prefix in ("linux", "dragon", "freebsd", "gnukfreebsd")):
1677            exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
1678        else:
1679            missing.append('ossaudiodev')
1680
1681        if host_platform == 'sunos5':
1682            # SunOS specific modules
1683            exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) )
1684        else:
1685            missing.append('sunaudiodev')
1686
1687        if host_platform == 'darwin':
1688            # _scproxy
1689            exts.append(Extension("_scproxy", [os.path.join(srcdir, "Mac/Modules/_scproxy.c")],
1690                extra_link_args= [
1691                    '-framework', 'SystemConfiguration',
1692                    '-framework', 'CoreFoundation'
1693                ]))
1694
1695
1696        if host_platform == 'darwin' and ("--disable-toolbox-glue" not in
1697                sysconfig.get_config_var("CONFIG_ARGS")):
1698
1699            if int(os.uname()[2].split('.')[0]) >= 8:
1700                # We're on Mac OS X 10.4 or later, the compiler should
1701                # support '-Wno-deprecated-declarations'. This will
1702                # suppress deprecation warnings for the Carbon extensions,
1703                # these extensions wrap the Carbon APIs and even those
1704                # parts that are deprecated.
1705                carbon_extra_compile_args = ['-Wno-deprecated-declarations']
1706            else:
1707                carbon_extra_compile_args = []
1708
1709            # Mac OS X specific modules.
1710            def macSrcExists(name1, name2=''):
1711                if not name1:
1712                    return None
1713                names = (name1,)
1714                if name2:
1715                    names = (name1, name2)
1716                path = os.path.join(srcdir, 'Mac', 'Modules', *names)
1717                return os.path.exists(path)
1718
1719            def addMacExtension(name, kwds, extra_srcs=[]):
1720                dirname = ''
1721                if name[0] == '_':
1722                    dirname = name[1:].lower()
1723                cname = name + '.c'
1724                cmodulename = name + 'module.c'
1725                # Check for NNN.c, NNNmodule.c, _nnn/NNN.c, _nnn/NNNmodule.c
1726                if macSrcExists(cname):
1727                    srcs = [cname]
1728                elif macSrcExists(cmodulename):
1729                    srcs = [cmodulename]
1730                elif macSrcExists(dirname, cname):
1731                    # XXX(nnorwitz): If all the names ended with module, we
1732                    # wouldn't need this condition.  ibcarbon is the only one.
1733                    srcs = [os.path.join(dirname, cname)]
1734                elif macSrcExists(dirname, cmodulename):
1735                    srcs = [os.path.join(dirname, cmodulename)]
1736                else:
1737                    raise RuntimeError("%s not found" % name)
1738
1739                # Here's the whole point:  add the extension with sources
1740                exts.append(Extension(name, srcs + extra_srcs, **kwds))
1741
1742            # Core Foundation
1743            core_kwds = {'extra_compile_args': carbon_extra_compile_args,
1744                         'extra_link_args': ['-framework', 'CoreFoundation'],
1745                        }
1746            addMacExtension('_CF', core_kwds, ['cf/pycfbridge.c'])
1747            addMacExtension('autoGIL', core_kwds)
1748
1749
1750
1751            # Carbon
1752            carbon_kwds = {'extra_compile_args': carbon_extra_compile_args,
1753                           'extra_link_args': ['-framework', 'Carbon'],
1754                          }
1755            CARBON_EXTS = ['ColorPicker', 'gestalt', 'MacOS', 'Nav',
1756                           'OSATerminology', 'icglue',
1757                           # All these are in subdirs
1758                           '_AE', '_AH', '_App', '_CarbonEvt', '_Cm', '_Ctl',
1759                           '_Dlg', '_Drag', '_Evt', '_File', '_Folder', '_Fm',
1760                           '_Help', '_Icn', '_IBCarbon', '_List',
1761                           '_Menu', '_Mlte', '_OSA', '_Res', '_Qd', '_Qdoffs',
1762                           '_Scrap', '_Snd', '_TE',
1763                          ]
1764            for name in CARBON_EXTS:
1765                addMacExtension(name, carbon_kwds)
1766
1767            # Workaround for a bug in the version of gcc shipped with Xcode 3.
1768            # The _Win extension should build just like the other Carbon extensions, but
1769            # this actually results in a hard crash of the linker.
1770            #
1771            if '-arch ppc64' in cflags and '-arch ppc' in cflags:
1772                win_kwds = {'extra_compile_args': carbon_extra_compile_args + ['-arch', 'i386', '-arch', 'ppc'],
1773                               'extra_link_args': ['-framework', 'Carbon', '-arch', 'i386', '-arch', 'ppc'],
1774                           }
1775                addMacExtension('_Win', win_kwds)
1776            else:
1777                addMacExtension('_Win', carbon_kwds)
1778
1779
1780            # Application Services & QuickTime
1781            app_kwds = {'extra_compile_args': carbon_extra_compile_args,
1782                        'extra_link_args': ['-framework','ApplicationServices'],
1783                       }
1784            addMacExtension('_Launch', app_kwds)
1785            addMacExtension('_CG', app_kwds)
1786
1787            exts.append( Extension('_Qt', ['qt/_Qtmodule.c'],
1788                        extra_compile_args=carbon_extra_compile_args,
1789                        extra_link_args=['-framework', 'QuickTime',
1790                                     '-framework', 'Carbon']) )
1791
1792
1793        self.extensions.extend(exts)
1794
1795        # Call the method for detecting whether _tkinter can be compiled
1796        self.detect_tkinter(inc_dirs, lib_dirs)
1797
1798        if '_tkinter' not in [e.name for e in self.extensions]:
1799            missing.append('_tkinter')
1800
1801##         # Uncomment these lines if you want to play with xxmodule.c
1802##         ext = Extension('xx', ['xxmodule.c'])
1803##         self.extensions.append(ext)
1804
1805        return missing
1806
1807    def detect_tkinter_explicitly(self):
1808        # Build _tkinter using explicit locations for Tcl/Tk.
1809        #
1810        # This is enabled when both arguments are given to ./configure:
1811        #
1812        #     --with-tcltk-includes="-I/path/to/tclincludes \
1813        #                            -I/path/to/tkincludes"
1814        #     --with-tcltk-libs="-L/path/to/tcllibs -ltclm.n \
1815        #                        -L/path/to/tklibs -ltkm.n"
1816        #
1817        # These values can also be specified or overridden via make:
1818        #    make TCLTK_INCLUDES="..." TCLTK_LIBS="..."
1819        #
1820        # This can be useful for building and testing tkinter with multiple
1821        # versions of Tcl/Tk.  Note that a build of Tk depends on a particular
1822        # build of Tcl so you need to specify both arguments and use care when
1823        # overriding.
1824
1825        # The _TCLTK variables are created in the Makefile sharedmods target.
1826        tcltk_includes = os.environ.get('_TCLTK_INCLUDES')
1827        tcltk_libs = os.environ.get('_TCLTK_LIBS')
1828        if not (tcltk_includes and tcltk_libs):
1829            # Resume default configuration search.
1830            return 0
1831
1832        extra_compile_args = tcltk_includes.split()
1833        extra_link_args = tcltk_libs.split()
1834        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1835                        define_macros=[('WITH_APPINIT', 1)],
1836                        extra_compile_args = extra_compile_args,
1837                        extra_link_args = extra_link_args,
1838                        )
1839        self.extensions.append(ext)
1840        return 1
1841
1842    def detect_tkinter_darwin(self, inc_dirs, lib_dirs):
1843        # The _tkinter module, using frameworks. Since frameworks are quite
1844        # different the UNIX search logic is not sharable.
1845        from os.path import join, exists
1846        framework_dirs = [
1847            '/Library/Frameworks',
1848            '/System/Library/Frameworks/',
1849            join(os.getenv('HOME'), '/Library/Frameworks')
1850        ]
1851
1852        sysroot = macosx_sdk_root()
1853
1854        # Find the directory that contains the Tcl.framework and Tk.framework
1855        # bundles.
1856        # XXX distutils should support -F!
1857        for F in framework_dirs:
1858            # both Tcl.framework and Tk.framework should be present
1859
1860
1861            for fw in 'Tcl', 'Tk':
1862                if is_macosx_sdk_path(F):
1863                    if not exists(join(sysroot, F[1:], fw + '.framework')):
1864                        break
1865                else:
1866                    if not exists(join(F, fw + '.framework')):
1867                        break
1868            else:
1869                # ok, F is now directory with both frameworks. Continure
1870                # building
1871                break
1872        else:
1873            # Tk and Tcl frameworks not found. Normal "unix" tkinter search
1874            # will now resume.
1875            return 0
1876
1877        # For 8.4a2, we must add -I options that point inside the Tcl and Tk
1878        # frameworks. In later release we should hopefully be able to pass
1879        # the -F option to gcc, which specifies a framework lookup path.
1880        #
1881        include_dirs = [
1882            join(F, fw + '.framework', H)
1883            for fw in 'Tcl', 'Tk'
1884            for H in 'Headers', 'Versions/Current/PrivateHeaders'
1885        ]
1886
1887        # For 8.4a2, the X11 headers are not included. Rather than include a
1888        # complicated search, this is a hard-coded path. It could bail out
1889        # if X11 libs are not found...
1890        include_dirs.append('/usr/X11R6/include')
1891        frameworks = ['-framework', 'Tcl', '-framework', 'Tk']
1892
1893        # All existing framework builds of Tcl/Tk don't support 64-bit
1894        # architectures.
1895        cflags = sysconfig.get_config_vars('CFLAGS')[0]
1896        archs = re.findall('-arch\s+(\w+)', cflags)
1897
1898        if is_macosx_sdk_path(F):
1899            fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(os.path.join(sysroot, F[1:]),))
1900        else:
1901            fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(F,))
1902
1903        detected_archs = []
1904        for ln in fp:
1905            a = ln.split()[-1]
1906            if a in archs:
1907                detected_archs.append(ln.split()[-1])
1908        fp.close()
1909
1910        for a in detected_archs:
1911            frameworks.append('-arch')
1912            frameworks.append(a)
1913
1914        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1915                        define_macros=[('WITH_APPINIT', 1)],
1916                        include_dirs = include_dirs,
1917                        libraries = [],
1918                        extra_compile_args = frameworks[2:],
1919                        extra_link_args = frameworks,
1920                        )
1921        self.extensions.append(ext)
1922        return 1
1923
1924    def detect_tkinter(self, inc_dirs, lib_dirs):
1925        # The _tkinter module.
1926
1927        # Check whether --with-tcltk-includes and --with-tcltk-libs were
1928        # configured or passed into the make target.  If so, use these values
1929        # to build tkinter and bypass the searches for Tcl and TK in standard
1930        # locations.
1931        if self.detect_tkinter_explicitly():
1932            return
1933
1934        # Rather than complicate the code below, detecting and building
1935        # AquaTk is a separate method. Only one Tkinter will be built on
1936        # Darwin - either AquaTk, if it is found, or X11 based Tk.
1937        if (host_platform == 'darwin' and
1938            self.detect_tkinter_darwin(inc_dirs, lib_dirs)):
1939            return
1940
1941        # Assume we haven't found any of the libraries or include files
1942        # The versions with dots are used on Unix, and the versions without
1943        # dots on Windows, for detection by cygwin.
1944        tcllib = tklib = tcl_includes = tk_includes = None
1945        for version in ['8.6', '86', '8.5', '85', '8.4', '84', '8.3', '83',
1946                        '8.2', '82', '8.1', '81', '8.0', '80']:
1947            tklib = self.compiler.find_library_file(lib_dirs,
1948                                                        'tk' + version)
1949            tcllib = self.compiler.find_library_file(lib_dirs,
1950                                                         'tcl' + version)
1951            if tklib and tcllib:
1952                # Exit the loop when we've found the Tcl/Tk libraries
1953                break
1954
1955        # Now check for the header files
1956        if tklib and tcllib:
1957            # Check for the include files on Debian and {Free,Open}BSD, where
1958            # they're put in /usr/include/{tcl,tk}X.Y
1959            dotversion = version
1960            if '.' not in dotversion and "bsd" in host_platform.lower():
1961                # OpenBSD and FreeBSD use Tcl/Tk library names like libtcl83.a,
1962                # but the include subdirs are named like .../include/tcl8.3.
1963                dotversion = dotversion[:-1] + '.' + dotversion[-1]
1964            tcl_include_sub = []
1965            tk_include_sub = []
1966            for dir in inc_dirs:
1967                tcl_include_sub += [dir + os.sep + "tcl" + dotversion]
1968                tk_include_sub += [dir + os.sep + "tk" + dotversion]
1969            tk_include_sub += tcl_include_sub
1970            tcl_includes = find_file('tcl.h', inc_dirs, tcl_include_sub)
1971            tk_includes = find_file('tk.h', inc_dirs, tk_include_sub)
1972
1973        if (tcllib is None or tklib is None or
1974            tcl_includes is None or tk_includes is None):
1975            self.announce("INFO: Can't locate Tcl/Tk libs and/or headers", 2)
1976            return
1977
1978        # OK... everything seems to be present for Tcl/Tk.
1979
1980        include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = []
1981        for dir in tcl_includes + tk_includes:
1982            if dir not in include_dirs:
1983                include_dirs.append(dir)
1984
1985        # Check for various platform-specific directories
1986        if host_platform == 'sunos5':
1987            include_dirs.append('/usr/openwin/include')
1988            added_lib_dirs.append('/usr/openwin/lib')
1989        elif os.path.exists('/usr/X11R6/include'):
1990            include_dirs.append('/usr/X11R6/include')
1991            added_lib_dirs.append('/usr/X11R6/lib64')
1992            added_lib_dirs.append('/usr/X11R6/lib')
1993        elif os.path.exists('/usr/X11R5/include'):
1994            include_dirs.append('/usr/X11R5/include')
1995            added_lib_dirs.append('/usr/X11R5/lib')
1996        else:
1997            # Assume default location for X11
1998            include_dirs.append('/usr/X11/include')
1999            added_lib_dirs.append('/usr/X11/lib')
2000
2001        # If Cygwin, then verify that X is installed before proceeding
2002        if host_platform == 'cygwin':
2003            x11_inc = find_file('X11/Xlib.h', [], include_dirs)
2004            if x11_inc is None:
2005                return
2006
2007        # Check for BLT extension
2008        if self.compiler.find_library_file(lib_dirs + added_lib_dirs,
2009                                               'BLT8.0'):
2010            defs.append( ('WITH_BLT', 1) )
2011            libs.append('BLT8.0')
2012        elif self.compiler.find_library_file(lib_dirs + added_lib_dirs,
2013                                                'BLT'):
2014            defs.append( ('WITH_BLT', 1) )
2015            libs.append('BLT')
2016
2017        # Add the Tcl/Tk libraries
2018        libs.append('tk'+ version)
2019        libs.append('tcl'+ version)
2020
2021        if host_platform in ['aix3', 'aix4']:
2022            libs.append('ld')
2023
2024        # Finally, link with the X11 libraries (not appropriate on cygwin)
2025        if host_platform != "cygwin":
2026            libs.append('X11')
2027
2028        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
2029                        define_macros=[('WITH_APPINIT', 1)] + defs,
2030                        include_dirs = include_dirs,
2031                        libraries = libs,
2032                        library_dirs = added_lib_dirs,
2033                        )
2034        self.extensions.append(ext)
2035
2036        # XXX handle these, but how to detect?
2037        # *** Uncomment and edit for PIL (TkImaging) extension only:
2038        #       -DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \
2039        # *** Uncomment and edit for TOGL extension only:
2040        #       -DWITH_TOGL togl.c \
2041        # *** Uncomment these for TOGL extension only:
2042        #       -lGL -lGLU -lXext -lXmu \
2043
2044    def configure_ctypes_darwin(self, ext):
2045        # Darwin (OS X) uses preconfigured files, in
2046        # the Modules/_ctypes/libffi_osx directory.
2047        srcdir = sysconfig.get_config_var('srcdir')
2048        ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
2049                                                  '_ctypes', 'libffi_osx'))
2050        sources = [os.path.join(ffi_srcdir, p)
2051                   for p in ['ffi.c',
2052                             'x86/darwin64.S',
2053                             'x86/x86-darwin.S',
2054                             'x86/x86-ffi_darwin.c',
2055                             'x86/x86-ffi64.c',
2056                             'powerpc/ppc-darwin.S',
2057                             'powerpc/ppc-darwin_closure.S',
2058                             'powerpc/ppc-ffi_darwin.c',
2059                             'powerpc/ppc64-darwin_closure.S',
2060                             ]]
2061
2062        # Add .S (preprocessed assembly) to C compiler source extensions.
2063        self.compiler.src_extensions.append('.S')
2064
2065        include_dirs = [os.path.join(ffi_srcdir, 'include'),
2066                        os.path.join(ffi_srcdir, 'powerpc')]
2067        ext.include_dirs.extend(include_dirs)
2068        ext.sources.extend(sources)
2069        return True
2070
2071    def configure_ctypes(self, ext):
2072        if not self.use_system_libffi:
2073            if host_platform == 'darwin':
2074                return self.configure_ctypes_darwin(ext)
2075
2076            srcdir = sysconfig.get_config_var('srcdir')
2077            ffi_builddir = os.path.join(self.build_temp, 'libffi')
2078            ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
2079                                         '_ctypes', 'libffi'))
2080            ffi_configfile = os.path.join(ffi_builddir, 'fficonfig.py')
2081
2082            from distutils.dep_util import newer_group
2083
2084            config_sources = [os.path.join(ffi_srcdir, fname)
2085                              for fname in os.listdir(ffi_srcdir)
2086                              if os.path.isfile(os.path.join(ffi_srcdir, fname))]
2087            if self.force or newer_group(config_sources,
2088                                         ffi_configfile):
2089                from distutils.dir_util import mkpath
2090                mkpath(ffi_builddir)
2091                config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split()
2092                               if (('--host=' in arg) or ('--build=' in arg))]
2093                if not self.verbose:
2094                    config_args.append("-q")
2095
2096                # Pass empty CFLAGS because we'll just append the resulting
2097                # CFLAGS to Python's; -g or -O2 is to be avoided.
2098                cmd = "cd %s && env CFLAGS='' '%s/configure' %s" \
2099                      % (ffi_builddir, ffi_srcdir, " ".join(config_args))
2100
2101                res = os.system(cmd)
2102                if res or not os.path.exists(ffi_configfile):
2103                    print "Failed to configure _ctypes module"
2104                    return False
2105
2106            fficonfig = {}
2107            with open(ffi_configfile) as f:
2108                exec f in fficonfig
2109
2110            # Add .S (preprocessed assembly) to C compiler source extensions.
2111            self.compiler.src_extensions.append('.S')
2112
2113            include_dirs = [os.path.join(ffi_builddir, 'include'),
2114                            ffi_builddir,
2115                            os.path.join(ffi_srcdir, 'src')]
2116            extra_compile_args = fficonfig['ffi_cflags'].split()
2117
2118            ext.sources.extend(os.path.join(ffi_srcdir, f) for f in
2119                               fficonfig['ffi_sources'])
2120            ext.include_dirs.extend(include_dirs)
2121            ext.extra_compile_args.extend(extra_compile_args)
2122        return True
2123
2124    def detect_ctypes(self, inc_dirs, lib_dirs):
2125        self.use_system_libffi = False
2126        include_dirs = []
2127        extra_compile_args = []
2128        extra_link_args = []
2129        sources = ['_ctypes/_ctypes.c',
2130                   '_ctypes/callbacks.c',
2131                   '_ctypes/callproc.c',
2132                   '_ctypes/stgdict.c',
2133                   '_ctypes/cfield.c']
2134        depends = ['_ctypes/ctypes.h']
2135
2136        if host_platform == 'darwin':
2137            sources.append('_ctypes/malloc_closure.c')
2138            sources.append('_ctypes/darwin/dlfcn_simple.c')
2139            extra_compile_args.append('-DMACOSX')
2140            include_dirs.append('_ctypes/darwin')
2141# XXX Is this still needed?
2142##            extra_link_args.extend(['-read_only_relocs', 'warning'])
2143
2144        elif host_platform == 'sunos5':
2145            # XXX This shouldn't be necessary; it appears that some
2146            # of the assembler code is non-PIC (i.e. it has relocations
2147            # when it shouldn't. The proper fix would be to rewrite
2148            # the assembler code to be PIC.
2149            # This only works with GCC; the Sun compiler likely refuses
2150            # this option. If you want to compile ctypes with the Sun
2151            # compiler, please research a proper solution, instead of
2152            # finding some -z option for the Sun compiler.
2153            extra_link_args.append('-mimpure-text')
2154
2155        elif host_platform.startswith('hp-ux'):
2156            extra_link_args.append('-fPIC')
2157
2158        ext = Extension('_ctypes',
2159                        include_dirs=include_dirs,
2160                        extra_compile_args=extra_compile_args,
2161                        extra_link_args=extra_link_args,
2162                        libraries=[],
2163                        sources=sources,
2164                        depends=depends)
2165        ext_test = Extension('_ctypes_test',
2166                             sources=['_ctypes/_ctypes_test.c'])
2167        self.extensions.extend([ext, ext_test])
2168
2169        if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
2170            return
2171
2172        if host_platform == 'darwin':
2173            # OS X 10.5 comes with libffi.dylib; the include files are
2174            # in /usr/include/ffi
2175            inc_dirs.append('/usr/include/ffi')
2176
2177        ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
2178        if not ffi_inc or ffi_inc[0] == '':
2179            ffi_inc = find_file('ffi.h', [], inc_dirs)
2180        if ffi_inc is not None:
2181            ffi_h = ffi_inc[0] + '/ffi.h'
2182            with open(ffi_h) as f:
2183                for line in f:
2184                    line = line.strip()
2185                    if line.startswith(('#define LIBFFI_H',
2186                                        '#define ffi_wrapper_h')):
2187                        break
2188                else:
2189                    ffi_inc = None
2190                    print('Header file {} does not define LIBFFI_H or '
2191                          'ffi_wrapper_h'.format(ffi_h))
2192        ffi_lib = None
2193        if ffi_inc is not None:
2194            for lib_name in ('ffi_convenience', 'ffi_pic', 'ffi'):
2195                if (self.compiler.find_library_file(lib_dirs, lib_name)):
2196                    ffi_lib = lib_name
2197                    break
2198
2199        if ffi_inc and ffi_lib:
2200            ext.include_dirs.extend(ffi_inc)
2201            ext.libraries.append(ffi_lib)
2202            self.use_system_libffi = True
2203
2204        if sysconfig.get_config_var('HAVE_LIBDL'):
2205            # for dlopen, see bpo-32647
2206            ext.libraries.append('dl')
2207
2208    def _detect_nis(self, inc_dirs, lib_dirs):
2209        if host_platform in {'win32', 'cygwin', 'qnx6'}:
2210            return None
2211
2212        libs = []
2213        library_dirs = []
2214        includes_dirs = []
2215
2216        # bpo-32521: glibc has deprecated Sun RPC for some time. Fedora 28
2217        # moved headers and libraries to libtirpc and libnsl. The headers
2218        # are in tircp and nsl sub directories.
2219        rpcsvc_inc = find_file(
2220            'rpcsvc/yp_prot.h', inc_dirs,
2221            [os.path.join(inc_dir, 'nsl') for inc_dir in inc_dirs]
2222        )
2223        rpc_inc = find_file(
2224            'rpc/rpc.h', inc_dirs,
2225            [os.path.join(inc_dir, 'tirpc') for inc_dir in inc_dirs]
2226        )
2227        if rpcsvc_inc is None or rpc_inc is None:
2228            # not found
2229            return None
2230        includes_dirs.extend(rpcsvc_inc)
2231        includes_dirs.extend(rpc_inc)
2232
2233        if self.compiler.find_library_file(lib_dirs, 'nsl'):
2234            libs.append('nsl')
2235        else:
2236            # libnsl-devel: check for libnsl in nsl/ subdirectory
2237            nsl_dirs = [os.path.join(lib_dir, 'nsl') for lib_dir in lib_dirs]
2238            libnsl = self.compiler.find_library_file(nsl_dirs, 'nsl')
2239            if libnsl is not None:
2240                library_dirs.append(os.path.dirname(libnsl))
2241                libs.append('nsl')
2242
2243        if self.compiler.find_library_file(lib_dirs, 'tirpc'):
2244            libs.append('tirpc')
2245
2246        return Extension(
2247            'nis', ['nismodule.c'],
2248            libraries=libs,
2249            library_dirs=library_dirs,
2250            include_dirs=includes_dirs
2251        )
2252
2253
2254class PyBuildInstall(install):
2255    # Suppress the warning about installation into the lib_dynload
2256    # directory, which is not in sys.path when running Python during
2257    # installation:
2258    def initialize_options (self):
2259        install.initialize_options(self)
2260        self.warn_dir=0
2261
2262class PyBuildInstallLib(install_lib):
2263    # Do exactly what install_lib does but make sure correct access modes get
2264    # set on installed directories and files. All installed files with get
2265    # mode 644 unless they are a shared library in which case they will get
2266    # mode 755. All installed directories will get mode 755.
2267
2268    so_ext = sysconfig.get_config_var("SO")
2269
2270    def install(self):
2271        outfiles = install_lib.install(self)
2272        self.set_file_modes(outfiles, 0644, 0755)
2273        self.set_dir_modes(self.install_dir, 0755)
2274        return outfiles
2275
2276    def set_file_modes(self, files, defaultMode, sharedLibMode):
2277        if not self.is_chmod_supported(): return
2278        if not files: return
2279
2280        for filename in files:
2281            if os.path.islink(filename): continue
2282            mode = defaultMode
2283            if filename.endswith(self.so_ext): mode = sharedLibMode
2284            log.info("changing mode of %s to %o", filename, mode)
2285            if not self.dry_run: os.chmod(filename, mode)
2286
2287    def set_dir_modes(self, dirname, mode):
2288        if not self.is_chmod_supported(): return
2289        os.path.walk(dirname, self.set_dir_modes_visitor, mode)
2290
2291    def set_dir_modes_visitor(self, mode, dirname, names):
2292        if os.path.islink(dirname): return
2293        log.info("changing mode of %s to %o", dirname, mode)
2294        if not self.dry_run: os.chmod(dirname, mode)
2295
2296    def is_chmod_supported(self):
2297        return hasattr(os, 'chmod')
2298
2299class PyBuildScripts(build_scripts):
2300    def copy_scripts(self):
2301        outfiles = build_scripts.copy_scripts(self)
2302        fullversion =  '-legacy' #'{0[0]}.{0[1]}'.format(sys.version_info)
2303        newoutfiles = []
2304        for filename in outfiles:
2305            if filename.endswith('2to3'):
2306                newfilename = filename + '-' + fullversion
2307            else:
2308                newfilename = filename + fullversion
2309            log.info('renaming {} to {}'.format(filename, newfilename))
2310            os.rename(filename, newfilename)
2311            newoutfiles.append(newfilename)
2312        return newoutfiles
2313
2314
2315SUMMARY = """
2316Python is an interpreted, interactive, object-oriented programming
2317language. It is often compared to Tcl, Perl, Scheme or Java.
2318
2319Python combines remarkable power with very clear syntax. It has
2320modules, classes, exceptions, very high level dynamic data types, and
2321dynamic typing. There are interfaces to many system calls and
2322libraries, as well as to various windowing systems (X11, Motif, Tk,
2323Mac, MFC). New built-in modules are easily written in C or C++. Python
2324is also usable as an extension language for applications that need a
2325programmable interface.
2326
2327The Python implementation is portable: it runs on many brands of UNIX,
2328on Windows, DOS, OS/2, Mac, Amiga... If your favorite system isn't
2329listed here, it may still be supported, if there's a C compiler for
2330it. Ask around on comp.lang.python -- or just try compiling Python
2331yourself.
2332"""
2333
2334CLASSIFIERS = """
2335Development Status :: 6 - Mature
2336License :: OSI Approved :: Python Software Foundation License
2337Natural Language :: English
2338Programming Language :: C
2339Programming Language :: Python
2340Topic :: Software Development
2341"""
2342
2343def main():
2344    # turn off warnings when deprecated modules are imported
2345    import warnings
2346    warnings.filterwarnings("ignore",category=DeprecationWarning)
2347    setup(# PyPI Metadata (PEP 301)
2348          name = "Python",
2349          version = sys.version.split()[0],
2350          url = "http://www.python.org/%s" % sys.version[:3],
2351          maintainer = "Guido van Rossum and the Python community",
2352          maintainer_email = "python-dev@python.org",
2353          description = "A high-level object-oriented programming language",
2354          long_description = SUMMARY.strip(),
2355          license = "PSF license",
2356          classifiers = filter(None, CLASSIFIERS.split("\n")),
2357          platforms = ["Many"],
2358
2359          # Build info
2360          cmdclass = {'build_ext':PyBuildExt,
2361                      'build_scripts':PyBuildScripts,
2362                      'install':PyBuildInstall,
2363                      'install_lib':PyBuildInstallLib},
2364          # The struct module is defined here, because build_ext won't be
2365          # called unless there's at least one extension module defined.
2366          ext_modules=[Extension('_struct', ['_struct.c'])],
2367
2368          # Scripts to install
2369          scripts = ['Tools/scripts/pydoc', 'Tools/scripts/idle',
2370                     'Tools/scripts/2to3']
2371        )
2372
2373# --install-platlib
2374if __name__ == '__main__':
2375    main()
2376