diff --git a/Makefile.pre.in b/Makefile.pre.in index 14e7f6035578be..5762d9565fce64 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -582,8 +582,8 @@ LIBEXPAT_HEADERS= \ # Default target all: @DEF_MAKE_ALL_RULE@ build_all: check-clean-src $(BUILDPYTHON) platform oldsharedmods sharedmods \ - gdbhooks Programs/_testembed scripts -build_wasm: check-clean-src $(BUILDPYTHON) platform oldsharedmods python-config + gdbhooks Programs/_testembed scripts checkoldsharedmods +build_wasm: check-clean-src $(BUILDPYTHON) platform oldsharedmods python-config checkoldsharedmods # Check that the source is clean when building out of source. check-clean-src: @@ -909,7 +909,7 @@ $(LIBEXPAT_A): $(LIBEXPAT_OBJS) # create relative links from build/lib.platform/egg.so to Modules/egg.so # pybuilddir.txt is created too late. We cannot use it in Makefile # targets. ln --relative is not portable. -oldsharedmods: $(SHAREDMODS) pybuilddir.txt +oldsharedmods: $(SHAREDMODS) $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt @target=`cat pybuilddir.txt`; \ $(MKDIR_P) $$target; \ for mod in X $(SHAREDMODS); do \ @@ -918,6 +918,9 @@ oldsharedmods: $(SHAREDMODS) pybuilddir.txt fi; \ done +checkoldsharedmods: oldsharedmods $(BUILDPYTHON) + @$(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/scripts/check_modules.py + Modules/Setup.local: @# Create empty Setup.local when file was deleted by user echo "# Edit this file for local setup changes" > $@ @@ -938,7 +941,7 @@ Makefile Modules/config.c: Makefile.pre \ $(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \ -s Modules \ Modules/Setup.local \ - @MODULES_SETUP_STDLIB@ \ + Modules/Setup.stdlib \ Modules/Setup.bootstrap \ $(srcdir)/Modules/Setup @mv config.c Modules @@ -2531,7 +2534,8 @@ update-config: Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h # Declare targets that aren't real files -.PHONY: all build_all build_wasm sharedmods check-clean-src oldsharedmods test quicktest +.PHONY: all build_all build_wasm sharedmods check-clean-src oldsharedmods +.PHONY: checkoldsharedmods test quicktest .PHONY: install altinstall oldsharedinstall bininstall altbininstall .PHONY: maninstall libinstall inclinstall libainstall sharedinstall .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure diff --git a/Misc/NEWS.d/next/Build/2022-06-28-09-42-10.gh-issue-93939._VWxKW.rst b/Misc/NEWS.d/next/Build/2022-06-28-09-42-10.gh-issue-93939._VWxKW.rst new file mode 100644 index 00000000000000..39410dfacd25e4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-06-28-09-42-10.gh-issue-93939._VWxKW.rst @@ -0,0 +1,2 @@ +Most stdlib extension modules are now built by ``configure`` and ``make`` +instead of :mod:`distutils` and ``setup.py``. diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index a199aefc510114..ba69ac32cd9f06 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -128,7 +128,7 @@ # multiprocessing @MODULE__POSIXSHMEM_TRUE@_posixshmem _multiprocessing/posixshmem.c -@MODULE__MULTIPROCESSING_TRUE@_multiprocessing _multiprocessing/multiprocessing.c _multiprocessing/semaphore.c +@MODULE__MULTIPROCESSING_TRUE@_multiprocessing _multiprocessing/multiprocessing.c @MODULE__MULTIPROCESSING_SEMAPHORE_C@ ############################################################################ diff --git a/Tools/scripts/check_modules.py b/Tools/scripts/check_modules.py new file mode 100644 index 00000000000000..fb616c158250ba --- /dev/null +++ b/Tools/scripts/check_modules.py @@ -0,0 +1,362 @@ +"""Check shared extension modules +""" + +import argparse +import collections +import enum +import importlib._bootstrap +from importlib.machinery import BuiltinImporter, ExtensionFileLoader, ModuleSpec +from importlib.util import spec_from_file_location, spec_from_loader +import os +import pathlib +import logging +import sys +import sysconfig +import warnings + + +logger = logging.getLogger(__name__) + +parser = argparse.ArgumentParser( + prog="check_shared_ext", description="Check shared extension modules" +) +parser.add_argument( + "--debug", + action="store_true", + help="Enable debug logging", +) +parser.add_argument( + "--list-module-names", + action="store_true", + help="Print a list of module names to stdout", +) + + +def validate_tzpath(): + base_tzpath = sysconfig.get_config_var("TZPATH") + if not base_tzpath: + return + + tzpaths = base_tzpath.split(os.pathsep) + bad_paths = [tzpath for tzpath in tzpaths if not os.path.isabs(tzpath)] + if bad_paths: + raise ValueError( + "TZPATH must contain only absolute paths, found:\n" + f"{tzpaths!r}\n" + "with invalid paths:\n" + f"{bad_paths!r}" + ) + + +class ModuleState(enum.Enum): + YES = "yes" + DISABLED = "disabled" + MISSING = "missing" + NA = "n/a" + # disabled by Setup / makesetup rule + DISABLED_SETUP = "disabled_setup" + + def __bool__(self): + return self.value == "yes" + + +ModuleInfo = collections.namedtuple("ModuleInfo", "name state is_builtin builddir_path") + + +class CheckExtensions: + pybuilddir_txt = "pybuilddir.txt" + # defined in Modules/config.h.in + config_h_modules = frozenset( + { + "_ast", + "_imp", + "_string", + "_tokenize", + "_warnings", + "builtins", + "gc", + "marshal", + "sys", + } + ) + # built by setup.py + setup_py_modules = frozenset({"_curses", "_curses_panel", "_dbm", "readline"}) + # Windows-only modules + windows_modules = frozenset( + { + "_msi", + "_overlapped", + "_testconsole", + "_winapi", + "msvcrt", + "nt", + "winreg", + "winsound", + } + ) + + def __init__(self): + self.cross_compiling = "_PYTHON_HOST_PLATFORM" in os.environ + self.strict_extensions_build = os.environ.get("PYTHONSTRICTEXTENSIONBUILD") + self.ext_suffix = sysconfig.get_config_var("EXT_SUFFIX") + self.platform = sysconfig.get_platform() + self.builddir = self.get_builddir() + self.modules = self.get_makefile_modules() + + self.builtin_ok = [] + self.shared_ok = [] + self.failed_on_import = [] + self.missing = [] + self.disabled_configure = [] + self.disabled_setup = [] + self.notavailable = [] + + def check(self): + for modinfo in self.modules: + logger.debug("Checking '%s' (%s)", modinfo.name, modinfo.builddir_path) + if modinfo.state == ModuleState.DISABLED: + self.disabled_configure.append(modinfo) + elif modinfo.state == ModuleState.DISABLED_SETUP: + self.disabled_setup.append(modinfo) + elif modinfo.state == ModuleState.MISSING: + self.missing.append(modinfo) + elif modinfo.state == ModuleState.NA: + self.notavailable.append(modinfo) + else: + try: + if self.cross_compiling: + self.check_module_cross(modinfo) + else: + self.check_module_import(modinfo) + except (ImportError, FileNotFoundError): + self.rename_module(modinfo) + self.failed_on_import.append(modinfo) + else: + if modinfo.is_builtin: + self.builtin_ok.append(modinfo) + else: + self.shared_ok.append(modinfo) + + def summary(self, *, verbose: bool = False): + longest = max([len(e.name) for e in self.modules], default=0) + + def print_three_column(modinfos: list[ModuleInfo]): + names = [modinfo.name for modinfo in modinfos] + names.sort(key=str.lower) + # guarantee zip() doesn't drop anything + while len(names) % 3: + names.append("") + for l, m, r in zip(names[::3], names[1::3], names[2::3]): + print("%-*s %-*s %-*s" % (longest, l, longest, m, longest, r)) + + if verbose and self.builtin_ok: + print("The following built-in modules have been successfully built:") + print_three_column(self.builtin_ok) + print() + + if verbose and self.shared_ok: + print("The following shared modules have been successfully built:") + print_three_column(self.shared_ok) + print() + + if self.disabled_configure: + print("The following modules are *disabled* in configure script:") + print_three_column(self.disabled_configure) + print() + + if self.disabled_setup: + print("The following modules are *disabled* in Modules/Setup files:") + print_three_column(self.disabled_setup) + print() + + if verbose and self.notavailable: + print(f"The following modules are not available on {self.platform}:") + print_three_column(self.notavailable) + print() + + if self.missing: + print("The necessary bits to build these optional modules were not found:") + print_three_column(self.missing) + print("To find the necessary bits, look in configure.ac and config.log.") + print() + + if self.failed_on_import: + print( + "Following modules built successfully " + "but were removed because they could not be imported:" + ) + print_three_column(self.failed_on_import) + print() + + if any( + modinfo.name == "_ssl" for modinfo in self.missing + self.failed_on_import + ): + print("Could not build the ssl module!") + print("Python requires a OpenSSL 1.1.1 or newer") + if sysconfig.get_config_var("OPENSSL_LDFLAGS"): + print("Custom linker flags may require --with-openssl-rpath=auto") + print() + + disabled = len(self.disabled_configure) + len(self.disabled_setup) + print( + f"Checked {len(self.modules)} modules (" + f"{len(self.builtin_ok)} built-in, " + f"{len(self.shared_ok)} shared, " + f"{len(self.notavailable)} n/a on {self.platform}, " + f"{disabled} disabled, " + f"{len(self.missing)} missing, " + f"{len(self.failed_on_import)} failed on import)" + ) + + def check_strict_build(self): + """Fail if modules are missing and it's a strict build""" + if self.strict_extensions_build and (self.failed_on_import or self.missing): + raise RuntimeError("Failed to build some stdlib modules") + + def list_module_names(self, *, all: bool = False) -> set: + names = {modinfo.name for modinfo in self.modules} + if all: + names.update(self.config_h_modules) + names.update(self.setup_py_modules) + names.update(self.windows_modules) + return names + + def get_builddir(self) -> pathlib.Path: + with open(self.pybuilddir_txt, encoding="utf-8") as f: + builddir = f.read() + builddir = pathlib.Path(builddir) + logger.debug("%s: %s", self.pybuilddir_txt, builddir) + return builddir + + def get_makefile_modules(self) -> list[ModuleInfo]: + """Get list of modules from Makefile + + MODBUILT_NAMES: modules in *static* block + MODSHARED_NAMES: modules in *shared* block + MODDISABLED_NAMES: modules in *disabled* block + + Modules built by setup.py addext() have a MODULE_{modname}_STATE entry, + but are not listed in MODSHARED_NAMES. + + Modules built by old-style setup.py add() have neither a MODULE_{modname} + entry nor an entry in MODSHARED_NAMES. + """ + moddisabled = set(sysconfig.get_config_var("MODDISABLED_NAMES").split()) + if self.cross_compiling: + modbuiltin = set(sysconfig.get_config_var("MODBUILT_NAMES").split()) + else: + modbuiltin = set(sys.builtin_module_names) + + modules = [] + for key, value in sysconfig.get_config_vars().items(): + if not key.startswith("MODULE_") or not key.endswith("_STATE"): + continue + if value not in {"yes", "disabled", "missing", "n/a"}: + raise ValueError(f"Unsupported value '{value}' for {key}") + + modname = key[7:-6].lower() + is_builtin = modname in modbuiltin + if modname in moddisabled: + # Setup "*disabled*" rule + state = ModuleState.DISABLED_SETUP + else: + try: + state = ModuleState(value) + except ValueError: + logger.exception("Invalid module state for %s", modname) + raise + + if is_builtin: + builddir_path = None + else: + builddir_path = self.builddir / f"{modname}{self.ext_suffix}" + + modules.append(ModuleInfo(modname, state, is_builtin, builddir_path)) + + modules.sort() + return modules + + def get_spec(self, modinfo: ModuleInfo) -> ModuleSpec: + """Get ModuleSpec for builtin or extension module""" + if modinfo.is_builtin: + return spec_from_loader(modinfo.name, loader=BuiltinImporter) + else: + location = os.fspath(modinfo.builddir_path) + loader = ExtensionFileLoader(modinfo.name, location) + return spec_from_file_location(modinfo.name, location, loader=loader) + + def check_module_import(self, modinfo: ModuleInfo): + """Attempt to import module and report errors""" + spec = self.get_spec(modinfo) + try: + with warnings.catch_warnings(): + # ignore deprecation warning from deprecated modules + warnings.simplefilter("ignore", DeprecationWarning) + importlib._bootstrap._load(spec) + except ImportError as e: + logger.error("%s failed to import: %s", modinfo.name, e) + raise + except Exception as e: + logger.exception("Importing extension '%s' failed!", modinfo.name) + raise + + def check_module_cross(self, modinfo: ModuleInfo): + """Sanity check for cross compiling""" + spec = self.get_spec(modinfo) + if spec.loader is BuiltinImporter: + return + st = os.stat(spec.origin) + if not st.st_size: + raise ImportError(f"{spec.origin} is an empty file") + + def rename_module(self, modinfo: ModuleInfo) -> None: + """Rename module file""" + if modinfo.builddir_path is None: + logger.error("Cannot mark builtin module '%s' as failed!", modinfo.name) + return + + failed_name = f"{modinfo.name}_failed{self.ext_suffix}" + if modinfo.builddir_path.is_symlink(): + symlink = modinfo.builddir_path + module_path = modinfo.builddir_path.resolve().relative_to(os.getcwd()) + failed_path = module_path.parent / failed_name + else: + symlink = None + module_path = modinfo.builddir_path + failed_path = self.builddir / failed_name + + # remove old failed file + failed_path.unlink(missing_ok=True) + # remove symlink + if symlink is not None: + symlink.unlink(missing_ok=True) + # rename shared extension file + try: + module_path.rename(failed_path) + except FileNotFoundError: + logger.debug("Shared extension file '%s' does not exist.", module_path) + else: + logger.debug("Rename '%s' -> '%s'", module_path, failed_path) + + +def main(): + args = parser.parse_args() + logging.basicConfig( + level=logging.DEBUG if args.debug else logging.INFO, + format="[%(levelname)s] %(message)s", + ) + + checker = CheckExtensions() + if args.list_module_names: + names = checker.list_module_names(all=True) + for name in sorted(names): + print(name) + else: + checker.check() + checker.summary(verbose=args.debug) + checker.check_strict_build() + validate_tzpath() + + +if __name__ == "__main__": + main() diff --git a/Tools/scripts/generate_stdlib_module_names.py b/Tools/scripts/generate_stdlib_module_names.py index 6f864c317da6c8..5eb15177e607be 100644 --- a/Tools/scripts/generate_stdlib_module_names.py +++ b/Tools/scripts/generate_stdlib_module_names.py @@ -8,10 +8,10 @@ import sysconfig -SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) +HERE = os.path.dirname(__file__) +SRC_DIR = os.path.dirname(os.path.dirname(HERE)) STDLIB_PATH = os.path.join(SRC_DIR, 'Lib') -MODULES_SETUP = os.path.join(SRC_DIR, 'Modules', 'Setup') -SETUP_PY = os.path.join(SRC_DIR, 'setup.py') +CHECK_MODULES = os.path.join(HERE, 'check_modules.py') IGNORE = { '__init__', @@ -41,23 +41,6 @@ 'xxsubtype', } -# Windows extension modules -WINDOWS_MODULES = ( - '_msi', - '_overlapped', - '_testconsole', - '_winapi', - 'msvcrt', - 'nt', - 'winreg', - 'winsound' -) - -# macOS extension modules -MACOS_MODULES = ( - '_scproxy', -) - # Pure Python modules (Lib/*.py) def list_python_modules(names): for filename in os.listdir(STDLIB_PATH): @@ -80,39 +63,15 @@ def list_packages(names): names.add(name) -# Extension modules built by setup.py -def list_setup_extensions(names): - cmd = [sys.executable, SETUP_PY, "-q", "build", "--list-module-names"] - output = subprocess.check_output(cmd) - output = output.decode("utf8") +# Built-in and extension modules built by Modules/Setup* +# also lists Windows modules, internal modules, and modules have not +# been ported from setup.py to Modules/Setup +def list_modules_check_modules(names): + cmd = [sys.executable, CHECK_MODULES, "--list-module-names"] + output = subprocess.check_output(cmd, text=True) extensions = output.splitlines() names |= set(extensions) - -# Built-in and extension modules built by Modules/Setup -def list_modules_setup_extensions(names): - assign_var = re.compile("^[A-Z]+=") - - with open(MODULES_SETUP, encoding="utf-8") as modules_fp: - for line in modules_fp: - # Strip comment - line = line.partition("#")[0] - line = line.rstrip() - if not line: - continue - if assign_var.match(line): - # Ignore "VAR=VALUE" - continue - if line in ("*disabled*", "*shared*"): - continue - parts = line.split() - if len(parts) < 2: - continue - # "errno errnomodule.c" => write "errno" - name = parts[0] - names.add(name) - - # List frozen modules of the PyImport_FrozenModules list (Python/frozen.c). # Use the "./Programs/_testembed list_frozen" command. def list_frozen(names): @@ -134,9 +93,9 @@ def list_frozen(names): def list_modules(): - names = set(sys.builtin_module_names) | set(WINDOWS_MODULES) | set(MACOS_MODULES) - list_modules_setup_extensions(names) - list_setup_extensions(names) + names = set(sys.builtin_module_names) + list_modules_check_modules(names) + # list_setup_extensions(names) list_packages(names) list_python_modules(names) list_frozen(names) diff --git a/configure b/configure index 2bd64fc1620a2d..e0fb8da01a1f09 100755 --- a/configure +++ b/configure @@ -774,11 +774,46 @@ MODULE__ASYNCIO_FALSE MODULE__ASYNCIO_TRUE MODULE_ARRAY_FALSE MODULE_ARRAY_TRUE +MODULE__SYMTABLE_FALSE +MODULE__SYMTABLE_TRUE +MODULE__STAT_FALSE +MODULE__STAT_TRUE +MODULE__OPERATOR_FALSE +MODULE__OPERATOR_TRUE +MODULE__LOCALE_FALSE +MODULE__LOCALE_TRUE +MODULE__FUNCTOOLS_FALSE +MODULE__FUNCTOOLS_TRUE +MODULE__ABC_FALSE +MODULE__ABC_TRUE +MODULE__WEAKREF_FALSE +MODULE__WEAKREF_TRUE MODULE_TIME_FALSE MODULE_TIME_TRUE +MODULE__THREAD_FALSE +MODULE__THREAD_TRUE +MODULE__SRE_FALSE +MODULE__SRE_TRUE +MODULE_ITERTOOLS_FALSE +MODULE_ITERTOOLS_TRUE MODULE__IO_FALSE MODULE__IO_TRUE -MODULES_SETUP_STDLIB +MODULE_ERRNO_FALSE +MODULE_ERRNO_TRUE +MODULE__COLLECTIONS_FALSE +MODULE__COLLECTIONS_TRUE +MODULE__CODECS_FALSE +MODULE__CODECS_TRUE +MODULE__TRACEMALLOC_FALSE +MODULE__TRACEMALLOC_TRUE +MODULE__SIGNAL_FALSE +MODULE__SIGNAL_TRUE +MODULE_POSIX_FALSE +MODULE_POSIX_TRUE +MODULE_FAULTHANDLER_FALSE +MODULE_FAULTHANDLER_TRUE +MODULE_ATEXIT_FALSE +MODULE_ATEXIT_TRUE MODULE_BUILDTYPE TEST_MODULES LIBB2_LIBS @@ -799,6 +834,7 @@ LIBPYTHON EXT_SUFFIX ALT_SOABI SOABI +MODULE__MULTIPROCESSING_SEMAPHORE_C LIBC LIBM HAVE_GETHOSTBYNAME @@ -10456,7 +10492,7 @@ case $ac_sys_system/$ac_sys_release in LIBTOOL_CRUFT="${LIBTOOL_CRUFT} -arch_only `/usr/bin/arch`" fi LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' - LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';; + LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VfpoiERSION)';; Darwin/*) gcc_version=`gcc -dumpversion` if test ${gcc_version} '<' 4.0 @@ -19752,6 +19788,11 @@ $as_echo "#define HAVE_BROKEN_SEM_GETVALUE 1" >>confdefs.h fi +if test "$ac_cv_func_sem_open" = "yes" -a "$ac_cv_posix_semaphores_enabled" = "yes"; then + MODULE__MULTIPROCESSING_SEMAPHORE_C=_multiprocessing/semaphore.c +fi + + ac_fn_c_check_decl "$LINENO" "RTLD_LAZY" "ac_cv_have_decl_RTLD_LAZY" "#include " if test "x$ac_cv_have_decl_RTLD_LAZY" = xyes; then : @@ -23089,28 +23130,173 @@ case $host_cpu in #( esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for additional Modules/Setup files" >&5 -$as_echo_n "checking for additional Modules/Setup files... " >&6; } -case $ac_sys_system in #( - Emscripten) : - MODULES_SETUP_STDLIB=Modules/Setup.stdlib ;; #( - WASI) : - MODULES_SETUP_STDLIB=Modules/Setup.stdlib ;; #( - *) : - MODULES_SETUP_STDLIB= - ;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MODULES_SETUP_STDLIB" >&5 -$as_echo "$MODULES_SETUP_STDLIB" >&6; } +MODULE_BLOCK= -MODULE_BLOCK= + if test "$py_cv_module_atexit" != "n/a"; then : + py_cv_module_atexit=yes +fi + if test "$py_cv_module_atexit" = yes; then + MODULE_ATEXIT_TRUE= + MODULE_ATEXIT_FALSE='#' +else + MODULE_ATEXIT_TRUE='#' + MODULE_ATEXIT_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE_ATEXIT_STATE=$py_cv_module_atexit$as_nl" + if test "x$py_cv_module_atexit" = xyes; then : + + + + +fi + + + if test "$py_cv_module_faulthandler" != "n/a"; then : + py_cv_module_faulthandler=yes +fi + if test "$py_cv_module_faulthandler" = yes; then + MODULE_FAULTHANDLER_TRUE= + MODULE_FAULTHANDLER_FALSE='#' +else + MODULE_FAULTHANDLER_TRUE='#' + MODULE_FAULTHANDLER_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE_FAULTHANDLER_STATE=$py_cv_module_faulthandler$as_nl" + if test "x$py_cv_module_faulthandler" = xyes; then : + + + + +fi + + + if test "$py_cv_module_posix" != "n/a"; then : + py_cv_module_posix=yes +fi + if test "$py_cv_module_posix" = yes; then + MODULE_POSIX_TRUE= + MODULE_POSIX_FALSE='#' +else + MODULE_POSIX_TRUE='#' + MODULE_POSIX_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE_POSIX_STATE=$py_cv_module_posix$as_nl" + if test "x$py_cv_module_posix" = xyes; then : + + + + +fi + + + if test "$py_cv_module__signal" != "n/a"; then : + py_cv_module__signal=yes +fi + if test "$py_cv_module__signal" = yes; then + MODULE__SIGNAL_TRUE= + MODULE__SIGNAL_FALSE='#' +else + MODULE__SIGNAL_TRUE='#' + MODULE__SIGNAL_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__SIGNAL_STATE=$py_cv_module__signal$as_nl" + if test "x$py_cv_module__signal" = xyes; then : + + + + +fi + + + if test "$py_cv_module__tracemalloc" != "n/a"; then : + py_cv_module__tracemalloc=yes +fi + if test "$py_cv_module__tracemalloc" = yes; then + MODULE__TRACEMALLOC_TRUE= + MODULE__TRACEMALLOC_FALSE='#' +else + MODULE__TRACEMALLOC_TRUE='#' + MODULE__TRACEMALLOC_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__TRACEMALLOC_STATE=$py_cv_module__tracemalloc$as_nl" + if test "x$py_cv_module__tracemalloc" = xyes; then : + + + + +fi + + + if test "$py_cv_module__codecs" != "n/a"; then : + py_cv_module__codecs=yes +fi + if test "$py_cv_module__codecs" = yes; then + MODULE__CODECS_TRUE= + MODULE__CODECS_FALSE='#' +else + MODULE__CODECS_TRUE='#' + MODULE__CODECS_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__CODECS_STATE=$py_cv_module__codecs$as_nl" + if test "x$py_cv_module__codecs" = xyes; then : + + + + +fi + + + if test "$py_cv_module__collections" != "n/a"; then : + py_cv_module__collections=yes +fi + if test "$py_cv_module__collections" = yes; then + MODULE__COLLECTIONS_TRUE= + MODULE__COLLECTIONS_FALSE='#' +else + MODULE__COLLECTIONS_TRUE='#' + MODULE__COLLECTIONS_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__COLLECTIONS_STATE=$py_cv_module__collections$as_nl" + if test "x$py_cv_module__collections" = xyes; then : + + + + +fi + + + if test "$py_cv_module_errno" != "n/a"; then : + py_cv_module_errno=yes +fi + if test "$py_cv_module_errno" = yes; then + MODULE_ERRNO_TRUE= + MODULE_ERRNO_FALSE='#' +else + MODULE_ERRNO_TRUE='#' + MODULE_ERRNO_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE_ERRNO_STATE=$py_cv_module_errno$as_nl" + if test "x$py_cv_module_errno" = xyes; then : + + + + +fi if test "$py_cv_module__io" != "n/a"; then : @@ -23130,6 +23316,66 @@ fi as_fn_append MODULE_BLOCK "MODULE__IO_CFLAGS=-I\$(srcdir)/Modules/_io$as_nl" +fi + + + if test "$py_cv_module_itertools" != "n/a"; then : + py_cv_module_itertools=yes +fi + if test "$py_cv_module_itertools" = yes; then + MODULE_ITERTOOLS_TRUE= + MODULE_ITERTOOLS_FALSE='#' +else + MODULE_ITERTOOLS_TRUE='#' + MODULE_ITERTOOLS_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE_ITERTOOLS_STATE=$py_cv_module_itertools$as_nl" + if test "x$py_cv_module_itertools" = xyes; then : + + + + +fi + + + if test "$py_cv_module__sre" != "n/a"; then : + py_cv_module__sre=yes +fi + if test "$py_cv_module__sre" = yes; then + MODULE__SRE_TRUE= + MODULE__SRE_FALSE='#' +else + MODULE__SRE_TRUE='#' + MODULE__SRE_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__SRE_STATE=$py_cv_module__sre$as_nl" + if test "x$py_cv_module__sre" = xyes; then : + + + + +fi + + + if test "$py_cv_module__thread" != "n/a"; then : + py_cv_module__thread=yes +fi + if test "$py_cv_module__thread" = yes; then + MODULE__THREAD_TRUE= + MODULE__THREAD_FALSE='#' +else + MODULE__THREAD_TRUE='#' + MODULE__THREAD_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__THREAD_STATE=$py_cv_module__thread$as_nl" + if test "x$py_cv_module__thread" = xyes; then : + + + + fi @@ -23150,6 +23396,146 @@ fi as_fn_append MODULE_BLOCK "MODULE_TIME_LDFLAGS=$TIMEMODULE_LIB$as_nl" +fi + + + if test "$py_cv_module__weakref" != "n/a"; then : + py_cv_module__weakref=yes +fi + if test "$py_cv_module__weakref" = yes; then + MODULE__WEAKREF_TRUE= + MODULE__WEAKREF_FALSE='#' +else + MODULE__WEAKREF_TRUE='#' + MODULE__WEAKREF_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__WEAKREF_STATE=$py_cv_module__weakref$as_nl" + if test "x$py_cv_module__weakref" = xyes; then : + + + + +fi + + + if test "$py_cv_module__abc" != "n/a"; then : + py_cv_module__abc=yes +fi + if test "$py_cv_module__abc" = yes; then + MODULE__ABC_TRUE= + MODULE__ABC_FALSE='#' +else + MODULE__ABC_TRUE='#' + MODULE__ABC_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__ABC_STATE=$py_cv_module__abc$as_nl" + if test "x$py_cv_module__abc" = xyes; then : + + + + +fi + + + if test "$py_cv_module__functools" != "n/a"; then : + py_cv_module__functools=yes +fi + if test "$py_cv_module__functools" = yes; then + MODULE__FUNCTOOLS_TRUE= + MODULE__FUNCTOOLS_FALSE='#' +else + MODULE__FUNCTOOLS_TRUE='#' + MODULE__FUNCTOOLS_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__FUNCTOOLS_STATE=$py_cv_module__functools$as_nl" + if test "x$py_cv_module__functools" = xyes; then : + + + + +fi + + + if test "$py_cv_module__locale" != "n/a"; then : + py_cv_module__locale=yes +fi + if test "$py_cv_module__locale" = yes; then + MODULE__LOCALE_TRUE= + MODULE__LOCALE_FALSE='#' +else + MODULE__LOCALE_TRUE='#' + MODULE__LOCALE_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__LOCALE_STATE=$py_cv_module__locale$as_nl" + if test "x$py_cv_module__locale" = xyes; then : + + + + +fi + + + if test "$py_cv_module__operator" != "n/a"; then : + py_cv_module__operator=yes +fi + if test "$py_cv_module__operator" = yes; then + MODULE__OPERATOR_TRUE= + MODULE__OPERATOR_FALSE='#' +else + MODULE__OPERATOR_TRUE='#' + MODULE__OPERATOR_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__OPERATOR_STATE=$py_cv_module__operator$as_nl" + if test "x$py_cv_module__operator" = xyes; then : + + + + +fi + + + if test "$py_cv_module__stat" != "n/a"; then : + py_cv_module__stat=yes +fi + if test "$py_cv_module__stat" = yes; then + MODULE__STAT_TRUE= + MODULE__STAT_FALSE='#' +else + MODULE__STAT_TRUE='#' + MODULE__STAT_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__STAT_STATE=$py_cv_module__stat$as_nl" + if test "x$py_cv_module__stat" = xyes; then : + + + + +fi + + + if test "$py_cv_module__symtable" != "n/a"; then : + py_cv_module__symtable=yes +fi + if test "$py_cv_module__symtable" = yes; then + MODULE__SYMTABLE_TRUE= + MODULE__SYMTABLE_FALSE='#' +else + MODULE__SYMTABLE_TRUE='#' + MODULE__SYMTABLE_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__SYMTABLE_STATE=$py_cv_module__symtable$as_nl" + if test "x$py_cv_module__symtable" = xyes; then : + + + + fi @@ -24670,8 +25056,8 @@ $as_echo "$py_cv_module_nis" >&6; } $as_echo_n "checking for stdlib extension module _sqlite3... " >&6; } if test "$py_cv_module__sqlite3" != "n/a"; then : - if test "$have_sqlite3" = "yes"; then : - if test "$have_supported_sqlite3" = "yes"; then : + if true; then : + if test "$have_sqlite3" = "yes" -a "$have_supported_sqlite3" = "yes"; then : py_cv_module__sqlite3=yes else py_cv_module__sqlite3=missing @@ -25388,14 +25774,86 @@ LTLIBOBJS=$ac_ltlibobjs +if test -z "${MODULE_ATEXIT_TRUE}" && test -z "${MODULE_ATEXIT_FALSE}"; then + as_fn_error $? "conditional \"MODULE_ATEXIT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_FAULTHANDLER_TRUE}" && test -z "${MODULE_FAULTHANDLER_FALSE}"; then + as_fn_error $? "conditional \"MODULE_FAULTHANDLER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_POSIX_TRUE}" && test -z "${MODULE_POSIX_FALSE}"; then + as_fn_error $? "conditional \"MODULE_POSIX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SIGNAL_TRUE}" && test -z "${MODULE__SIGNAL_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SIGNAL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__TRACEMALLOC_TRUE}" && test -z "${MODULE__TRACEMALLOC_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TRACEMALLOC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__CODECS_TRUE}" && test -z "${MODULE__CODECS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CODECS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__COLLECTIONS_TRUE}" && test -z "${MODULE__COLLECTIONS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__COLLECTIONS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_ERRNO_TRUE}" && test -z "${MODULE_ERRNO_FALSE}"; then + as_fn_error $? "conditional \"MODULE_ERRNO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__IO_TRUE}" && test -z "${MODULE__IO_FALSE}"; then as_fn_error $? "conditional \"MODULE__IO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_ITERTOOLS_TRUE}" && test -z "${MODULE_ITERTOOLS_FALSE}"; then + as_fn_error $? "conditional \"MODULE_ITERTOOLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SRE_TRUE}" && test -z "${MODULE__SRE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SRE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__THREAD_TRUE}" && test -z "${MODULE__THREAD_FALSE}"; then + as_fn_error $? "conditional \"MODULE__THREAD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_TIME_TRUE}" && test -z "${MODULE_TIME_FALSE}"; then as_fn_error $? "conditional \"MODULE_TIME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__WEAKREF_TRUE}" && test -z "${MODULE__WEAKREF_FALSE}"; then + as_fn_error $? "conditional \"MODULE__WEAKREF\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__ABC_TRUE}" && test -z "${MODULE__ABC_FALSE}"; then + as_fn_error $? "conditional \"MODULE__ABC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__FUNCTOOLS_TRUE}" && test -z "${MODULE__FUNCTOOLS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__FUNCTOOLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__LOCALE_TRUE}" && test -z "${MODULE__LOCALE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__LOCALE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__OPERATOR_TRUE}" && test -z "${MODULE__OPERATOR_FALSE}"; then + as_fn_error $? "conditional \"MODULE__OPERATOR\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__STAT_TRUE}" && test -z "${MODULE__STAT_FALSE}"; then + as_fn_error $? "conditional \"MODULE__STAT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SYMTABLE_TRUE}" && test -z "${MODULE__SYMTABLE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SYMTABLE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_ARRAY_TRUE}" && test -z "${MODULE_ARRAY_FALSE}"; then as_fn_error $? "conditional \"MODULE_ARRAY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -26899,7 +27357,11 @@ fi $as_echo "$as_me: creating Makefile" >&6;} $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ - Modules/Setup.local $MODULES_SETUP_STDLIB Modules/Setup.bootstrap $srcdir/Modules/Setup + Modules/Setup.local Modules/Setup.stdlib Modules/Setup.bootstrap $srcdir/Modules/Setup +if test $? -ne 0; then + as_fn_error $? "makesetup failed" "$LINENO" 5 +fi + mv config.c Modules if test -z "$PKG_CONFIG"; then diff --git a/configure.ac b/configure.ac index ba38133578ab4f..0627d71d92dcb4 100644 --- a/configure.ac +++ b/configure.ac @@ -2892,7 +2892,7 @@ case $ac_sys_system/$ac_sys_release in LIBTOOL_CRUFT="${LIBTOOL_CRUFT} -arch_only `/usr/bin/arch`" fi LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' - LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';; + LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VfpoiERSION)';; Darwin/*) gcc_version=`gcc -dumpversion` if test ${gcc_version} '<' 4.0 @@ -5509,6 +5509,12 @@ AS_VAR_IF([ac_cv_broken_sem_getvalue], [yes], [ ) ]) +dnl Build _multiprocessing/semaphore.c when we have working semaphores. +if test "$ac_cv_func_sem_open" = "yes" -a "$ac_cv_posix_semaphores_enabled" = "yes"; then + MODULE__MULTIPROCESSING_SEMAPHORE_C=_multiprocessing/semaphore.c +fi +AC_SUBST([MODULE__MULTIPROCESSING_SEMAPHORE_C]) + AC_CHECK_DECLS([RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND, RTLD_MEMBER], [], [], [[#include ]]) # determine what size digit to use for Python's longs @@ -6773,17 +6779,6 @@ AS_CASE([$host_cpu], ) AC_SUBST([MODULE_BUILDTYPE]) -dnl Use Modules/Setup.stdlib as additional provider? -AC_MSG_CHECKING([for additional Modules/Setup files]) -AS_CASE([$ac_sys_system], - [Emscripten], [MODULES_SETUP_STDLIB=Modules/Setup.stdlib], - [WASI], [MODULES_SETUP_STDLIB=Modules/Setup.stdlib], - [MODULES_SETUP_STDLIB=] -) -AC_MSG_RESULT([$MODULES_SETUP_STDLIB]) -AC_SUBST([MODULES_SETUP_STDLIB]) - - dnl _MODULE_BLOCK_ADD([VAR], [VALUE]) dnl internal: adds $1=quote($2) to MODULE_BLOCK AC_DEFUN([_MODULE_BLOCK_ADD], [AS_VAR_APPEND([MODULE_BLOCK], ["$1=_AS_QUOTE([$2])$as_nl"])]) @@ -6839,9 +6834,32 @@ AC_DEFUN([PY_STDLIB_MOD_SIMPLE], [ m4_popdef([modstate])dnl ]) +dnl Some core modules are hard-coded in Modules/config.h.in +dnl marshal, _imp, _ast, _tokenize, builtins, sys, gc, _warnings, _string + dnl static modules in Modules/Setup.bootstrap +PY_STDLIB_MOD_SIMPLE([atexit]) +PY_STDLIB_MOD_SIMPLE([faulthandler]) +PY_STDLIB_MOD_SIMPLE([posix]) +PY_STDLIB_MOD_SIMPLE([_signal]) +PY_STDLIB_MOD_SIMPLE([_tracemalloc]) +dnl bootstrap: modules used by importlib, deepfreeze, freeze, runpy, and sysconfig +PY_STDLIB_MOD_SIMPLE([_codecs]) +PY_STDLIB_MOD_SIMPLE([_collections]) +PY_STDLIB_MOD_SIMPLE([errno]) PY_STDLIB_MOD_SIMPLE([_io], [-I\$(srcdir)/Modules/_io], []) +PY_STDLIB_MOD_SIMPLE([itertools]) +PY_STDLIB_MOD_SIMPLE([_sre]) +PY_STDLIB_MOD_SIMPLE([_thread]) PY_STDLIB_MOD_SIMPLE([time], [], [$TIMEMODULE_LIB]) +PY_STDLIB_MOD_SIMPLE([_weakref]) +dnl bootstrap: commonly used core modules +PY_STDLIB_MOD_SIMPLE([_abc]) +PY_STDLIB_MOD_SIMPLE([_functools]) +PY_STDLIB_MOD_SIMPLE([_locale]) +PY_STDLIB_MOD_SIMPLE([_operator]) +PY_STDLIB_MOD_SIMPLE([_stat]) +PY_STDLIB_MOD_SIMPLE([_symtable]) dnl always enabled extension modules PY_STDLIB_MOD_SIMPLE([array]) @@ -6946,8 +6964,7 @@ PY_STDLIB_MOD([nis], [$LIBNSL_CFLAGS], [$LIBNSL_LIBS]) dnl PY_STDLIB_MOD([readline], [], [], [], []) PY_STDLIB_MOD([_sqlite3], - [test "$have_sqlite3" = "yes"], - [test "$have_supported_sqlite3" = "yes"], + [], [test "$have_sqlite3" = "yes" -a "$have_supported_sqlite3" = "yes"], [$LIBSQLITE3_CFLAGS], [$LIBSQLITE3_LIBS]) PY_STDLIB_MOD([_tkinter], [], [test "$have_tcltk" = "yes"], @@ -7007,7 +7024,11 @@ fi AC_MSG_NOTICE([creating Makefile]) $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ - Modules/Setup.local $MODULES_SETUP_STDLIB Modules/Setup.bootstrap $srcdir/Modules/Setup + Modules/Setup.local Modules/Setup.stdlib Modules/Setup.bootstrap $srcdir/Modules/Setup +if test $? -ne 0; then + AC_MSG_ERROR([makesetup failed]) +fi + mv config.c Modules if test -z "$PKG_CONFIG"; then diff --git a/setup.py b/setup.py index 843ec35effe109..54ebf01f50f8a1 100644 --- a/setup.py +++ b/setup.py @@ -311,78 +311,6 @@ def __init__(self, dist): def add(self, ext): self.extensions.append(ext) - def addext(self, ext, *, update_flags=True): - """Add extension with Makefile MODULE_{name} support - """ - if update_flags: - self.update_extension_flags(ext) - - state = sysconfig.get_config_var(f"MODULE_{ext.name.upper()}_STATE") - if state == "yes": - self.extensions.append(ext) - elif state == "disabled": - self.disabled_configure.append(ext.name) - elif state == "missing": - self.missing.append(ext.name) - elif state == "n/a": - # not available on current platform - pass - else: - # not migrated to MODULE_{name}_STATE yet. - self.announce( - f'WARNING: Makefile is missing module variable for "{ext.name}"', - level=2 - ) - self.extensions.append(ext) - - def update_extension_flags(self, ext): - """Update extension flags with module CFLAGS and LDFLAGS - - Reads MODULE_{name}_CFLAGS and _LDFLAGS - - Distutils appends extra args to the compiler arguments. Some flags like - -I must appear earlier, otherwise the pre-processor picks up files - from system include directories. - """ - upper_name = ext.name.upper() - # Parse compiler flags (-I, -D, -U, extra args) - cflags = sysconfig.get_config_var(f"MODULE_{upper_name}_CFLAGS") - if cflags: - for token in shlex.split(cflags): - switch = token[0:2] - value = token[2:] - if switch == '-I': - ext.include_dirs.append(value) - elif switch == '-D': - key, _, val = value.partition("=") - if not val: - val = None - ext.define_macros.append((key, val)) - elif switch == '-U': - ext.undef_macros.append(value) - else: - ext.extra_compile_args.append(token) - - # Parse linker flags (-L, -l, extra objects, extra args) - ldflags = sysconfig.get_config_var(f"MODULE_{upper_name}_LDFLAGS") - if ldflags: - for token in shlex.split(ldflags): - switch = token[0:2] - value = token[2:] - if switch == '-L': - ext.library_dirs.append(value) - elif switch == '-l': - ext.libraries.append(value) - elif ( - token[0] != '-' and - token.endswith(('.a', '.o', '.so', '.sl', '.dylib')) - ): - ext.extra_objects.append(token) - else: - ext.extra_link_args.append(token) - - return ext - def set_srcdir(self): self.srcdir = sysconfig.get_config_var('srcdir') if not self.srcdir: @@ -900,120 +828,6 @@ def init_inc_lib_dirs(self): if item.startswith('-L'): self.lib_dirs.append(item[2:]) - def detect_simple_extensions(self): - # - # The following modules are all pretty straightforward, and compile - # on pretty much any POSIXish platform. - # - - # array objects - self.addext(Extension('array', ['arraymodule.c'])) - - # Context Variables - self.addext(Extension('_contextvars', ['_contextvarsmodule.c'])) - - # math library functions, e.g. sin() - self.addext(Extension('math', ['mathmodule.c'])) - - # complex math library functions - self.addext(Extension('cmath', ['cmathmodule.c'])) - - # libm is needed by delta_new() that uses round() and by accum() that - # uses modf(). - self.addext(Extension('_datetime', ['_datetimemodule.c'])) - self.addext(Extension('_zoneinfo', ['_zoneinfo.c'])) - # random number generator implemented in C - self.addext(Extension("_random", ["_randommodule.c"])) - self.addext(Extension("_bisect", ["_bisectmodule.c"])) - self.addext(Extension("_heapq", ["_heapqmodule.c"])) - # C-optimized pickle replacement - self.addext(Extension("_pickle", ["_pickle.c"])) - # _json speedups - self.addext(Extension("_json", ["_json.c"])) - - # profiler (_lsprof is for cProfile.py) - self.addext(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) - # static Unicode character database - self.addext(Extension('unicodedata', ['unicodedata.c'])) - self.addext(Extension('_opcode', ['_opcode.c'])) - - # asyncio speedups - self.addext(Extension("_asyncio", ["_asynciomodule.c"])) - - self.addext(Extension("_queue", ["_queuemodule.c"])) - self.addext(Extension("_statistics", ["_statisticsmodule.c"])) - self.addext(Extension("_struct", ["_struct.c"])) - self.addext(Extension("_typing", ["_typingmodule.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) - self.addext(Extension('fcntl', ['fcntlmodule.c'])) - # grp(3) - self.addext(Extension('grp', ['grpmodule.c'])) - - self.addext(Extension('_socket', ['socketmodule.c'])) - self.addext(Extension('spwd', ['spwdmodule.c'])) - - # select(2); not on ancient System V - self.addext(Extension('select', ['selectmodule.c'])) - - # Memory-mapped files (also works on Win32). - self.addext(Extension('mmap', ['mmapmodule.c'])) - - # Lance Ellinghaus's syslog module - # syslog daemon interface - self.addext(Extension('syslog', ['syslogmodule.c'])) - - # Python interface to subinterpreter C-API. - self.addext(Extension('_xxsubinterpreters', ['_xxsubinterpretersmodule.c'])) - - # - # 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. - self.addext(Extension('audioop', ['audioop.c'])) - - # CSV files - self.addext(Extension('_csv', ['_csv.c'])) - - # POSIX subprocess module helper. - self.addext(Extension('_posixsubprocess', ['_posixsubprocess.c'])) - - def detect_test_extensions(self): - # Python C API test module - self.addext(Extension('_testcapi', ['_testcapimodule.c'])) - - # Python Internal C API test module - self.addext(Extension('_testinternalcapi', ['_testinternalcapi.c'])) - - # Python PEP-3118 (buffer protocol) test module - self.addext(Extension('_testbuffer', ['_testbuffer.c'])) - - # Test loading multiple modules from one compiled file (https://bugs.python.org/issue16421) - self.addext(Extension('_testimportmultiple', ['_testimportmultiple.c'])) - - # Test multi-phase extension module init (PEP 489) - self.addext(Extension('_testmultiphase', ['_testmultiphase.c'])) - - # Fuzz tests. - self.addext(Extension( - '_xxtestfuzz', - ['_xxtestfuzz/_xxtestfuzz.c', '_xxtestfuzz/fuzzer.c'] - )) - def detect_readline_curses(self): # readline readline_termcap_library = "" @@ -1159,9 +973,6 @@ def detect_readline_curses(self): elif not skip_curses_panel: self.missing.append('_curses_panel') - def detect_crypt(self): - self.addext(Extension('_crypt', ['_cryptmodule.c'])) - 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 @@ -1234,91 +1045,6 @@ def detect_dbm_gdbm(self): else: self.missing.append('_dbm') - # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: - self.addext(Extension('_gdbm', ['_gdbmmodule.c'])) - - def detect_sqlite(self): - sources = [ - "_sqlite/blob.c", - "_sqlite/connection.c", - "_sqlite/cursor.c", - "_sqlite/microprotocols.c", - "_sqlite/module.c", - "_sqlite/prepare_protocol.c", - "_sqlite/row.c", - "_sqlite/statement.c", - "_sqlite/util.c", - ] - self.addext(Extension("_sqlite3", sources=sources)) - - def detect_platform_specific_exts(self): - # Unix-only modules - # Steen Lumholt's termios module - self.addext(Extension('termios', ['termios.c'])) - # Jeremy Hylton's rlimit interface - self.addext(Extension('resource', ['resource.c'])) - # linux/soundcard.h or sys/soundcard.h - self.addext(Extension('ossaudiodev', ['ossaudiodev.c'])) - - # macOS-only, needs SystemConfiguration and CoreFoundation framework - self.addext(Extension('_scproxy', ['_scproxy.c'])) - - def detect_compress_exts(self): - # Andrew Kuchling's zlib module. - self.addext(Extension('zlib', ['zlibmodule.c'])) - - # Helper module for various ascii-encoders. Uses zlib for an optimized - # crc32 if we have it. Otherwise binascii uses its own. - self.addext(Extension('binascii', ['binascii.c'])) - - # Gustavo Niemeyer's bz2 module. - self.addext(Extension('_bz2', ['_bz2module.c'])) - - # LZMA compression support. - self.addext(Extension('_lzma', ['_lzmamodule.c'])) - - 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. - # - self.addext(Extension('pyexpat', sources=['pyexpat.c'])) - - # Fredrik Lundh's cElementTree module. Note that this also - # uses expat (via the CAPI hook in pyexpat). - self.addext(Extension('_elementtree', sources=['_elementtree.c'])) - - def detect_multibytecodecs(self): - # Hye-Shik Chang's CJKCodecs modules. - self.addext(Extension('_multibytecodec', - ['cjkcodecs/multibytecodec.c'])) - for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'): - self.addext(Extension( - f'_codecs_{loc}', [f'cjkcodecs/_codecs_{loc}.c'] - )) - - def detect_multiprocessing(self): - # Richard Oudkerk's multiprocessing module - multiprocessing_srcs = ['_multiprocessing/multiprocessing.c'] - if ( - sysconfig.get_config_var('HAVE_SEM_OPEN') and not - sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED') - ): - multiprocessing_srcs.append('_multiprocessing/semaphore.c') - self.addext(Extension('_multiprocessing', multiprocessing_srcs)) - self.addext(Extension('_posixshmem', ['_multiprocessing/posixshmem.c'])) - - def detect_uuid(self): - # Build the _uuid module if possible - self.addext(Extension('_uuid', ['_uuidmodule.c'])) - def detect_modules(self): # remove dummy extension self.extensions = [] @@ -1326,88 +1052,9 @@ def detect_modules(self): # Some C extensions are built by entries in Modules/Setup.bootstrap. # These are extensions are required to bootstrap the interpreter or # build process. - self.detect_simple_extensions() - self.detect_test_extensions() self.detect_readline_curses() - self.detect_crypt() - self.detect_openssl_hashlib() - self.detect_hash_builtins() self.detect_dbm_gdbm() - self.detect_sqlite() - self.detect_platform_specific_exts() - 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_tkinter() - self.detect_uuid() - - # Uncomment the next line if you want to play with xxmodule.c -# self.add(Extension('xx', ['xxmodule.c'])) - - self.addext(Extension('xxlimited', ['xxlimited.c'])) - self.addext(Extension('xxlimited_35', ['xxlimited_35.c'])) - - def detect_tkinter(self): - self.addext(Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'])) - - def detect_ctypes(self): - # Thomas Heller's _ctypes module - src = [ - '_ctypes/_ctypes.c', - '_ctypes/callbacks.c', - '_ctypes/callproc.c', - '_ctypes/stgdict.c', - '_ctypes/cfield.c', - ] - malloc_closure = sysconfig.get_config_var( - "MODULE__CTYPES_MALLOC_CLOSURE" - ) - if malloc_closure: - src.append(malloc_closure) - - self.addext(Extension('_ctypes', src)) - self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c'])) - - def detect_decimal(self): - # Stefan Krah's _decimal module - self.addext( - Extension( - '_decimal', - ['_decimal/_decimal.c'], - # Uncomment for extra functionality: - # define_macros=[('EXTRA_FUNCTIONALITY', 1)] - ) - ) - - def detect_openssl_hashlib(self): - self.addext(Extension('_ssl', ['_ssl.c'])) - self.addext(Extension('_hashlib', ['_hashopenssl.c'])) - - def detect_hash_builtins(self): - # By default 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). Modules can - # be disabled via the --with-builtin-hashlib-hashes configure flag. - - self.addext(Extension('_md5', ['md5module.c'])) - self.addext(Extension('_sha1', ['sha1module.c'])) - self.addext(Extension('_sha256', ['sha256module.c'])) - self.addext(Extension('_sha512', ['sha512module.c'])) - self.addext(Extension('_sha3', ['_sha3/sha3module.c'])) - self.addext(Extension('_blake2', - [ - '_blake2/blake2module.c', - '_blake2/blake2b_impl.c', - '_blake2/blake2s_impl.c' - ] - )) - def detect_nis(self): - self.addext(Extension('nis', ['nismodule.c'])) class PyBuildInstall(install):