diff --git a/setup.py b/setup.py index b04208602f3b9a..22d67ea530dbb2 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,17 @@ # Autodetecting setup.py script for building the Python extensions -# -import sys, os, importlib.machinery, re, argparse -from glob import glob +import argparse import importlib._bootstrap +import importlib.machinery import importlib.util +import os +import re +import sys import sysconfig +from glob import glob from distutils import log -from distutils.errors import * +from distutils.errors import CCompilerError, DistutilsError from distutils.core import Extension, setup from distutils.command.build_ext import build_ext from distutils.command.install import install @@ -16,23 +19,6 @@ from distutils.command.build_scripts import build_scripts from distutils.spawn import find_executable -cross_compiling = "_PYTHON_HOST_PLATFORM" in os.environ - -# Set common compiler and linker flags derived from the Makefile, -# reserved for building the interpreter and the stdlib modules. -# See bpo-21121 and bpo-35257 -def set_compiler_flags(compiler_flags, compiler_py_flags_nodist): - flags = sysconfig.get_config_var(compiler_flags) - py_flags_nodist = sysconfig.get_config_var(compiler_py_flags_nodist) - sysconfig.get_config_vars()[compiler_flags] = flags + ' ' + py_flags_nodist - -set_compiler_flags('CFLAGS', 'PY_CFLAGS_NODIST') -set_compiler_flags('LDFLAGS', 'PY_LDFLAGS_NODIST') - -class Dummy: - """Hack for parallel build""" - ProcessPoolExecutor = None -sys.modules['concurrent.futures.process'] = Dummy def get_platform(): # cross build @@ -42,15 +28,67 @@ def get_platform(): if sys.platform.startswith('osf1'): return 'osf1' return sys.platform -host_platform = get_platform() -VXWORKS = ('vxworks' in host_platform) + +# Compile extensions used to test Python? +TEST_EXTENSIONS = True +# Math library needed to get floor() or sqrt() functions +MATH_LIBS = ['m'] +CROSS_COMPILING = ("_PYTHON_HOST_PLATFORM" in os.environ) +HOST_PLATFORM = get_platform() +MACOS = (HOST_PLATFORM == 'darwin') +MS_WINDOWS = (HOST_PLATFORM == 'win32') +CYGWIN = (HOST_PLATFORM == 'cygwin') +VXWORKS = ('vxworks' in HOST_PLATFORM) # Were we compiled --with-pydebug or with #define Py_DEBUG? COMPILED_WITH_PYDEBUG = ('--with-pydebug' in sysconfig.get_config_var("CONFIG_ARGS")) # This global variable is used to hold the list of modules to be disabled. -disabled_module_list = [] +DISABLED_MODULE_LIST = [] + +SUMMARY = """ +Python is an interpreted, interactive, object-oriented programming +language. It is often compared to Tcl, Perl, Scheme or Java. + +Python combines remarkable power with very clear syntax. It has +modules, classes, exceptions, very high level dynamic data types, and +dynamic typing. There are interfaces to many system calls and +libraries, as well as to various windowing systems (X11, Motif, Tk, +Mac, MFC). New built-in modules are easily written in C or C++. Python +is also usable as an extension language for applications that need a +programmable interface. + +The Python implementation is portable: it runs on many brands of UNIX, +on Windows, DOS, Mac, Amiga... If your favorite system isn't +listed here, it may still be supported, if there's a C compiler for +it. Ask around on comp.lang.python -- or just try compiling Python +yourself. +""" + +CLASSIFIERS = """ +Development Status :: 6 - Mature +License :: OSI Approved :: Python Software Foundation License +Natural Language :: English +Programming Language :: C +Programming Language :: Python +Topic :: Software Development +""" + + +# Set common compiler and linker flags derived from the Makefile, +# reserved for building the interpreter and the stdlib modules. +# See bpo-21121 and bpo-35257 +def set_compiler_flags(compiler_flags, compiler_py_flags_nodist): + flags = sysconfig.get_config_var(compiler_flags) + py_flags_nodist = sysconfig.get_config_var(compiler_py_flags_nodist) + sysconfig.get_config_vars()[compiler_flags] = flags + ' ' + py_flags_nodist + + +class DummyProcess: + """Hack for parallel build""" + ProcessPoolExecutor = None + def add_dir_to_list(dirlist, dir): """Add the directory 'dir' to the list 'dirlist' (after any relative @@ -67,6 +105,7 @@ def add_dir_to_list(dirlist, dir): return dirlist.insert(0, dir) + def sysroot_paths(make_vars, subdirs): """Get the paths of sysroot sub-directories. @@ -92,6 +131,7 @@ def sysroot_paths(make_vars, subdirs): break return dirs + def macosx_sdk_root(): """ Return the directory of the current OSX SDK, @@ -105,6 +145,7 @@ def macosx_sdk_root(): sysroot = m.group(1) return sysroot + def is_macosx_sdk_path(path): """ Returns True if 'path' can be located in an OSX SDK @@ -113,6 +154,7 @@ def is_macosx_sdk_path(path): or path.startswith('/System/') or path.startswith('/Library/') ) + def find_file(filename, std_dirs, paths): """Searches for the directory where a given file is located, and returns a possibly-empty list of additional directories, or None @@ -124,7 +166,7 @@ def find_file(filename, std_dirs, paths): 'paths' is a list of additional locations to check; if the file is found in one of them, the resulting list will contain the directory. """ - if host_platform == 'darwin': + if MACOS: # Honor the MacOSX SDK setting when one was specified. # An SDK is a directory with the same structure as a real # system, but with only header files and libraries. @@ -134,7 +176,7 @@ def find_file(filename, std_dirs, paths): for dir in std_dirs: f = os.path.join(dir, filename) - if host_platform == 'darwin' and is_macosx_sdk_path(dir): + if MACOS and is_macosx_sdk_path(dir): f = os.path.join(sysroot, dir[1:], filename) if os.path.exists(f): return [] @@ -143,7 +185,7 @@ def find_file(filename, std_dirs, paths): for dir in paths: f = os.path.join(dir, filename) - if host_platform == 'darwin' and is_macosx_sdk_path(dir): + if MACOS and is_macosx_sdk_path(dir): f = os.path.join(sysroot, dir[1:], filename) if os.path.exists(f): @@ -152,12 +194,13 @@ def find_file(filename, std_dirs, paths): # Not found anywhere return None + def find_library_file(compiler, libname, std_dirs, paths): result = compiler.find_library_file(std_dirs + paths, libname) if result is None: return None - if host_platform == 'darwin': + if MACOS: sysroot = macosx_sdk_root() # Check whether the found file is in one of the standard directories @@ -166,7 +209,7 @@ def find_library_file(compiler, libname, std_dirs, paths): # Ensure path doesn't end with path separator p = p.rstrip(os.sep) - if host_platform == 'darwin' and is_macosx_sdk_path(p): + if MACOS and is_macosx_sdk_path(p): # Note that, as of Xcode 7, Apple SDKs may contain textual stub # libraries with .tbd extensions rather than the normal .dylib # shared libraries installed in /. The Apple compiler tool @@ -195,7 +238,7 @@ def find_library_file(compiler, libname, std_dirs, paths): # Ensure path doesn't end with path separator p = p.rstrip(os.sep) - if host_platform == 'darwin' and is_macosx_sdk_path(p): + if MACOS and is_macosx_sdk_path(p): if os.path.join(sysroot, p[1:]) == dirname: return [ p ] @@ -210,6 +253,7 @@ def module_enabled(extlist, modname): extlist = [ext for ext in extlist if ext.name == modname] return len(extlist) + def find_module_file(module, dirlist): """Find a module in a set of possible folders. If it is not found return the unadorned filename""" @@ -220,23 +264,37 @@ def find_module_file(module, dirlist): log.info("WARNING: multiple copies of %s found", module) return os.path.join(list[0], module) + class PyBuildExt(build_ext): def __init__(self, dist): build_ext.__init__(self, dist) self.failed = [] self.failed_on_import = [] + self.missing = [] + self.srcdir = None + self.config_h_vars = None + self.inc_dirs = None + self.lib_dirs = None if '-j' in os.environ.get('MAKEFLAGS', ''): self.parallel = True + def add_ext(self, ext): + self.extensions.append(ext) + def build_extensions(self): + self.srcdir = sysconfig.get_config_var('srcdir') + if not self.srcdir: + # Maybe running on Windows but not using CYGWIN? + raise ValueError("No source directory; cannot proceed.") + self.srcdir = os.path.abspath(self.srcdir) # Detect which modules should be compiled - missing = self.detect_modules() + self.detect_modules() # Remove modules that are present on the disabled list extensions = [ext for ext in self.extensions - if ext.name not in disabled_module_list] + if ext.name not in DISABLED_MODULE_LIST] # move ctypes to the end, it depends on other modules ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) if "_ctypes" in ext_map: @@ -246,15 +304,10 @@ def build_extensions(self): # Fix up the autodetected modules, prefixing all the source files # with Modules/. - srcdir = sysconfig.get_config_var('srcdir') - if not srcdir: - # Maybe running on Windows but not using CYGWIN? - raise ValueError("No source directory; cannot proceed.") - srcdir = os.path.abspath(srcdir) - moddirlist = [os.path.join(srcdir, 'Modules')] + moddirlist = [os.path.join(self.srcdir, 'Modules')] # Fix up the paths for scripts, too - self.distribution.scripts = [os.path.join(srcdir, filename) + self.distribution.scripts = [os.path.join(self.srcdir, filename) for filename in self.distribution.scripts] # Python header files @@ -328,12 +381,12 @@ def print_three_column(lst): print("%-*s %-*s %-*s" % (longest, e, longest, f, longest, g)) - if missing: + if self.missing: print() print("Python build finished successfully!") print("The necessary bits to build these optional modules were not " "found:") - print_three_column(missing) + print_three_column(self.missing) print("To find the necessary bits, look in setup.py in" " detect_modules() for the module's name.") print() @@ -371,7 +424,7 @@ def print_three_column(lst): print() if any('_ssl' in l - for l in (missing, self.failed, self.failed_on_import)): + for l in (self.missing, self.failed, self.failed_on_import)): print() print("Could not build the ssl module!") print("Python requires an OpenSSL 1.0.2 or 1.1 compatible " @@ -389,9 +442,9 @@ def build_extension(self, ext): try: build_ext.build_extension(self, ext) - except (CCompilerError, DistutilsError) as why: + except (CCompilerError, DistutilsError) as exc: self.announce('WARNING: building of extension "%s" failed: %s' % - (ext.name, sys.exc_info()[1])) + (ext.name, exc)) self.failed.append(ext.name) return @@ -411,7 +464,7 @@ def check_extension_import(self, ext): ext.name) return - if host_platform == 'darwin' and ( + if MACOS and ( sys.maxsize > 2**32 and '-arch' in ext.extra_link_args): # Don't bother doing an import check when an extension was # build with an explicit '-arch' flag on OSX. That's currently @@ -425,7 +478,7 @@ def check_extension_import(self, ext): # Workaround for Cygwin: Cygwin currently has fork issues when many # modules have been imported - if host_platform == 'cygwin': + if CYGWIN: self.announce('WARNING: skipping import check for Cygwin-based "%s"' % ext.name) return @@ -439,7 +492,7 @@ def check_extension_import(self, ext): sys.path_importer_cache.clear() # Don't try to load extensions for cross builds - if cross_compiling: + if CROSS_COMPILING: return loader = importlib.machinery.ExtensionFileLoader(ext.name, ext_filename) @@ -465,6 +518,26 @@ def check_extension_import(self, ext): level=3) self.failed.append(ext.name) + def add_ldflags_cppflags(self): + # Add paths specified in the environment variables LDFLAGS and + # CPPFLAGS for header and library files. + # We must get the values from the Makefile and not the environment + # directly since an inconsistently reproducible issue comes up where + # the environment variable is not set even though the value were passed + # into configure and stored in the Makefile (issue found on OS X 10.3). + for env_var, arg_name, dir_list in ( + ('LDFLAGS', '-R', self.compiler.runtime_library_dirs), + ('LDFLAGS', '-L', self.compiler.library_dirs), + ('CPPFLAGS', '-I', self.compiler.include_dirs)): + env_val = sysconfig.get_config_var(env_var) + if env_val: + parser = argparse.ArgumentParser() + parser.add_argument(arg_name, dest="dirs", action="append") + options, _ = parser.parse_known_args(env_val.split()) + if options.dirs: + for directory in reversed(options.dirs): + add_dir_to_list(dir_list, directory) + def add_multiarch_paths(self): # Debian/Ubuntu multiarch support. # https://wiki.ubuntu.com/MultiarchSpec @@ -492,7 +565,7 @@ def add_multiarch_paths(self): if not find_executable('dpkg-architecture'): return opt = '' - if cross_compiling: + if CROSS_COMPILING: opt = '-t' + sysconfig.get_config_var('HOST_GNU_TYPE') tmpfile = os.path.join(self.build_temp, 'multiarch') if not os.path.exists(self.build_temp): @@ -520,8 +593,6 @@ def add_cross_compiling_paths(self): is_gcc = False is_clang = False in_incdirs = False - inc_dirs = [] - lib_dirs = [] try: if ret >> 8 == 0: with open(tmpfile) as fp: @@ -546,38 +617,20 @@ def add_cross_compiling_paths(self): finally: os.unlink(tmpfile) - def detect_modules(self): + def add_compiler_directories(self): # Ensure that /usr/local is always used, but the local build # directories (i.e. '.' and 'Include') must be first. See issue # 10520. - if not cross_compiling: + if not CROSS_COMPILING: add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') # only change this for cross builds for 3.3, issues on Mageia - if cross_compiling: + if CROSS_COMPILING: self.add_cross_compiling_paths() self.add_multiarch_paths() + self.add_ldflags_cppflags() - # Add paths specified in the environment variables LDFLAGS and - # CPPFLAGS for header and library files. - # We must get the values from the Makefile and not the environment - # directly since an inconsistently reproducible issue comes up where - # the environment variable is not set even though the value were passed - # into configure and stored in the Makefile (issue found on OS X 10.3). - for env_var, arg_name, dir_list in ( - ('LDFLAGS', '-R', self.compiler.runtime_library_dirs), - ('LDFLAGS', '-L', self.compiler.library_dirs), - ('CPPFLAGS', '-I', self.compiler.include_dirs)): - env_val = sysconfig.get_config_var(env_var) - if env_val: - parser = argparse.ArgumentParser() - parser.add_argument(arg_name, dest="dirs", action="append") - options, _ = parser.parse_known_args(env_val.split()) - if options.dirs: - for directory in reversed(options.dirs): - add_dir_to_list(dir_list, directory) - - if (not cross_compiling and + if (not CROSS_COMPILING and os.path.normpath(sys.base_prefix) != '/usr' and not sysconfig.get_config_var('PYTHONFRAMEWORK')): # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework @@ -589,41 +642,38 @@ def detect_modules(self): add_dir_to_list(self.compiler.include_dirs, sysconfig.get_config_var("INCLUDEDIR")) + def init_inc_lib_dirs(self): system_lib_dirs = ['/lib64', '/usr/lib64', '/lib', '/usr/lib'] system_include_dirs = ['/usr/include'] # lib_dirs and inc_dirs are used to search for files; # if a file is found in one of those directories, it can # be assumed that no additional -I,-L directives are needed. - if not cross_compiling: - lib_dirs = self.compiler.library_dirs + system_lib_dirs - inc_dirs = self.compiler.include_dirs + system_include_dirs + if not CROSS_COMPILING: + self.lib_dirs = self.compiler.library_dirs + system_lib_dirs + self.inc_dirs = self.compiler.include_dirs + system_include_dirs else: # Add the sysroot paths. 'sysroot' is a compiler option used to # set the logical path of the standard system headers and # libraries. - lib_dirs = (self.compiler.library_dirs + + self.lib_dirs = (self.compiler.library_dirs + sysroot_paths(('LDFLAGS', 'CC'), system_lib_dirs)) - inc_dirs = (self.compiler.include_dirs + + self.inc_dirs = (self.compiler.include_dirs + sysroot_paths(('CPPFLAGS', 'CFLAGS', 'CC'), system_include_dirs)) - exts = [] - missing = [] config_h = sysconfig.get_config_h_filename() with open(config_h) as file: - config_h_vars = sysconfig.parse_config_h(file) - - srcdir = sysconfig.get_config_var('srcdir') + self.config_h_vars = sysconfig.parse_config_h(file) # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb) - if host_platform in ['osf1', 'unixware7', 'openunix8']: - lib_dirs += ['/usr/ccs/lib'] + if HOST_PLATFORM in ['osf1', 'unixware7', 'openunix8']: + self.lib_dirs += ['/usr/ccs/lib'] # HP-UX11iv3 keeps files in lib/hpux folders. - if host_platform == 'hp-ux11': - lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32'] + if HOST_PLATFORM == 'hp-ux11': + self.lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32'] - if host_platform == 'darwin': + if MACOS: # This should work on any unixy platform ;-) # If the user has bothered specifying additional -I and -L flags # in OPT and LDFLAGS we might as well use them here. @@ -635,149 +685,15 @@ def detect_modules(self): 'CFLAGS', 'LDFLAGS') for item in cflags.split(): if item.startswith('-I'): - inc_dirs.append(item[2:]) + self.inc_dirs.append(item[2:]) for item in ldflags.split(): if item.startswith('-L'): - lib_dirs.append(item[2:]) - - # - # The following modules are all pretty straightforward, and compile - # on pretty much any POSIXish platform. - # - - # array objects - exts.append( Extension('array', ['arraymodule.c']) ) - - # Context Variables - exts.append( Extension('_contextvars', ['_contextvarsmodule.c']) ) - - shared_math = 'Modules/_math.o' - # complex math library functions - exts.append( Extension('cmath', ['cmathmodule.c'], - extra_objects=[shared_math], - depends=['_math.h', shared_math], - libraries=['m']) ) - # math library functions, e.g. sin() - exts.append( Extension('math', ['mathmodule.c'], - extra_objects=[shared_math], - depends=['_math.h', shared_math], - libraries=['m']) ) - - # time libraries: librt may be needed for clock_gettime() - time_libs = [] - lib = sysconfig.get_config_var('TIMEMODULE_LIB') - if lib: - time_libs.append(lib) - - # time operations and variables - exts.append( Extension('time', ['timemodule.c'], - libraries=time_libs) ) - # libm is needed by delta_new() that uses round() and by accum() that - # uses modf(). - exts.append( Extension('_datetime', ['_datetimemodule.c'], - libraries=['m']) ) - # random number generator implemented in C - exts.append( Extension("_random", ["_randommodule.c"]) ) - # bisect - exts.append( Extension("_bisect", ["_bisectmodule.c"]) ) - # heapq - exts.append( Extension("_heapq", ["_heapqmodule.c"]) ) - # C-optimized pickle replacement - exts.append( Extension("_pickle", ["_pickle.c"]) ) - # atexit - exts.append( Extension("atexit", ["atexitmodule.c"]) ) - # _json speedups - exts.append( Extension("_json", ["_json.c"], - # pycore_accu.h requires Py_BUILD_CORE_BUILTIN - extra_compile_args=['-DPy_BUILD_CORE_BUILTIN']) ) - # Python C API test module - exts.append( Extension('_testcapi', ['_testcapimodule.c'], - depends=['testcapi_long.h']) ) - # Python PEP-3118 (buffer protocol) test module - exts.append( Extension('_testbuffer', ['_testbuffer.c']) ) - # Test loading multiple modules from one compiled file (http://bugs.python.org/issue16421) - exts.append( Extension('_testimportmultiple', ['_testimportmultiple.c']) ) - # Test multi-phase extension module init (PEP 489) - exts.append( Extension('_testmultiphase', ['_testmultiphase.c']) ) - # profiler (_lsprof is for cProfile.py) - exts.append( Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c']) ) - # static Unicode character database - exts.append( Extension('unicodedata', ['unicodedata.c'], - depends=['unicodedata_db.h', 'unicodename_db.h']) ) - # _opcode module - exts.append( Extension('_opcode', ['_opcode.c']) ) - # asyncio speedups - exts.append( Extension("_asyncio", ["_asynciomodule.c"]) ) - # _abc speedups - exts.append( Extension("_abc", ["_abc.c"]) ) - # _queue module - exts.append( Extension("_queue", ["_queuemodule.c"]) ) - - # Modules with some UNIX dependencies -- on by default: - # (If you have a really backward UNIX, select and socket may not be - # supported...) - - # fcntl(2) and ioctl(2) - libs = [] - if (config_h_vars.get('FLOCK_NEEDS_LIBBSD', False)): - # May be necessary on AIX for flock function - libs = ['bsd'] - exts.append( Extension('fcntl', ['fcntlmodule.c'], libraries=libs) ) - # pwd(3) - exts.append( Extension('pwd', ['pwdmodule.c']) ) - # grp(3) - if not VXWORKS: - exts.append( Extension('grp', ['grpmodule.c']) ) - # spwd, shadow passwords - if (config_h_vars.get('HAVE_GETSPNAM', False) or - config_h_vars.get('HAVE_GETSPENT', False)): - exts.append( Extension('spwd', ['spwdmodule.c']) ) - else: - missing.append('spwd') - - # select(2); not on ancient System V - exts.append( Extension('select', ['selectmodule.c']) ) - - # Fred Drake's interface to the Python parser - exts.append( Extension('parser', ['parsermodule.c']) ) - - # Memory-mapped files (also works on Win32). - exts.append( Extension('mmap', ['mmapmodule.c']) ) - - # Lance Ellinghaus's syslog module - # syslog daemon interface - exts.append( Extension('syslog', ['syslogmodule.c']) ) - - # Fuzz tests. - exts.append( Extension( - '_xxtestfuzz', - ['_xxtestfuzz/_xxtestfuzz.c', '_xxtestfuzz/fuzzer.c']) - ) - - # Python interface to subinterpreter C-API. - exts.append(Extension('_xxsubinterpreters', ['_xxsubinterpretersmodule.c'], - define_macros=[('Py_BUILD_CORE', '')])) - - # - # Here ends the simple stuff. From here on, modules need certain - # libraries, are platform-specific, or present other surprises. - # - - # Multimedia modules - # These don't work for 64-bit platforms!!! - # These represent audio samples or images as strings: - # - # Operations on audio samples - # According to #993173, this one should actually work fine on - # 64-bit platforms. - # - # audioop needs libm for floor() in multiple functions. - exts.append( Extension('audioop', ['audioop.c'], - libraries=['m']) ) + self.lib_dirs.append(item[2:]) + def detect_readline_curses(self): # readline - do_readline = self.compiler.find_library_file(lib_dirs, 'readline') + do_readline = self.compiler.find_library_file(self.lib_dirs, 'readline') readline_termcap_library = "" curses_library = "" # Cannot use os.popen here in py3k. @@ -786,7 +702,7 @@ def detect_modules(self): os.makedirs(self.build_temp) # Determine if readline is already linked against curses or tinfo. if do_readline: - if cross_compiling: + if CROSS_COMPILING: ret = os.system("%s -d %s | grep '(NEEDED)' > %s" \ % (sysconfig.get_config_var('READELF'), do_readline, tmpfile)) @@ -812,14 +728,14 @@ def detect_modules(self): # use the same library for the readline and curses modules. if 'curses' in readline_termcap_library: curses_library = readline_termcap_library - elif self.compiler.find_library_file(lib_dirs, 'ncursesw'): + elif self.compiler.find_library_file(self.lib_dirs, 'ncursesw'): curses_library = 'ncursesw' - elif self.compiler.find_library_file(lib_dirs, 'ncurses'): + elif self.compiler.find_library_file(self.lib_dirs, 'ncurses'): curses_library = 'ncurses' - elif self.compiler.find_library_file(lib_dirs, 'curses'): + elif self.compiler.find_library_file(self.lib_dirs, 'curses'): curses_library = 'curses' - if host_platform == 'darwin': + if MACOS: os_release = int(os.uname()[2].split('.')[0]) dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') if (dep_target and @@ -830,10 +746,10 @@ def detect_modules(self): # MacOSX 10.4 has a broken readline. Don't try to build # the readline module unless the user has installed a fixed # readline package - if find_file('readline/rlconf.h', inc_dirs, []) is None: + if find_file('readline/rlconf.h', self.inc_dirs, []) is None: do_readline = False if do_readline: - if host_platform == 'darwin' and os_release < 9: + if MACOS and os_release < 9: # In every directory on the search path search for a dynamic # library and then a static library, instead of first looking # for dynamic libraries on the entire path. @@ -848,85 +764,182 @@ def detect_modules(self): pass # Issue 7384: Already linked against curses or tinfo. elif curses_library: readline_libs.append(curses_library) - elif self.compiler.find_library_file(lib_dirs + + elif self.compiler.find_library_file(self.lib_dirs + ['/usr/lib/termcap'], 'termcap'): readline_libs.append('termcap') - exts.append( Extension('readline', ['readline.c'], + self.add_ext( Extension('readline', ['readline.c'], library_dirs=['/usr/lib/termcap'], extra_link_args=readline_extra_link_args, libraries=readline_libs) ) else: - missing.append('readline') + self.missing.append('readline') - # crypt module. + # Curses support, requiring the System V version of curses, often + # provided by the ncurses library. + curses_defines = [] + curses_includes = [] + panel_library = 'panel' + if curses_library == 'ncursesw': + curses_defines.append(('HAVE_NCURSESW', '1')) + if not CROSS_COMPILING: + curses_includes.append('/usr/include/ncursesw') + # Bug 1464056: If _curses.so links with ncursesw, + # _curses_panel.so must link with panelw. + panel_library = 'panelw' + if MACOS: + # On OS X, there is no separate /usr/lib/libncursesw nor + # libpanelw. If we are here, we found a locally-supplied + # version of libncursesw. There should also be a + # libpanelw. _XOPEN_SOURCE defines are usually excluded + # for OS X but we need _XOPEN_SOURCE_EXTENDED here for + # ncurses wide char support + curses_defines.append(('_XOPEN_SOURCE_EXTENDED', '1')) + elif MACOS and curses_library == 'ncurses': + # Building with the system-suppied combined libncurses/libpanel + curses_defines.append(('HAVE_NCURSESW', '1')) + curses_defines.append(('_XOPEN_SOURCE_EXTENDED', '1')) + + if curses_library.startswith('ncurses'): + curses_libs = [curses_library] + self.add_ext( Extension('_curses', ['_cursesmodule.c'], + include_dirs=curses_includes, + define_macros=curses_defines, + libraries = curses_libs) ) + elif curses_library == 'curses' and not MACOS: + # OSX has an old Berkeley curses, not good enough for + # the _curses module. + if (self.compiler.find_library_file(self.lib_dirs, 'terminfo')): + curses_libs = ['curses', 'terminfo'] + elif (self.compiler.find_library_file(self.lib_dirs, 'termcap')): + curses_libs = ['curses', 'termcap'] + else: + curses_libs = ['curses'] + + self.add_ext( Extension('_curses', ['_cursesmodule.c'], + define_macros=curses_defines, + libraries = curses_libs) ) + else: + self.missing.append('_curses') + + # If the curses module is enabled, check for the panel module + if (module_enabled(self.extensions, '_curses') and + self.compiler.find_library_file(self.lib_dirs, panel_library)): + self.add_ext( Extension('_curses_panel', ['_curses_panel.c'], + include_dirs=curses_includes, + define_macros=curses_defines, + libraries = [panel_library] + curses_libs) ) + else: + self.missing.append('_curses_panel') - if self.compiler.find_library_file(lib_dirs, 'crypt'): + def detect_crypt(self): + # crypt module. + if self.compiler.find_library_file(self.lib_dirs, 'crypt'): libs = ['crypt'] else: libs = [] if not VXWORKS: - exts.append( Extension('_crypt', ['_cryptmodule.c'], libraries=libs) ) - elif self.compiler.find_library_file(lib_dirs, 'OPENSSL'): + self.add_ext( Extension('_crypt', ['_cryptmodule.c'], libraries=libs) ) + elif self.compiler.find_library_file(self.lib_dirs, 'OPENSSL'): libs = ['OPENSSL'] - exts.append( Extension('_crypt', ['_cryptmodule.c'], libraries=libs) ) - - # CSV files - exts.append( Extension('_csv', ['_csv.c']) ) - - # POSIX subprocess module helper. - exts.append( Extension('_posixsubprocess', ['_posixsubprocess.c']) ) + self.add_ext( Extension('_crypt', ['_cryptmodule.c'], libraries=libs) ) + def detect_socket(self): # socket(2) if not VXWORKS: - exts.append( Extension('_socket', ['socketmodule.c'], + self.add_ext( Extension('_socket', ['socketmodule.c'], depends = ['socketmodule.h']) ) - elif self.compiler.find_library_file(lib_dirs, 'net'): + elif self.compiler.find_library_file(self.lib_dirs, 'net'): libs = ['net'] - exts.append( Extension('_socket', ['socketmodule.c'], + self.add_ext( Extension('_socket', ['socketmodule.c'], depends = ['socketmodule.h'], libraries=libs) ) - # Detect SSL support for the socket module (via _ssl) - ssl_ext, hashlib_ext = self._detect_openssl(inc_dirs, lib_dirs) - if ssl_ext is not None: - exts.append(ssl_ext) - else: - missing.append('_ssl') - if hashlib_ext is not None: - exts.append(hashlib_ext) + def detect_expat_elementtree(self): + # Interface to the Expat XML parser + # + # Expat was written by James Clark and is now maintained by a group of + # developers on SourceForge; see www.libexpat.org for more information. + # The pyexpat module was written by Paul Prescod after a prototype by + # Jack Jansen. The Expat source is included in Modules/expat/. Usage + # of a system shared libexpat.so is possible with --with-system-expat + # configure option. + # + # More information on Expat can be found at www.libexpat.org. + # + if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"): + expat_inc = [] + define_macros = [] + extra_compile_args = [] + expat_lib = ['expat'] + expat_sources = [] + expat_depends = [] else: - missing.append('_hashlib') + expat_inc = [os.path.join(self.srcdir, 'Modules', 'expat')] + define_macros = [ + ('HAVE_EXPAT_CONFIG_H', '1'), + # bpo-30947: Python uses best available entropy sources to + # call XML_SetHashSalt(), expat entropy sources are not needed + ('XML_POOR_ENTROPY', '1'), + ] + extra_compile_args = [] + expat_lib = [] + expat_sources = ['expat/xmlparse.c', + 'expat/xmlrole.c', + 'expat/xmltok.c'] + expat_depends = ['expat/ascii.h', + 'expat/asciitab.h', + 'expat/expat.h', + 'expat/expat_config.h', + 'expat/expat_external.h', + 'expat/internal.h', + 'expat/latin1tab.h', + 'expat/utf8tab.h', + 'expat/xmlrole.h', + 'expat/xmltok.h', + 'expat/xmltok_impl.h' + ] - # We always compile these even when OpenSSL is available (issue #14693). - # It's harmless and the object code is tiny (40-50 KiB per module, - # only loaded when actually used). - exts.append( Extension('_sha256', ['sha256module.c'], - depends=['hashlib.h']) ) - exts.append( Extension('_sha512', ['sha512module.c'], - depends=['hashlib.h']) ) - exts.append( Extension('_md5', ['md5module.c'], - depends=['hashlib.h']) ) - exts.append( Extension('_sha1', ['sha1module.c'], - depends=['hashlib.h']) ) - - blake2_deps = glob(os.path.join(os.getcwd(), srcdir, - 'Modules/_blake2/impl/*')) - blake2_deps.append('hashlib.h') + cc = sysconfig.get_config_var('CC').split()[0] + ret = os.system( + '"%s" -Werror -Wimplicit-fallthrough -E -xc /dev/null >/dev/null 2>&1' % cc) + if ret >> 8 == 0: + extra_compile_args.append('-Wno-implicit-fallthrough') - exts.append( Extension('_blake2', - ['_blake2/blake2module.c', - '_blake2/blake2b_impl.c', - '_blake2/blake2s_impl.c'], - depends=blake2_deps) ) + self.add_ext(Extension('pyexpat', + define_macros = define_macros, + extra_compile_args = extra_compile_args, + include_dirs = expat_inc, + libraries = expat_lib, + sources = ['pyexpat.c'] + expat_sources, + depends = expat_depends, + )) - sha3_deps = glob(os.path.join(os.getcwd(), srcdir, - 'Modules/_sha3/kcp/*')) - sha3_deps.append('hashlib.h') - exts.append( Extension('_sha3', - ['_sha3/sha3module.c'], - depends=sha3_deps)) + # Fredrik Lundh's cElementTree module. Note that this also + # uses expat (via the CAPI hook in pyexpat). + if os.path.isfile(os.path.join(self.srcdir, 'Modules', '_elementtree.c')): + define_macros.append(('USE_PYEXPAT_CAPI', None)) + self.add_ext(Extension('_elementtree', + define_macros = define_macros, + include_dirs = expat_inc, + libraries = expat_lib, + sources = ['_elementtree.c'], + depends = ['pyexpat.c'] + expat_sources + + expat_depends, + )) + else: + self.missing.append('_elementtree') + + def detect_multibytecodecs(self): + # Hye-Shik Chang's CJKCodecs modules. + self.add_ext(Extension('_multibytecodec', + ['cjkcodecs/multibytecodec.c'])) + for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'): + self.add_ext(Extension('_codecs_%s' % loc, + ['cjkcodecs/_codecs_%s.c' % loc])) + + def detect_dbm_gdbm(self): # Modules that provide persistent dictionary-like semantics. You will # probably want to arrange for at least one of them to be available on # your machine, though none are defined by default because of library @@ -999,7 +1012,7 @@ def gen_db_minor_ver_nums(major): db_inc_paths.append('/pkg/db-3.%d/include' % x) db_inc_paths.append('/opt/db-3.%d/include' % x) - if cross_compiling: + if CROSS_COMPILING: db_inc_paths = [] # Add some common subdirectories for Sleepycat DB to the list, @@ -1007,7 +1020,7 @@ def gen_db_minor_ver_nums(major): # picked up when it is installed in a non-standard prefix and # the user has added that prefix into inc_dirs. std_variants = [] - for dn in inc_dirs: + for dn in self.inc_dirs: std_variants.append(os.path.join(dn, 'db3')) std_variants.append(os.path.join(dn, 'db4')) for x in gen_db_minor_ver_nums(4): @@ -1022,16 +1035,18 @@ def gen_db_minor_ver_nums(major): db_ver_inc_map = {} - if host_platform == 'darwin': + if MACOS: sysroot = macosx_sdk_root() - class db_found(Exception): pass + class db_found(Exception): + pass + try: # See whether there is a Sleepycat header in the standard # search path. - for d in inc_dirs + db_inc_paths: + for d in self.inc_dirs + db_inc_paths: f = os.path.join(d, "db.h") - if host_platform == 'darwin' and is_macosx_sdk_path(d): + if MACOS and is_macosx_sdk_path(d): f = os.path.join(sysroot, d[1:], "db.h") if db_setup_debug: print("db: looking for db.h in", f) @@ -1082,7 +1097,7 @@ class db_found(Exception): pass db_incdir.replace("include", 'lib'), ] - if host_platform != 'darwin': + if not MACOS: db_dirs_to_check = list(filter(os.path.isdir, db_dirs_to_check)) else: @@ -1107,7 +1122,7 @@ class db_found(Exception): pass ('db%d%d' % db_ver), ('db%d' % db_ver[0])): dblib_file = self.compiler.find_library_file( - db_dirs_to_check + lib_dirs, dblib ) + db_dirs_to_check + self.lib_dirs, dblib ) if dblib_file: dblib_dir = [ os.path.abspath(os.path.dirname(dblib_file)) ] raise db_found @@ -1122,11 +1137,11 @@ class db_found(Exception): pass # Only add the found library and include directories if they aren't # already being searched. This avoids an explicit runtime library # dependency. - if db_incdir in inc_dirs: + if db_incdir in self.inc_dirs: db_incs = None else: db_incs = [db_incdir] - if dblib_dir[0] in lib_dirs: + if dblib_dir[0] in self.lib_dirs: dblib_dir = None else: if db_setup_debug: print("db: no appropriate library found") @@ -1147,7 +1162,7 @@ class db_found(Exception): pass '/usr/local/include/sqlite', '/usr/local/include/sqlite3', ] - if cross_compiling: + if CROSS_COMPILING: sqlite_inc_paths = [] MIN_SQLITE_VERSION_NUMBER = (3, 0, 8) MIN_SQLITE_VERSION = ".".join([str(x) @@ -1156,12 +1171,12 @@ class db_found(Exception): pass # Scan the default include directories before the SQLite specific # ones. This allows one to override the copy of sqlite on OSX, # where /usr/include contains an old version of sqlite. - if host_platform == 'darwin': + if MACOS: sysroot = macosx_sdk_root() - for d_ in inc_dirs + sqlite_inc_paths: + for d_ in self.inc_dirs + sqlite_inc_paths: d = d_ - if host_platform == 'darwin' and is_macosx_sdk_path(d): + if MACOS and is_macosx_sdk_path(d): d = os.path.join(sysroot, d[1:]) f = os.path.join(d, "sqlite3.h") @@ -1196,7 +1211,7 @@ class db_found(Exception): pass os.path.join(sqlite_incdir, '..', '..', 'lib'), ] sqlite_libfile = self.compiler.find_library_file( - sqlite_dirs_to_check + lib_dirs, 'sqlite3') + sqlite_dirs_to_check + self.lib_dirs, 'sqlite3') if sqlite_libfile: sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))] @@ -1212,7 +1227,7 @@ class db_found(Exception): pass '_sqlite/util.c', ] sqlite_defines = [] - if host_platform != "win32": + if not MS_WINDOWS: sqlite_defines.append(('MODULE_NAME', '"sqlite3"')) else: sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"')) @@ -1222,7 +1237,7 @@ class db_found(Exception): pass if '--enable-loadable-sqlite-extensions' not in sysconfig.get_config_var("CONFIG_ARGS"): sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1")) - if host_platform == 'darwin': + if MACOS: # In every directory on the search path search for a dynamic # library and then a static library, instead of first looking # for dynamic libraries on the entire path. @@ -1239,21 +1254,21 @@ class db_found(Exception): pass if sqlite_incdir not in self.compiler.include_dirs: include_dirs.append(sqlite_incdir) # avoid a runtime library path for a system library dir - if sqlite_libdir and sqlite_libdir[0] in lib_dirs: + if sqlite_libdir and sqlite_libdir[0] in self.lib_dirs: sqlite_libdir = None - exts.append(Extension('_sqlite3', sqlite_srcs, + self.add_ext(Extension('_sqlite3', sqlite_srcs, define_macros=sqlite_defines, include_dirs=include_dirs, library_dirs=sqlite_libdir, extra_link_args=sqlite_extra_link_args, libraries=["sqlite3",])) else: - missing.append('_sqlite3') + self.missing.append('_sqlite3') dbm_setup_debug = False # verbose debug prints from this script? dbm_order = ['gdbm'] # The standard Unix dbm module: - if host_platform not in ['cygwin']: + if not CYGWIN: config_args = [arg.strip("'") for arg in sysconfig.get_config_var("CONFIG_ARGS").split()] dbm_args = [arg for arg in config_args @@ -1265,13 +1280,13 @@ class db_found(Exception): pass dbmext = None for cand in dbm_order: if cand == "ndbm": - if find_file("ndbm.h", inc_dirs, []) is not None: + if find_file("ndbm.h", self.inc_dirs, []) is not None: # Some systems have -lndbm, others have -lgdbm_compat, # others don't have either - if self.compiler.find_library_file(lib_dirs, + if self.compiler.find_library_file(self.lib_dirs, 'ndbm'): ndbm_libs = ['ndbm'] - elif self.compiler.find_library_file(lib_dirs, + elif self.compiler.find_library_file(self.lib_dirs, 'gdbm_compat'): ndbm_libs = ['gdbm_compat'] else: @@ -1285,12 +1300,12 @@ class db_found(Exception): pass break elif cand == "gdbm": - if self.compiler.find_library_file(lib_dirs, 'gdbm'): + if self.compiler.find_library_file(self.lib_dirs, 'gdbm'): gdbm_libs = ['gdbm'] - if self.compiler.find_library_file(lib_dirs, + if self.compiler.find_library_file(self.lib_dirs, 'gdbm_compat'): gdbm_libs.append('gdbm_compat') - if find_file("gdbm/ndbm.h", inc_dirs, []) is not None: + if find_file("gdbm/ndbm.h", self.inc_dirs, []) is not None: if dbm_setup_debug: print("building dbm using gdbm") dbmext = Extension( '_dbm', ['_dbmmodule.c'], @@ -1299,7 +1314,7 @@ class db_found(Exception): pass ], libraries = gdbm_libs) break - if find_file("gdbm-ndbm.h", inc_dirs, []) is not None: + if find_file("gdbm-ndbm.h", self.inc_dirs, []) is not None: if dbm_setup_debug: print("building dbm using gdbm") dbmext = Extension( '_dbm', ['_dbmmodule.c'], @@ -1320,93 +1335,21 @@ class db_found(Exception): pass ('DB_DBM_HSEARCH', None), ], libraries=dblibs) - break - if dbmext is not None: - exts.append(dbmext) - else: - missing.append('_dbm') - - # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: - if ('gdbm' in dbm_order and - self.compiler.find_library_file(lib_dirs, 'gdbm')): - exts.append( Extension('_gdbm', ['_gdbmmodule.c'], - libraries = ['gdbm'] ) ) - else: - missing.append('_gdbm') - - # Unix-only modules - if host_platform != 'win32': - if not VXWORKS: - # Steen Lumholt's termios module - exts.append( Extension('termios', ['termios.c']) ) - # Jeremy Hylton's rlimit interface - exts.append( Extension('resource', ['resource.c']) ) - else: - missing.extend(['resource', 'termios']) - - nis = self._detect_nis(inc_dirs, lib_dirs) - if nis is not None: - exts.append(nis) - else: - missing.append('nis') - - # Curses support, requiring the System V version of curses, often - # provided by the ncurses library. - curses_defines = [] - curses_includes = [] - panel_library = 'panel' - if curses_library == 'ncursesw': - curses_defines.append(('HAVE_NCURSESW', '1')) - if not cross_compiling: - curses_includes.append('/usr/include/ncursesw') - # Bug 1464056: If _curses.so links with ncursesw, - # _curses_panel.so must link with panelw. - panel_library = 'panelw' - if host_platform == 'darwin': - # On OS X, there is no separate /usr/lib/libncursesw nor - # libpanelw. If we are here, we found a locally-supplied - # version of libncursesw. There should also be a - # libpanelw. _XOPEN_SOURCE defines are usually excluded - # for OS X but we need _XOPEN_SOURCE_EXTENDED here for - # ncurses wide char support - curses_defines.append(('_XOPEN_SOURCE_EXTENDED', '1')) - elif host_platform == 'darwin' and curses_library == 'ncurses': - # Building with the system-suppied combined libncurses/libpanel - curses_defines.append(('HAVE_NCURSESW', '1')) - curses_defines.append(('_XOPEN_SOURCE_EXTENDED', '1')) - - if curses_library.startswith('ncurses'): - curses_libs = [curses_library] - exts.append( Extension('_curses', ['_cursesmodule.c'], - include_dirs=curses_includes, - define_macros=curses_defines, - libraries = curses_libs) ) - elif curses_library == 'curses' and host_platform != 'darwin': - # OSX has an old Berkeley curses, not good enough for - # the _curses module. - if (self.compiler.find_library_file(lib_dirs, 'terminfo')): - curses_libs = ['curses', 'terminfo'] - elif (self.compiler.find_library_file(lib_dirs, 'termcap')): - curses_libs = ['curses', 'termcap'] + break + if dbmext is not None: + self.add_ext(dbmext) else: - curses_libs = ['curses'] - - exts.append( Extension('_curses', ['_cursesmodule.c'], - define_macros=curses_defines, - libraries = curses_libs) ) - else: - missing.append('_curses') + self.missing.append('_dbm') - # If the curses module is enabled, check for the panel module - if (module_enabled(exts, '_curses') and - self.compiler.find_library_file(lib_dirs, panel_library)): - exts.append( Extension('_curses_panel', ['_curses_panel.c'], - include_dirs=curses_includes, - define_macros=curses_defines, - libraries = [panel_library] + curses_libs) ) + # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: + if ('gdbm' in dbm_order and + self.compiler.find_library_file(self.lib_dirs, 'gdbm')): + self.add_ext( Extension('_gdbm', ['_gdbmmodule.c'], + libraries = ['gdbm'] ) ) else: - missing.append('_curses_panel') + self.missing.append('_gdbm') + def detect_compress_exts(self): # Andrew Kuchling's zlib module. Note that some versions of zlib # 1.1.3 have security problems. See CERT Advisory CA-2002-07: # http://www.cert.org/advisories/CA-2002-07.html @@ -1419,13 +1362,13 @@ class db_found(Exception): pass # # You can upgrade zlib to version 1.1.4 yourself by going to # http://www.gzip.org/zlib/ - zlib_inc = find_file('zlib.h', [], inc_dirs) + zlib_inc = find_file('zlib.h', [], self.inc_dirs) have_zlib = False if zlib_inc is not None: zlib_h = zlib_inc[0] + '/zlib.h' version = '"0.0.0"' version_req = '"1.1.3"' - if host_platform == 'darwin' and is_macosx_sdk_path(zlib_h): + if MACOS and is_macosx_sdk_path(zlib_h): zlib_h = os.path.join(macosx_sdk_root(), zlib_h[1:]) with open(zlib_h) as fp: while 1: @@ -1436,21 +1379,21 @@ class db_found(Exception): pass version = line.split()[2] break if version >= version_req: - if (self.compiler.find_library_file(lib_dirs, 'z')): - if host_platform == "darwin": + if (self.compiler.find_library_file(self.lib_dirs, 'z')): + if MACOS: zlib_extra_link_args = ('-Wl,-search_paths_first',) else: zlib_extra_link_args = () - exts.append( Extension('zlib', ['zlibmodule.c'], + self.add_ext( Extension('zlib', ['zlibmodule.c'], libraries = ['z'], extra_link_args = zlib_extra_link_args)) have_zlib = True else: - missing.append('zlib') + self.missing.append('zlib') else: - missing.append('zlib') + self.missing.append('zlib') else: - missing.append('zlib') + self.missing.append('zlib') # Helper module for various ascii-encoders. Uses zlib for an optimized # crc32 if we have it. Otherwise binascii uses its own. @@ -1462,144 +1405,33 @@ class db_found(Exception): pass extra_compile_args = [] libraries = [] extra_link_args = [] - exts.append( Extension('binascii', ['binascii.c'], + self.add_ext( Extension('binascii', ['binascii.c'], extra_compile_args = extra_compile_args, libraries = libraries, extra_link_args = extra_link_args) ) # Gustavo Niemeyer's bz2 module. - if (self.compiler.find_library_file(lib_dirs, 'bz2')): - if host_platform == "darwin": + if (self.compiler.find_library_file(self.lib_dirs, 'bz2')): + if MACOS: bz2_extra_link_args = ('-Wl,-search_paths_first',) else: bz2_extra_link_args = () - exts.append( Extension('_bz2', ['_bz2module.c'], + self.add_ext( Extension('_bz2', ['_bz2module.c'], libraries = ['bz2'], extra_link_args = bz2_extra_link_args) ) else: - missing.append('_bz2') + self.missing.append('_bz2') # LZMA compression support. - if self.compiler.find_library_file(lib_dirs, 'lzma'): - exts.append( Extension('_lzma', ['_lzmamodule.c'], + if self.compiler.find_library_file(self.lib_dirs, 'lzma'): + self.add_ext( Extension('_lzma', ['_lzmamodule.c'], libraries = ['lzma']) ) else: - missing.append('_lzma') - - # Interface to the Expat XML parser - # - # Expat was written by James Clark and is now maintained by a group of - # developers on SourceForge; see www.libexpat.org for more information. - # The pyexpat module was written by Paul Prescod after a prototype by - # Jack Jansen. The Expat source is included in Modules/expat/. Usage - # of a system shared libexpat.so is possible with --with-system-expat - # configure option. - # - # More information on Expat can be found at www.libexpat.org. - # - if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"): - expat_inc = [] - define_macros = [] - extra_compile_args = [] - expat_lib = ['expat'] - expat_sources = [] - expat_depends = [] - else: - expat_inc = [os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')] - define_macros = [ - ('HAVE_EXPAT_CONFIG_H', '1'), - # bpo-30947: Python uses best available entropy sources to - # call XML_SetHashSalt(), expat entropy sources are not needed - ('XML_POOR_ENTROPY', '1'), - ] - extra_compile_args = [] - expat_lib = [] - expat_sources = ['expat/xmlparse.c', - 'expat/xmlrole.c', - 'expat/xmltok.c'] - expat_depends = ['expat/ascii.h', - 'expat/asciitab.h', - 'expat/expat.h', - 'expat/expat_config.h', - 'expat/expat_external.h', - 'expat/internal.h', - 'expat/latin1tab.h', - 'expat/utf8tab.h', - 'expat/xmlrole.h', - 'expat/xmltok.h', - 'expat/xmltok_impl.h' - ] - - cc = sysconfig.get_config_var('CC').split()[0] - ret = os.system( - '"%s" -Werror -Wimplicit-fallthrough -E -xc /dev/null >/dev/null 2>&1' % cc) - if ret >> 8 == 0: - extra_compile_args.append('-Wno-implicit-fallthrough') - - exts.append(Extension('pyexpat', - define_macros = define_macros, - extra_compile_args = extra_compile_args, - include_dirs = expat_inc, - libraries = expat_lib, - sources = ['pyexpat.c'] + expat_sources, - depends = expat_depends, - )) - - # Fredrik Lundh's cElementTree module. Note that this also - # uses expat (via the CAPI hook in pyexpat). - - if os.path.isfile(os.path.join(srcdir, 'Modules', '_elementtree.c')): - define_macros.append(('USE_PYEXPAT_CAPI', None)) - exts.append(Extension('_elementtree', - define_macros = define_macros, - include_dirs = expat_inc, - libraries = expat_lib, - sources = ['_elementtree.c'], - depends = ['pyexpat.c'] + expat_sources + - expat_depends, - )) - else: - missing.append('_elementtree') - - # Hye-Shik Chang's CJKCodecs modules. - exts.append(Extension('_multibytecodec', - ['cjkcodecs/multibytecodec.c'])) - for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'): - exts.append(Extension('_codecs_%s' % loc, - ['cjkcodecs/_codecs_%s.c' % loc])) - - # Stefan Krah's _decimal module - exts.append(self._decimal_ext()) - - # Thomas Heller's _ctypes module - self.detect_ctypes(inc_dirs, lib_dirs) + self.missing.append('_lzma') + def detect_multiprocessing(self): # Richard Oudkerk's multiprocessing module - if host_platform == 'win32': # Windows - macros = dict() - libraries = ['ws2_32'] - - elif host_platform == 'darwin': # Mac OSX - macros = dict() - libraries = [] - - elif host_platform == 'cygwin': # Cygwin - macros = dict() - libraries = [] - - elif host_platform.startswith('openbsd'): - macros = dict() - libraries = [] - - elif host_platform.startswith('netbsd'): - macros = dict() - libraries = [] - - else: # Linux and other unices - macros = dict() - libraries = ['rt'] - - if host_platform == 'win32': + if MS_WINDOWS: multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c', '_multiprocessing/semaphore.c', ] @@ -1618,63 +1450,225 @@ class db_found(Exception): pass if sysconfig.get_config_var('SHM_NEEDS_LIBRT'): # need to link with librt to get shm_open() libs.append('rt') - exts.append( Extension('_posixshmem', posixshmem_srcs, + self.add_ext( Extension('_posixshmem', posixshmem_srcs, define_macros={}, libraries=libs, include_dirs=["Modules/_multiprocessing"])) - exts.append ( Extension('_multiprocessing', multiprocessing_srcs, - define_macros=list(macros.items()), + self.add_ext ( Extension('_multiprocessing', multiprocessing_srcs, include_dirs=["Modules/_multiprocessing"])) - # End multiprocessing + + def add_simple_extensions(self): + # + # The following modules are all pretty straightforward, and compile + # on pretty much any POSIXish platform. + # + + # array objects + self.add_ext( Extension('array', ['arraymodule.c']) ) + + # Context Variables + self.add_ext( Extension('_contextvars', ['_contextvarsmodule.c']) ) + + shared_math = 'Modules/_math.o' + # complex math library functions + self.add_ext( Extension('cmath', ['cmathmodule.c'], + extra_objects=[shared_math], + depends=['_math.h', shared_math], + libraries=MATH_LIBS) ) + # math library functions, e.g. sin() + self.add_ext( Extension('math', ['mathmodule.c'], + extra_objects=[shared_math], + depends=['_math.h', shared_math], + libraries=MATH_LIBS) ) + + # time operations and variables + # time libraries: librt may be needed for clock_gettime() + time_lib = sysconfig.get_config_var('TIMEMODULE_LIB') + time_libs = [] + if time_lib: + time_libs.append(time_lib) + self.add_ext( Extension('time', ['timemodule.c'], + libraries=time_libs) ) + + # MATH_LIBS is needed by delta_new() that uses round() + # and by accum() that uses modf(). + self.add_ext( Extension('_datetime', ['_datetimemodule.c'], + libraries=MATH_LIBS) ) + # random number generator implemented in C + self.add_ext( Extension("_random", ["_randommodule.c"]) ) + # bisect + self.add_ext( Extension("_bisect", ["_bisectmodule.c"]) ) + # heapq + self.add_ext( Extension("_heapq", ["_heapqmodule.c"]) ) + # C-optimized pickle replacement + self.add_ext( Extension("_pickle", ["_pickle.c"]) ) + # atexit + self.add_ext( Extension("atexit", ["atexitmodule.c"]) ) + # _json speedups + self.add_ext( Extension("_json", ["_json.c"], + # pycore_accu.h requires Py_BUILD_CORE_BUILTIN + extra_compile_args=['-DPy_BUILD_CORE_BUILTIN']) ) + # profiler (_lsprof is for cProfile.py) + self.add_ext( Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c']) ) + # static Unicode character database + self.add_ext( Extension('unicodedata', ['unicodedata.c'], + depends=['unicodedata_db.h', 'unicodename_db.h']) ) + # _opcode module + self.add_ext( Extension('_opcode', ['_opcode.c']) ) + # asyncio speedups + self.add_ext( Extension("_asyncio", ["_asynciomodule.c"]) ) + # _abc speedups + self.add_ext( Extension("_abc", ["_abc.c"]) ) + # _queue module + self.add_ext( Extension("_queue", ["_queuemodule.c"]) ) + + # Modules with some UNIX dependencies -- on by default: + # (If you have a really backward UNIX, select and socket may not be + # supported...) + + # fcntl(2) and ioctl(2) + fcntl_libs = [] + if (self.config_h_vars.get('FLOCK_NEEDS_LIBBSD', False)): + # May be necessary on AIX for flock function + fcntl_libs = ['bsd'] + self.add_ext( Extension('fcntl', ['fcntlmodule.c'], libraries=fcntl_libs) ) + # pwd(3) + self.add_ext( Extension('pwd', ['pwdmodule.c']) ) + # grp(3) + if not VXWORKS: + self.add_ext( Extension('grp', ['grpmodule.c']) ) + # spwd, shadow passwords + if (self.config_h_vars.get('HAVE_GETSPNAM', False) or + self.config_h_vars.get('HAVE_GETSPENT', False)): + self.add_ext( Extension('spwd', ['spwdmodule.c']) ) + else: + self.missing.append('spwd') + + # select(2); not on ancient System V + self.add_ext( Extension('select', ['selectmodule.c']) ) + + # Fred Drake's interface to the Python parser + self.add_ext( Extension('parser', ['parsermodule.c']) ) + + # Memory-mapped files (also works on Win32). + self.add_ext( Extension('mmap', ['mmapmodule.c']) ) + + # Lance Ellinghaus's syslog module + # syslog daemon interface + self.add_ext( Extension('syslog', ['syslogmodule.c']) ) + + # Python interface to subinterpreter C-API. + self.add_ext(Extension('_xxsubinterpreters', ['_xxsubinterpretersmodule.c'], + define_macros=[('Py_BUILD_CORE', '')])) + + # Multimedia modules + # These don't work for 64-bit platforms!!! + # These represent audio samples or images as strings: + # + # Operations on audio samples + # According to #993173, this one should actually work fine on + # 64-bit platforms. + # + # audioop needs MATH_LIBS for floor() in multiple functions. + self.add_ext( Extension('audioop', ['audioop.c'], + libraries=MATH_LIBS) ) + + # CSV files + self.add_ext( Extension('_csv', ['_csv.c']) ) + + # POSIX subprocess module helper. + self.add_ext( Extension('_posixsubprocess', ['_posixsubprocess.c']) ) + + def add_test_extensions(self): + # Python C API test module + self.add_ext( Extension('_testcapi', ['_testcapimodule.c'], + depends=['testcapi_long.h']) ) + # Python PEP-3118 (buffer protocol) test module + self.add_ext( Extension('_testbuffer', ['_testbuffer.c']) ) + # Test loading multiple modules from one compiled file (http://bugs.python.org/issue16421) + self.add_ext( Extension('_testimportmultiple', ['_testimportmultiple.c']) ) + # Test multi-phase extension module init (PEP 489) + self.add_ext( Extension('_testmultiphase', ['_testmultiphase.c']) ) + # Fuzz tests. + self.add_ext( Extension( + '_xxtestfuzz', + ['_xxtestfuzz/_xxtestfuzz.c', '_xxtestfuzz/fuzzer.c']) + ) + + def detect_platform_specific_exts(self): + # Unix-only modules + if not MS_WINDOWS: + if not VXWORKS: + # Steen Lumholt's termios module + self.add_ext( Extension('termios', ['termios.c']) ) + # Jeremy Hylton's rlimit interface + self.add_ext( Extension('resource', ['resource.c']) ) + else: + self.missing.extend(['resource', 'termios']) # Platform-specific libraries - if host_platform.startswith(('linux', 'freebsd', 'gnukfreebsd')): - exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) ) + if HOST_PLATFORM.startswith(('linux', 'freebsd', 'gnukfreebsd')): + self.add_ext( Extension('ossaudiodev', ['ossaudiodev.c']) ) else: - missing.append('ossaudiodev') + self.missing.append('ossaudiodev') - if host_platform == 'darwin': - exts.append( + if MACOS: + self.add_ext( Extension('_scproxy', ['_scproxy.c'], extra_link_args=[ '-framework', 'SystemConfiguration', '-framework', 'CoreFoundation', ])) - self.extensions.extend(exts) - - # Call the method for detecting whether _tkinter can be compiled - self.detect_tkinter(inc_dirs, lib_dirs) - - if '_tkinter' not in [e.name for e in self.extensions]: - missing.append('_tkinter') - + def detect_uuid(self): # Build the _uuid module if possible - uuid_incs = find_file("uuid.h", inc_dirs, ["/usr/include/uuid"]) + uuid_incs = find_file("uuid.h", self.inc_dirs, ["/usr/include/uuid"]) if uuid_incs is not None: - if self.compiler.find_library_file(lib_dirs, 'uuid'): + if self.compiler.find_library_file(self.lib_dirs, 'uuid'): uuid_libs = ['uuid'] else: uuid_libs = [] - self.extensions.append(Extension('_uuid', ['_uuidmodule.c'], + self.add_ext(Extension('_uuid', ['_uuidmodule.c'], libraries=uuid_libs, include_dirs=uuid_incs)) else: - missing.append('_uuid') + self.missing.append('_uuid') + + def detect_modules(self): + self.add_compiler_directories() + self.init_inc_lib_dirs() + + self.add_simple_extensions() + if TEST_EXTENSIONS: + self.add_test_extensions() + self.detect_platform_specific_exts() + + self.detect_readline_curses() + self.detect_crypt() + self.detect_socket() + self.detect_openssl_hashlib() + self.detect_dbm_gdbm() + self.detect_nis() + self.detect_compress_exts() + self.detect_expat_elementtree() + self.detect_multibytecodecs() + self.detect_decimal() + self.detect_ctypes() + self.detect_multiprocessing() + self.detect_uuid() + self.detect_tkinter() ## # Uncomment these lines if you want to play with xxmodule.c ## ext = Extension('xx', ['xxmodule.c']) -## self.extensions.append(ext) +## self.add_ext(ext) if 'd' not in sysconfig.get_config_var('ABIFLAGS'): ext = Extension('xxlimited', ['xxlimited.c'], define_macros=[('Py_LIMITED_API', '0x03050000')]) - self.extensions.append(ext) - - return missing + self.add_ext(ext) - def detect_tkinter_explicitly(self): + def _detect_tkinter_explicitly(self): # Build _tkinter using explicit locations for Tcl/Tk. # # This is enabled when both arguments are given to ./configure: @@ -1697,7 +1691,7 @@ def detect_tkinter_explicitly(self): tcltk_libs = os.environ.get('_TCLTK_LIBS') if not (tcltk_includes and tcltk_libs): # Resume default configuration search. - return 0 + return False extra_compile_args = tcltk_includes.split() extra_link_args = tcltk_libs.split() @@ -1706,10 +1700,10 @@ def detect_tkinter_explicitly(self): extra_compile_args = extra_compile_args, extra_link_args = extra_link_args, ) - self.extensions.append(ext) - return 1 + self.add_ext(ext) + return True - def detect_tkinter_darwin(self, inc_dirs, lib_dirs): + def _detect_tkinter_macos(self): # The _tkinter module, using frameworks. Since frameworks are quite # different the UNIX search logic is not sharable. from os.path import join, exists @@ -1742,7 +1736,7 @@ def detect_tkinter_darwin(self, inc_dirs, lib_dirs): else: # Tk and Tcl frameworks not found. Normal "unix" tkinter search # will now resume. - return 0 + return False # For 8.4a2, we must add -I options that point inside the Tcl and Tk # frameworks. In later release we should hopefully be able to pass @@ -1795,24 +1789,23 @@ def detect_tkinter_darwin(self, inc_dirs, lib_dirs): extra_compile_args = frameworks[2:], extra_link_args = frameworks, ) - self.extensions.append(ext) - return 1 + self.add_ext(ext) + return True - def detect_tkinter(self, inc_dirs, lib_dirs): + def detect_tkinter(self): # The _tkinter module. # Check whether --with-tcltk-includes and --with-tcltk-libs were # configured or passed into the make target. If so, use these values # to build tkinter and bypass the searches for Tcl and TK in standard # locations. - if self.detect_tkinter_explicitly(): + if self._detect_tkinter_explicitly(): return # Rather than complicate the code below, detecting and building # AquaTk is a separate method. Only one Tkinter will be built on # Darwin - either AquaTk, if it is found, or X11 based Tk. - if (host_platform == 'darwin' and - self.detect_tkinter_darwin(inc_dirs, lib_dirs)): + if MACOS and self._detect_tkinter_macos(): return # Assume we haven't found any of the libraries or include files @@ -1821,9 +1814,9 @@ def detect_tkinter(self, inc_dirs, lib_dirs): tcllib = tklib = tcl_includes = tk_includes = None for version in ['8.6', '86', '8.5', '85', '8.4', '84', '8.3', '83', '8.2', '82', '8.1', '81', '8.0', '80']: - tklib = self.compiler.find_library_file(lib_dirs, + tklib = self.compiler.find_library_file(self.lib_dirs, 'tk' + version) - tcllib = self.compiler.find_library_file(lib_dirs, + tcllib = self.compiler.find_library_file(self.lib_dirs, 'tcl' + version) if tklib and tcllib: # Exit the loop when we've found the Tcl/Tk libraries @@ -1834,33 +1827,37 @@ def detect_tkinter(self, inc_dirs, lib_dirs): # Check for the include files on Debian and {Free,Open}BSD, where # they're put in /usr/include/{tcl,tk}X.Y dotversion = version - if '.' not in dotversion and "bsd" in host_platform.lower(): + if '.' not in dotversion and "bsd" in HOST_PLATFORM.lower(): # OpenBSD and FreeBSD use Tcl/Tk library names like libtcl83.a, # but the include subdirs are named like .../include/tcl8.3. dotversion = dotversion[:-1] + '.' + dotversion[-1] tcl_include_sub = [] tk_include_sub = [] - for dir in inc_dirs: + for dir in self.inc_dirs: tcl_include_sub += [dir + os.sep + "tcl" + dotversion] tk_include_sub += [dir + os.sep + "tk" + dotversion] tk_include_sub += tcl_include_sub - tcl_includes = find_file('tcl.h', inc_dirs, tcl_include_sub) - tk_includes = find_file('tk.h', inc_dirs, tk_include_sub) + tcl_includes = find_file('tcl.h', self.inc_dirs, tcl_include_sub) + tk_includes = find_file('tk.h', self.inc_dirs, tk_include_sub) if (tcllib is None or tklib is None or tcl_includes is None or tk_includes is None): self.announce("INFO: Can't locate Tcl/Tk libs and/or headers", 2) + self.missing.append('_tkinter') return # OK... everything seems to be present for Tcl/Tk. - include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = [] + include_dirs = [] + libs = [] + defs = [] + added_lib_dirs = [] for dir in tcl_includes + tk_includes: if dir not in include_dirs: include_dirs.append(dir) # Check for various platform-specific directories - if host_platform == 'sunos5': + if HOST_PLATFORM == 'sunos5': include_dirs.append('/usr/openwin/include') added_lib_dirs.append('/usr/openwin/lib') elif os.path.exists('/usr/X11R6/include'): @@ -1876,17 +1873,18 @@ def detect_tkinter(self, inc_dirs, lib_dirs): added_lib_dirs.append('/usr/X11/lib') # If Cygwin, then verify that X is installed before proceeding - if host_platform == 'cygwin': + if CYGWIN: x11_inc = find_file('X11/Xlib.h', [], include_dirs) if x11_inc is None: + self.missing.append('_tkinter') return # Check for BLT extension - if self.compiler.find_library_file(lib_dirs + added_lib_dirs, + if self.compiler.find_library_file(self.lib_dirs + added_lib_dirs, 'BLT8.0'): defs.append( ('WITH_BLT', 1) ) libs.append('BLT8.0') - elif self.compiler.find_library_file(lib_dirs + added_lib_dirs, + elif self.compiler.find_library_file(self.lib_dirs + added_lib_dirs, 'BLT'): defs.append( ('WITH_BLT', 1) ) libs.append('BLT') @@ -1895,11 +1893,11 @@ def detect_tkinter(self, inc_dirs, lib_dirs): libs.append('tk'+ version) libs.append('tcl'+ version) - if host_platform in ['aix3', 'aix4']: + if HOST_PLATFORM in ['aix3', 'aix4']: libs.append('ld') # Finally, link with the X11 libraries (not appropriate on cygwin) - if host_platform != "cygwin": + if not CYGWIN: libs.append('X11') ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'], @@ -1908,7 +1906,7 @@ def detect_tkinter(self, inc_dirs, lib_dirs): libraries = libs, library_dirs = added_lib_dirs, ) - self.extensions.append(ext) + self.add_ext(ext) # XXX handle these, but how to detect? # *** Uncomment and edit for PIL (TkImaging) extension only: @@ -1921,8 +1919,7 @@ def detect_tkinter(self, inc_dirs, lib_dirs): def configure_ctypes_darwin(self, ext): # Darwin (OS X) uses preconfigured files, in # the Modules/_ctypes/libffi_osx directory. - srcdir = sysconfig.get_config_var('srcdir') - ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', + ffi_srcdir = os.path.abspath(os.path.join(self.srcdir, 'Modules', '_ctypes', 'libffi_osx')) sources = [os.path.join(ffi_srcdir, p) for p in ['ffi.c', @@ -1947,13 +1944,14 @@ def configure_ctypes_darwin(self, ext): def configure_ctypes(self, ext): if not self.use_system_libffi: - if host_platform == 'darwin': + if MACOS: return self.configure_ctypes_darwin(ext) print('INFO: Could not locate ffi libs and/or headers') return False return True - def detect_ctypes(self, inc_dirs, lib_dirs): + def detect_ctypes(self): + # Thomas Heller's _ctypes module self.use_system_libffi = False include_dirs = [] extra_compile_args = [] @@ -1965,15 +1963,15 @@ def detect_ctypes(self, inc_dirs, lib_dirs): '_ctypes/cfield.c'] depends = ['_ctypes/ctypes.h'] - if host_platform == 'darwin': + if MACOS: sources.append('_ctypes/malloc_closure.c') sources.append('_ctypes/darwin/dlfcn_simple.c') extra_compile_args.append('-DMACOSX') include_dirs.append('_ctypes/darwin') -# XXX Is this still needed? -## extra_link_args.extend(['-read_only_relocs', 'warning']) + # XXX Is this still needed? + # extra_link_args.extend(['-read_only_relocs', 'warning']) - elif host_platform == 'sunos5': + elif HOST_PLATFORM == 'sunos5': # XXX This shouldn't be necessary; it appears that some # of the assembler code is non-PIC (i.e. it has relocations # when it shouldn't. The proper fix would be to rewrite @@ -1984,7 +1982,7 @@ def detect_ctypes(self, inc_dirs, lib_dirs): # finding some -z option for the Sun compiler. extra_link_args.append('-mimpure-text') - elif host_platform.startswith('hp-ux'): + elif HOST_PLATFORM.startswith('hp-ux'): extra_link_args.append('-fPIC') ext = Extension('_ctypes', @@ -1994,22 +1992,26 @@ def detect_ctypes(self, inc_dirs, lib_dirs): libraries=[], sources=sources, depends=depends) - # function my_sqrt() needs libm for sqrt() - ext_test = Extension('_ctypes_test', - sources=['_ctypes/_ctypes_test.c'], - libraries=['m']) - self.extensions.extend([ext, ext_test]) + self.add_ext(ext) - if host_platform == 'darwin': + if TEST_EXTENSIONS: + # function my_sqrt() needs MATH_LIBS for sqrt() + ext_test = Extension('_ctypes_test', + sources=['_ctypes/_ctypes_test.c'], + libraries=MATH_LIBS) + self.add_ext(ext_test) + + ffi_inc_dirs = self.inc_dirs.copy() + if MACOS: if '--with-system-ffi' not in sysconfig.get_config_var("CONFIG_ARGS"): return # OS X 10.5 comes with libffi.dylib; the include files are # in /usr/include/ffi - inc_dirs.append('/usr/include/ffi') + ffi_inc_dirs.append('/usr/include/ffi') ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] if not ffi_inc or ffi_inc[0] == '': - ffi_inc = find_file('ffi.h', [], inc_dirs) + ffi_inc = find_file('ffi.h', [], ffi_inc_dirs) if ffi_inc is not None: ffi_h = ffi_inc[0] + '/ffi.h' if not os.path.exists(ffi_h): @@ -2018,7 +2020,7 @@ def detect_ctypes(self, inc_dirs, lib_dirs): ffi_lib = None if ffi_inc is not None: for lib_name in ('ffi', 'ffi_pic'): - if (self.compiler.find_library_file(lib_dirs, lib_name)): + if (self.compiler.find_library_file(self.lib_dirs, lib_name)): ffi_lib = lib_name break @@ -2031,7 +2033,8 @@ def detect_ctypes(self, inc_dirs, lib_dirs): # for dlopen, see bpo-32647 ext.libraries.append('dl') - def _decimal_ext(self): + def detect_decimal(self): + # Stefan Krah's _decimal module extra_compile_args = [] undef_macros = [] if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"): @@ -2040,12 +2043,11 @@ def _decimal_ext(self): sources = ['_decimal/_decimal.c'] depends = ['_decimal/docstrings.h'] else: - srcdir = sysconfig.get_config_var('srcdir') - include_dirs = [os.path.abspath(os.path.join(srcdir, + include_dirs = [os.path.abspath(os.path.join(self.srcdir, 'Modules', '_decimal', 'libmpdec'))] - libraries = ['m'] + libraries = MATH_LIBS sources = [ '_decimal/_decimal.c', '_decimal/libmpdec/basearith.c', @@ -2101,7 +2103,7 @@ def _decimal_ext(self): if machine: # Override automatic configuration to facilitate testing. define_macros = config[machine] - elif host_platform == 'darwin': + elif MACOS: # Universal here means: build with the same options Python # was built with. define_macros = config['universal'] @@ -2115,7 +2117,7 @@ def _decimal_ext(self): elif sizeof_size_t == 4: ppro = sysconfig.get_config_var('HAVE_GCC_ASM_FOR_X87') if ppro and ('gcc' in cc or 'clang' in cc) and \ - not 'sunos' in host_platform: + not 'sunos' in HOST_PLATFORM: # solaris: problems with register allocation. # icc >= 11.0 works as well. define_macros = config['ppro'] @@ -2148,9 +2150,10 @@ def _decimal_ext(self): sources=sources, depends=depends ) - return ext + self.add_ext(ext) - def _detect_openssl(self, inc_dirs, lib_dirs): + def detect_openssl_hashlib(self): + # Detect SSL support for the socket module (via _ssl) config_vars = sysconfig.get_config_vars() def split_var(name, sep): @@ -2173,14 +2176,14 @@ def split_var(name, sep): # Find OpenSSL includes ssl_incs = find_file( - 'openssl/ssl.h', inc_dirs, openssl_includes + 'openssl/ssl.h', self.inc_dirs, openssl_includes ) if ssl_incs is None: return None, None # OpenSSL 1.0.2 uses Kerberos for KRB5 ciphers krb5_h = find_file( - 'krb5.h', inc_dirs, + 'krb5.h', self.inc_dirs, ['/usr/kerberos/include'] ) if krb5_h: @@ -2194,22 +2197,56 @@ def split_var(name, sep): libraries=openssl_libs, depends=['socketmodule.h'] ) + self.add_ext(ssl_ext) else: - ssl_ext = None + self.missing.append('_ssl') + # _hashlib module + hashlib_depends = ['hashlib.h', + # hashlib.h includes pythread.h + 'pythread.h'] hashlib_ext = Extension( '_hashlib', ['_hashopenssl.c'], - depends=['hashlib.h'], + depends=hashlib_depends, include_dirs=openssl_includes, library_dirs=openssl_libdirs, libraries=openssl_libs, ) + self.add_ext(hashlib_ext) + + # We always compile these even when OpenSSL is available (issue #14693). + # It's harmless and the object code is tiny (40-50 KiB per module, + # only loaded when actually used). + self.add_ext( Extension('_sha256', ['sha256module.c'], + depends=hashlib_depends) ) + self.add_ext( Extension('_sha512', ['sha512module.c'], + depends=hashlib_depends) ) + self.add_ext( Extension('_md5', ['md5module.c'], + depends=hashlib_depends) ) + self.add_ext( Extension('_sha1', ['sha1module.c'], + depends=hashlib_depends) ) + + blake2_deps = glob(os.path.join(self.srcdir, + 'Modules/_blake2/impl/*')) + blake2_deps.extend(hashlib_depends) + + self.add_ext( Extension('_blake2', + ['_blake2/blake2module.c', + '_blake2/blake2b_impl.c', + '_blake2/blake2s_impl.c'], + depends=blake2_deps) ) - return ssl_ext, hashlib_ext + sha3_deps = glob(os.path.join(self.srcdir, + 'Modules/_sha3/kcp/*')) + sha3_deps.extend(hashlib_depends) + self.add_ext( Extension('_sha3', + ['_sha3/sha3module.c'], + depends=sha3_deps)) - def _detect_nis(self, inc_dirs, lib_dirs): - if host_platform in {'win32', 'cygwin', 'qnx6'}: - return None + def detect_nis(self): + if MS_WINDOWS or CYGWIN or HOST_PLATFORM == 'qnx6': + self.missing.append('nis') + return libs = [] library_dirs = [] @@ -2219,38 +2256,40 @@ def _detect_nis(self, inc_dirs, lib_dirs): # moved headers and libraries to libtirpc and libnsl. The headers # are in tircp and nsl sub directories. rpcsvc_inc = find_file( - 'rpcsvc/yp_prot.h', inc_dirs, - [os.path.join(inc_dir, 'nsl') for inc_dir in inc_dirs] + 'rpcsvc/yp_prot.h', self.inc_dirs, + [os.path.join(inc_dir, 'nsl') for inc_dir in self.inc_dirs] ) rpc_inc = find_file( - 'rpc/rpc.h', inc_dirs, - [os.path.join(inc_dir, 'tirpc') for inc_dir in inc_dirs] + 'rpc/rpc.h', self.inc_dirs, + [os.path.join(inc_dir, 'tirpc') for inc_dir in self.inc_dirs] ) if rpcsvc_inc is None or rpc_inc is None: # not found - return None + self.missing.append('nis') + return includes_dirs.extend(rpcsvc_inc) includes_dirs.extend(rpc_inc) - if self.compiler.find_library_file(lib_dirs, 'nsl'): + if self.compiler.find_library_file(self.lib_dirs, 'nsl'): libs.append('nsl') else: # libnsl-devel: check for libnsl in nsl/ subdirectory - nsl_dirs = [os.path.join(lib_dir, 'nsl') for lib_dir in lib_dirs] + nsl_dirs = [os.path.join(lib_dir, 'nsl') for lib_dir in self.lib_dirs] libnsl = self.compiler.find_library_file(nsl_dirs, 'nsl') if libnsl is not None: library_dirs.append(os.path.dirname(libnsl)) libs.append('nsl') - if self.compiler.find_library_file(lib_dirs, 'tirpc'): + if self.compiler.find_library_file(self.lib_dirs, 'tirpc'): libs.append('tirpc') - return Extension( + ext = Extension( 'nis', ['nismodule.c'], libraries=libs, library_dirs=library_dirs, include_dirs=includes_dirs ) + self.add_ext(ext) class PyBuildInstall(install): @@ -2300,6 +2339,7 @@ def set_dir_modes(self, dirname, mode): log.info("changing mode of %s to %o", dirpath, mode) if not self.dry_run: os.chmod(dirpath, mode) + class PyBuildScripts(build_scripts): def copy_scripts(self): outfiles, updated_files = build_scripts.copy_scripts(self) @@ -2319,35 +2359,14 @@ def copy_scripts(self): newupdated_files.append(newfilename) return newoutfiles, newupdated_files -SUMMARY = """ -Python is an interpreted, interactive, object-oriented programming -language. It is often compared to Tcl, Perl, Scheme or Java. - -Python combines remarkable power with very clear syntax. It has -modules, classes, exceptions, very high level dynamic data types, and -dynamic typing. There are interfaces to many system calls and -libraries, as well as to various windowing systems (X11, Motif, Tk, -Mac, MFC). New built-in modules are easily written in C or C++. Python -is also usable as an extension language for applications that need a -programmable interface. -The Python implementation is portable: it runs on many brands of UNIX, -on Windows, DOS, Mac, Amiga... If your favorite system isn't -listed here, it may still be supported, if there's a C compiler for -it. Ask around on comp.lang.python -- or just try compiling Python -yourself. -""" +def main(): + set_compiler_flags('CFLAGS', 'PY_CFLAGS_NODIST') + set_compiler_flags('LDFLAGS', 'PY_LDFLAGS_NODIST') -CLASSIFIERS = """ -Development Status :: 6 - Mature -License :: OSI Approved :: Python Software Foundation License -Natural Language :: English -Programming Language :: C -Programming Language :: Python -Topic :: Software Development -""" + # Hack for parallel build + sys.modules['concurrent.futures.process'] = DummyProcess -def main(): # turn off warnings when deprecated modules are imported import warnings warnings.filterwarnings("ignore",category=DeprecationWarning)