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