From d636002c482905eed73b7896c1ec034ff03a297c Mon Sep 17 00:00:00 2001 From: zaniebot <242828183+zaniebot@users.noreply.github.com> Date: Wed, 21 Oct 2026 18:47:58 +0000 Subject: [PATCH] Track header dependencies during compilation --- .gitignore | 1 + Doc/using/configure.rst | 18 ++++-- Lib/test/test_tools/test_makefile.py | 24 +++++++ Makefile.pre.in | 93 +++++++++++++++++----------- Modules/makesetup | 7 ++- configure | 71 +++++++++++++++++++++ configure.ac | 29 +++++++++ 7 files changed, 201 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 2fce2ac10ae9a74..3201ea8aa59c3b5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.cover *.iml *.o +*.o.d *.o.tmp *.lto *.a diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index c36328ca6f79723..c6e2c7b4b8b2a19 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -673,6 +673,15 @@ Install Options .. versionadded:: 3.10 +.. option:: --disable-dependency-tracking + + Disable compiler-generated header dependencies and use the manually maintained + header dependencies instead. By default, compilers that support dependency + files record the headers used by each object file, allowing the build to + identify the objects affected by a header change. + + .. versionadded:: 3.16 + .. option:: --with-ensurepip=[upgrade|install|no] Select the :mod:`ensurepip` command run on Python installation: @@ -1476,10 +1485,11 @@ all`` will build. The three choices are: Depending on the most recent source file changes, Make will rebuild any targets (object files and executables) deemed out-of-date, -including running ``configure`` again if necessary. Source/target -dependencies are many and maintained manually however, so Make -sometimes doesn't have all the information necessary to correctly -detect all targets which need to be rebuilt. Depending on which +including running ``configure`` again if necessary. Header dependencies are +recorded during compilation when the compiler supports dependency files. +Other dependencies, and header dependencies when compiler-generated dependencies +are disabled or unsupported, are maintained manually. Make may therefore lack +information needed to detect all targets which need to be rebuilt. Depending on which targets aren't rebuilt, you might experience a number of problems. If you have build or test problems which you can't otherwise explain, ``make clean && make`` should work around most dependency problems, at diff --git a/Lib/test/test_tools/test_makefile.py b/Lib/test/test_tools/test_makefile.py index 31a516067394e1e..df38dab20472b59 100644 --- a/Lib/test/test_tools/test_makefile.py +++ b/Lib/test/test_tools/test_makefile.py @@ -3,9 +3,12 @@ """ import os +import shutil +import subprocess import unittest from test import support import sysconfig +from sysconfig.__main__ import _parse_makefile MAKEFILE = sysconfig.get_makefile_filename() @@ -16,6 +19,27 @@ class TestMakefile(unittest.TestCase): + @support.requires_subprocess() + @unittest.skipUnless(sysconfig.is_python_build(), 'requires a source build') + def test_internal_header_dependencies(self): + config = _parse_makefile(MAKEFILE) + if not config.get('C_DEPENDENCY_FLAGS'): + self.skipTest('compiler-generated dependencies are disabled') + make = shutil.which('gmake') or shutil.which('make') + if make is None: + self.skipTest('make is not available') + header = os.path.join(config['srcdir'], 'Include/internal/pycore_atexit.h') + for obj, expected in [('Modules/atexitmodule.o', 1), ('Parser/token.o', 0)]: + with self.subTest(object=obj): + result = subprocess.run( + [make, '-q', '-W', header, obj], + cwd=config['abs_builddir'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + self.assertEqual(result.returncode, expected, result.stderr) + def list_test_dirs(self): result = [] found_testsubdirs = False diff --git a/Makefile.pre.in b/Makefile.pre.in index c49a16f1edc3bef..04afddede1571ba 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -24,6 +24,7 @@ MODBUILT_NAMES= _MODBUILT_NAMES_ MODSHARED_NAMES= _MODSHARED_NAMES_ MODDISABLED_NAMES= _MODDISABLED_NAMES_ MODOBJS= _MODOBJS_ +MODCOMPILE_OBJS= _MODCOMPILE_OBJS_ MODLIBS= _MODLIBS_ # === Variables set by configure @@ -132,6 +133,7 @@ PY_CORE_EXE_LDFLAGS:= $(if $(CONFIGURE_EXE_LDFLAGS), $(CONFIGURE_EXE_LDFLAGS) $( CFLAGS_ALIASING=@CFLAGS_ALIASING@ # Compilation flags only for ceval.c. CFLAGS_CEVAL=@CFLAGS_CEVAL@ +C_DEPENDENCY_FLAGS=@C_DEPENDENCY_FLAGS@ # Machine-dependent subdirectories @@ -1448,21 +1450,39 @@ PYTHON_HEADERS= \ \ $(srcdir)/Python/stdlib_module_names.h +ifneq ($(C_DEPENDENCY_FLAGS),) +# Generated headers must exist before the first compilation creates dependencies. +PYTHON_HEADERS= pyconfig.h $(DTRACE_HEADERS) +C_DEPENDENCY_OBJS= $(filter-out $(JIT_OBJS),$(LIBRARY_OBJS)) \ + $(MODCOMPILE_OBJS) $(LIBEXPAT_OBJS) $(LIBHACL_HMAC_OBJS) \ + Programs/python.o Programs/_testembed.o Programs/_bootstrap_python.o \ + Programs/_freeze_module.o Modules/getpath_noop.o +C_DEPENDENCY_FILES:= $(wildcard $(addsuffix .d,$(C_DEPENDENCY_OBJS))) +-include $(C_DEPENDENCY_FILES) + +# Rebuild tracked objects that are missing dependency files. +C_DEPENDENCY_MISSING:= $(filter-out $(C_DEPENDENCY_FILES:.d=),$(wildcard $(C_DEPENDENCY_OBJS))) +ifneq ($(C_DEPENDENCY_MISSING),) +.PHONY: missing-dependency-files +$(C_DEPENDENCY_MISSING): missing-dependency-files +endif +endif + ########################################################################## # Build static libexpat.a LIBEXPAT_CFLAGS=@LIBEXPAT_CFLAGS@ $(PY_STDMODULE_CFLAGS) $(CCSHARED) Modules/expat/xcs.o: $(srcdir)/Modules/expat/xcs.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS) - $(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xcs.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xcs.c Modules/expat/xmlparse.o: $(srcdir)/Modules/expat/xmlparse.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS) - $(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmlparse.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmlparse.c Modules/expat/xmlrole.o: $(srcdir)/Modules/expat/xmlrole.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS) - $(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmlrole.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmlrole.c Modules/expat/xmltok.o: $(srcdir)/Modules/expat/xmltok.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS) - $(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmltok.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmltok.c $(LIBEXPAT_A): $(LIBEXPAT_OBJS) -rm -f $@ @@ -1482,44 +1502,44 @@ $(LIBEXPAT_A): $(LIBEXPAT_OBJS) # For WASI, static linking is needed and HACL* is statically linked instead. Modules/_hacl/Lib_Memzero0.o: $(srcdir)/Modules/_hacl/Lib_Memzero0.c $(LIBHACL_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Lib_Memzero0.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Lib_Memzero0.c Modules/_hacl/Hacl_Hash_MD5.o: $(srcdir)/Modules/_hacl/Hacl_Hash_MD5.c $(LIBHACL_MD5_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_MD5.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_MD5.c $(LIBHACL_MD5_LIB_STATIC): $(LIBHACL_MD5_OBJS) -rm -f $@ $(AR) $(ARFLAGS) $@ $(LIBHACL_MD5_OBJS) Modules/_hacl/Hacl_Hash_SHA1.o: $(srcdir)/Modules/_hacl/Hacl_Hash_SHA1.c $(LIBHACL_SHA1_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_SHA1.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_SHA1.c $(LIBHACL_SHA1_LIB_STATIC): $(LIBHACL_SHA1_OBJS) -rm -f $@ $(AR) $(ARFLAGS) $@ $(LIBHACL_SHA1_OBJS) Modules/_hacl/Hacl_Hash_SHA2.o: $(srcdir)/Modules/_hacl/Hacl_Hash_SHA2.c $(LIBHACL_SHA2_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_SHA2.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_SHA2.c $(LIBHACL_SHA2_LIB_STATIC): $(LIBHACL_SHA2_OBJS) -rm -f $@ $(AR) $(ARFLAGS) $@ $(LIBHACL_SHA2_OBJS) Modules/_hacl/Hacl_Hash_SHA3.o: $(srcdir)/Modules/_hacl/Hacl_Hash_SHA3.c $(LIBHACL_SHA3_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_SHA3.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_SHA3.c $(LIBHACL_SHA3_LIB_STATIC): $(LIBHACL_SHA3_OBJS) -rm -f $@ $(AR) $(ARFLAGS) $@ $(LIBHACL_SHA3_OBJS) Modules/_hacl/Hacl_Hash_Blake2s.o: $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s.c $(LIBHACL_BLAKE2_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s.c Modules/_hacl/Hacl_Hash_Blake2b.o: $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2b.c $(LIBHACL_BLAKE2_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2b.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2b.c Modules/_hacl/Hacl_Hash_Blake2s_Simd128.o: $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s_Simd128.c $(LIBHACL_BLAKE2_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) $(LIBHACL_BLAKE2_SIMD128_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s_Simd128.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) $(LIBHACL_BLAKE2_SIMD128_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s_Simd128.c Modules/_hacl/Hacl_Hash_Blake2s_Simd128_universal2.o: $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s_Simd128_universal2.c $(LIBHACL_BLAKE2_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) $(LIBHACL_BLAKE2_SIMD128_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s_Simd128_universal2.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) $(LIBHACL_BLAKE2_SIMD128_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s_Simd128_universal2.c Modules/_hacl/Hacl_Hash_Blake2b_Simd256.o: $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2b_Simd256.c $(LIBHACL_BLAKE2_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) $(LIBHACL_BLAKE2_SIMD256_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2b_Simd256.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) $(LIBHACL_BLAKE2_SIMD256_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2b_Simd256.c Modules/_hacl/Hacl_Hash_Blake2b_Simd256_universal2.o: $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2b_Simd256_universal2.c $(LIBHACL_BLAKE2_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) $(LIBHACL_BLAKE2_SIMD256_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2b_Simd256_universal2.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) $(LIBHACL_BLAKE2_SIMD256_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2b_Simd256_universal2.c $(LIBHACL_BLAKE2_LIB_STATIC): $(LIBHACL_BLAKE2_OBJS) -rm -f $@ $(AR) $(ARFLAGS) $@ $(LIBHACL_BLAKE2_OBJS) @@ -1527,9 +1547,9 @@ $(LIBHACL_BLAKE2_LIB_STATIC): $(LIBHACL_BLAKE2_OBJS) # Other HACL* cryptographic primitives Modules/_hacl/Hacl_HMAC.o: $(srcdir)/Modules/_hacl/Hacl_HMAC.c $(LIBHACL_HMAC_HEADERS) - $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_HMAC.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_HMAC.c Modules/_hacl/Hacl_Streaming_HMAC.o: $(srcdir)/Modules/_hacl/Hacl_Streaming_HMAC.c $(LIBHACL_HMAC_HEADERS) - $(CC) -Wno-unused-variable -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Streaming_HMAC.c + $(CC) $(C_DEPENDENCY_FLAGS) -Wno-unused-variable -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Streaming_HMAC.c $(LIBHACL_HMAC_LIB_STATIC): $(LIBHACL_HMAC_OBJS) -rm -f $@ $(AR) $(ARFLAGS) $@ $(LIBHACL_HMAC_OBJS) @@ -1879,14 +1899,14 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \ $(MODOBJS) \ $(DTRACE_OBJS) \ $(srcdir)/Modules/getbuildinfo.c - $(CC) -c $(PY_CORE_CFLAGS) \ + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) \ -DGITVERSION="\"`LC_ALL=C $(GITVERSION)`\"" \ -DGITTAG="\"`LC_ALL=C $(GITTAG)`\"" \ -DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \ -o $@ $(srcdir)/Modules/getbuildinfo.c Modules/getpath.o: $(srcdir)/Modules/getpath.c Python/frozen_modules/getpath.h Makefile $(PYTHON_HEADERS) - $(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ -DPREFIX='"$(host_prefix)"' \ -DEXEC_PREFIX='"$(host_exec_prefix)"' \ -DVERSION='"$(VERSION)"' \ @@ -1896,10 +1916,10 @@ Modules/getpath.o: $(srcdir)/Modules/getpath.c Python/frozen_modules/getpath.h M -o $@ $(srcdir)/Modules/getpath.c Programs/python.o: $(srcdir)/Programs/python.c - $(CC) -c $(PY_CORE_CFLAGS) -o $@ $(srcdir)/Programs/python.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -o $@ $(srcdir)/Programs/python.c Programs/_testembed.o: $(srcdir)/Programs/_testembed.c Programs/test_frozenmain.h $(PYTHON_HEADERS) - $(CC) -c $(PY_CORE_CFLAGS) -o $@ $(srcdir)/Programs/_testembed.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -o $@ $(srcdir)/Programs/_testembed.c Modules/_sre/sre.o: $(srcdir)/Modules/_sre/sre.c $(srcdir)/Modules/_sre/sre.h $(srcdir)/Modules/_sre/sre_constants.h $(srcdir)/Modules/_sre/sre_lib.h @@ -1924,17 +1944,17 @@ Python/initconfig.o: $(srcdir)/Python/initconfig.c $(srcdir)/Python/config_commo Python/interpconfig.o: $(srcdir)/Python/interpconfig.c $(srcdir)/Python/config_common.h Python/dynload_shlib.o: $(srcdir)/Python/dynload_shlib.c Makefile - $(CC) -c $(PY_CORE_CFLAGS) \ + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) \ -DSOABI='"$(SOABI)"' \ -o $@ $(srcdir)/Python/dynload_shlib.c Python/dynload_hpux.o: $(srcdir)/Python/dynload_hpux.c Makefile - $(CC) -c $(PY_CORE_CFLAGS) \ + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) \ -DSHLIB_EXT='"$(EXT_SUFFIX)"' \ -o $@ $(srcdir)/Python/dynload_hpux.c Python/sysmodule.o: $(srcdir)/Python/sysmodule.c Makefile $(srcdir)/Include/pydtrace.h - $(CC) -c $(PY_CORE_CFLAGS) \ + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) \ -DABIFLAGS='"$(ABIFLAGS)"' \ $(MULTIARCH_CPPFLAGS) \ -o $@ $(srcdir)/Python/sysmodule.c @@ -2034,10 +2054,10 @@ regen-sre: Python/compile.o Python/codegen.o Python/symtable.o Python/ast_unparse.o Python/ast.o Python/future.o: $(srcdir)/Include/internal/pycore_ast.h $(srcdir)/Include/internal/pycore_ast.h Python/getplatform.o: $(srcdir)/Python/getplatform.c - $(CC) -c $(PY_CORE_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c Python/importdl.o: $(srcdir)/Python/importdl.c - $(CC) -c $(PY_CORE_CFLAGS) -I$(DLINCLDIR) -o $@ $(srcdir)/Python/importdl.c + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -I$(DLINCLDIR) -o $@ $(srcdir)/Python/importdl.c Objects/unicodectype.o: $(srcdir)/Objects/unicodectype.c \ $(srcdir)/Objects/unicodetype_db.h @@ -3133,22 +3153,22 @@ config.status: $(srcdir)/configure .PRECIOUS: config.status $(BUILDPYTHON) Makefile Makefile.pre Python/asm_trampoline_x86_64.o: $(srcdir)/Python/asm_trampoline_x86_64.S - $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -o $@ $< Python/asm_trampoline_aarch64.o: $(srcdir)/Python/asm_trampoline_aarch64.S - $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -o $@ $< Python/asm_trampoline_riscv64.o: $(srcdir)/Python/asm_trampoline_riscv64.S - $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -o $@ $< # On macOS universal2 builds, $(PY_CORE_CFLAGS) contains "-arch arm64 -arch x86_64", # which would produce fat .o files containing both architectures for each .S input. # lipo -create then refuses to combine them because they share architectures. # Build each per-arch object with a single -arch flag before merging with lipo. Python/asm_trampoline_universal2.o: $(srcdir)/Python/asm_trampoline_aarch64.S $(srcdir)/Python/asm_trampoline_x86_64.S - $(CC) -c $(filter-out -arch arm64 x86_64,$(PY_CORE_CFLAGS)) -arch arm64 \ + $(CC) $(C_DEPENDENCY_FLAGS) -c $(filter-out -arch arm64 x86_64,$(PY_CORE_CFLAGS)) -arch arm64 \ -o Python/asm_trampoline_arm64-apple-darwin.o $(srcdir)/Python/asm_trampoline_aarch64.S - $(CC) -c $(filter-out -arch arm64 x86_64,$(PY_CORE_CFLAGS)) -arch x86_64 \ + $(CC) $(C_DEPENDENCY_FLAGS) -c $(filter-out -arch arm64 x86_64,$(PY_CORE_CFLAGS)) -arch x86_64 \ -o Python/asm_trampoline_x86_64-apple-darwin.o $(srcdir)/Python/asm_trampoline_x86_64.S lipo -create -output $@ \ Python/asm_trampoline_arm64-apple-darwin.o \ @@ -3184,27 +3204,27 @@ jit_shim-universal2-apple-darwin.o: jit_shim-aarch64-apple-darwin.o jit_shim-x86 lipo -create -output $@ jit_shim-aarch64-apple-darwin.o jit_shim-x86_64-apple-darwin.o Python/jit.o: $(srcdir)/Python/jit.c @JIT_STENCILS_H@ - $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -o $@ $< Python/jit_unwind.o: $(srcdir)/Python/jit_unwind.c $(JIT_UNWIND_INFO_H) - $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -o $@ $< .PHONY: regen-jit regen-jit: $(JIT_TARGETS) # Some make's put the object file in the current directory .c.o: - $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) -o $@ $< # bpo-30104: dtoa.c uses union to cast double to unsigned long[2]. clang 4.0 # with -O2 or higher and strict aliasing miscompiles the ratio() function # causing rounding issues. Compile dtoa.c using -fno-strict-aliasing on clang. # https://bugs.llvm.org//show_bug.cgi?id=31928 Python/dtoa.o: Python/dtoa.c - $(CC) -c $(PY_CORE_CFLAGS) $(CFLAGS_ALIASING) -o $@ $< + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) $(CFLAGS_ALIASING) -o $@ $< Python/ceval.o: Python/ceval.c - $(CC) -c $(PY_CORE_CFLAGS) $(CFLAGS_CEVAL) -o $@ $< + $(CC) $(C_DEPENDENCY_FLAGS) -c $(PY_CORE_CFLAGS) $(CFLAGS_CEVAL) -o $@ $< # Run reindent on the library .PHONY: reindent @@ -3273,6 +3293,7 @@ clean-retain-profile: pycremoval # Keep the generated JIT shim objects with the rest of the JIT generated # files: they are regenerated as a group and tracked by .jit-stamp. find . -name '*.[oa]' ! -name 'jit_shim*.o' -exec rm -f {} ';' + find . -name '*.o.d' -exec rm -f {} ';' find . -name '*.s[ol]' -exec rm -f {} ';' find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' find . -name '*.lto' -exec rm -f {} ';' diff --git a/Modules/makesetup b/Modules/makesetup index 8b28946608b5762..51a9aa1023a5a84 100755 --- a/Modules/makesetup +++ b/Modules/makesetup @@ -111,6 +111,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | MODS= SHAREDMODS= OBJS= + COMPILE_OBJS= LIBS= LOCALLIBS= BASELIBS= @@ -243,6 +244,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | *) obj="$srcdir/$obj";; esac objs="$objs $obj" + COMPILE_OBJS="$COMPILE_OBJS $obj" case $src in glmodule.c) ;; /*) ;; @@ -254,12 +256,12 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | no) cc="$cc $cpps \$(PY_STDMODULE_CFLAGS) \$(CCSHARED)" rule="$obj: $src \$(MODULE_${mods_upper}_DEPS) \$(MODULE_DEPS_SHARED) \$(PYTHON_HEADERS)" - rule="$rule; $cc -c $src -o $obj" + rule="$rule; $cc \$(C_DEPENDENCY_FLAGS) -c $src -o $obj" ;; *) cc="$cc $cpps \$(PY_BUILTIN_MODULE_CFLAGS)" rule="$obj: $src \$(MODULE_${mods_upper}_DEPS) \$(MODULE_DEPS_STATIC) \$(PYTHON_HEADERS)" - rule="$rule; $cc -c $src -o $obj" + rule="$rule; $cc \$(C_DEPENDENCY_FLAGS) -c $src -o $obj" ;; esac echo "$rule" >>$rulesf @@ -332,6 +334,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | echo "s%_MODSHARED_NAMES_%$BUILT_SHARED%" >>$sedf echo "s%_MODDISABLED_NAMES_%$DISABLED%" >>$sedf echo "s%_MODOBJS_%$OBJS%" >>$sedf + echo "s%_MODCOMPILE_OBJS_%$COMPILE_OBJS%" >>$sedf echo "s%_MODLIBS_%$LIBS%" >>$sedf echo "/Definitions added by makesetup/r $sedr" >>$sedf sed -f $sedf $makepre >Makefile diff --git a/configure b/configure index 38fd8575530e8a0..774b608389fc81f 100755 --- a/configure +++ b/configure @@ -643,6 +643,7 @@ ac_includes_default="\ ac_header_c_list= ac_subst_vars='LTLIBOBJS +C_DEPENDENCY_FLAGS MODULE_BLOCK JIT_SHIM_BUILD_O JIT_SHIM_O @@ -1161,6 +1162,7 @@ with_ssl_default_suites with_builtin_hashlib_hashes enable_test_modules with_build_details_suffix +enable_dependency_tracking ' ac_precious_vars='build_alias host_alias @@ -1883,6 +1885,8 @@ Optional Features: use big digits (30 or 15 bits) for Python longs (default is 30)] --disable-test-modules don't build nor install test modules + --disable-dependency-tracking + do not use compiler-generated header dependencies Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -39148,6 +39152,73 @@ fi # substitute multiline block, must come after last PY_STDLIB_MOD() +# Check whether --enable-dependency-tracking was given. +if test ${enable_dependency_tracking+y} +then : + enableval=$enable_dependency_tracking; +else case e in #( + e) enable_dependency_tracking=yes ;; +esac +fi + +case $enable_dependency_tracking in #( + yes|no) : + ;; #( + *) : + as_fn_error $? "--enable-dependency-tracking accepts yes or no" "$LINENO" 5 ;; +esac +C_DEPENDENCY_FLAGS= +if test "$enable_dependency_tracking" = yes +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compiler-generated header dependencies" >&5 +printf %s "checking for compiler-generated header dependencies... " >&6; } +if test ${ac_cv_cc_dependencies+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -MMD -MP -MF conftest.d -MQ conftest.o" + echo > conftest-deps.h + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include "conftest-deps.h" + int main(void) { return 0; } + +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + + if test -s conftest.d && grep conftest-deps.h conftest.d >/dev/null +then : + ac_cv_cc_dependencies=yes +else case e in #( + e) ac_cv_cc_dependencies=no ;; +esac +fi + +else case e in #( + e) ac_cv_cc_dependencies=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS="$save_CFLAGS" + rm -f conftest.d conftest-deps.h + ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_dependencies" >&5 +printf "%s\n" "$ac_cv_cc_dependencies" >&6; } + if test "x$ac_cv_cc_dependencies" = xyes +then : + C_DEPENDENCY_FLAGS='-MMD -MP -MF "$@.d" -MQ "$@"' +fi + +fi + + # generate output files ac_config_files="$ac_config_files Makefile.pre Misc/python.pc Misc/python-embed.pc Misc/python-config.sh" diff --git a/configure.ac b/configure.ac index 777ced944545941..b0cce7fe3ae4d53 100644 --- a/configure.ac +++ b/configure.ac @@ -8927,6 +8927,35 @@ AC_SUBST([JIT_SHIM_BUILD_O]) # substitute multiline block, must come after last PY_STDLIB_MOD() AC_SUBST([MODULE_BLOCK]) +AC_ARG_ENABLE([dependency-tracking], + [AS_HELP_STRING([--disable-dependency-tracking], + [do not use compiler-generated header dependencies])], + [], [enable_dependency_tracking=yes]) +AS_CASE([$enable_dependency_tracking], + [yes|no], [], + [AC_MSG_ERROR([--enable-dependency-tracking accepts yes or no])]) +C_DEPENDENCY_FLAGS= +AS_IF([test "$enable_dependency_tracking" = yes], [ + AC_CACHE_CHECK([for compiler-generated header dependencies], + [ac_cv_cc_dependencies], [ + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -MMD -MP -MF conftest.d -MQ conftest.o" + echo > conftest-deps.h + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + #include "conftest-deps.h" + int main(void) { return 0; } + ]])], [ + AS_IF([test -s conftest.d && grep conftest-deps.h conftest.d >/dev/null], + [ac_cv_cc_dependencies=yes], [ac_cv_cc_dependencies=no]) + ], [ac_cv_cc_dependencies=no]) + CFLAGS="$save_CFLAGS" + rm -f conftest.d conftest-deps.h + ]) + AS_VAR_IF([ac_cv_cc_dependencies], [yes], + [C_DEPENDENCY_FLAGS='-MMD -MP -MF "$@.d" -MQ "$@"']) +]) +AC_SUBST([C_DEPENDENCY_FLAGS]) + # generate output files AC_CONFIG_FILES(m4_normalize([ Makefile.pre