build: per-file automatic dependencies (.deps), retire the Depend/sed machinery

Replace the monolithic per-directory `Depend` file -- generated by a separate,
serial `make depend` pass (one `gcc -MM` over all sources) and post-processed by
sed -- with automake-style per-file dependency fragments produced as a side
effect of each compile.

rules.mak's %.o rule now adds, when the compiler supports it,
  -MMD -MP -MF .deps/<stem>.d
so every object records the (non-system) headers it used.  Those fragments are
`-include`d best-effort: absent on a first build, present and correct after.
Benefits:
  * self-maintaining -- no explicit depend step; deps refresh on every compile;
  * parallel -- generated during the (already parallel) compile, no barrier;
  * -MMD already drops system headers (what the sed did) and -MP tolerates a
    removed/renamed header, so the sed post-processing is gone;
  * fixes out-of-tree incremental header tracking: with an absolute srcdir the
    old sed stripped the now-absolute *local* header paths too, silently losing
    them; the .d files keep them.

configure probes `-MMD -MP` (AUTODEP_FLAGS; empty and best-effort-skipped if the
compiler cannot).  clean/distclean remove .deps (rm -r); .gitignore replaces the
obsolete */Depend with .deps/.  `make depend` is kept as a no-op for callers that
still invoke it (e.g. the WASM build script).

Verified out-of-tree (--disable-ccache): 324 .d files, 0 Depend files, a header
touch recompiles its dependents, no-op rebuild is idle, clean clears .deps.  (The
top-level depend phase still runs here as a no-op; removed next.)

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
Darryl L. Miles
2026-07-26 14:54:11 -04:00
committed by R. Timothy Edwards
co-authored by Claude Opus 4.8
parent c27ef5fab1
commit 1bc8537b5d
5 changed files with 78 additions and 41 deletions
+31 -4
View File
@@ -636,7 +636,7 @@ MSED
MCPP
LD_RUN_PATH
SHLIB_CFLAGS
DEPEND_FLAG
AUTODEP_FLAGS
gr_hprog
gr_hsrcs
gr_srcs
@@ -6349,7 +6349,7 @@ extra_defs="$extra_defs -DCAD_DIR=\\\"\${LIBDIR}\\\" -DBIN_DIR=\\\"\${BINDIR}\\\
X_LIBS=
X_CFLAGS=
INC_SPECS=
DEPEND_FLAG=
AUTODEP_FLAGS=
SHLIB_CFLAGS=""
LD_RUN_PATH=""
WISH_EXE=""
@@ -9435,9 +9435,36 @@ fi
fi
if test "$GCC" = "yes" ; then
DEPEND_FLAG="-MM"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC generates dependencies with -MMD -MP" >&5
$as_echo_n "checking whether $CC generates dependencies with -MMD -MP... " >&6; }
magic_save_cflags="$CFLAGS"
CFLAGS="$CFLAGS -MMD -MP -MF conftest.autodep.d"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if test -f conftest.autodep.d ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }; AUTODEP_FLAGS="-MMD -MP"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no (produced no .d)" >&5
$as_echo "no (produced no .d)" >&6; }
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f conftest.autodep.d
CFLAGS="$magic_save_cflags"
+21 -5
View File
@@ -370,7 +370,7 @@ extra_defs="$extra_defs -DCAD_DIR=\\\"\${LIBDIR}\\\" -DBIN_DIR=\\\"\${BINDIR}\\\
X_LIBS=
X_CFLAGS=
INC_SPECS=
DEPEND_FLAG=
AUTODEP_FLAGS=
SHLIB_CFLAGS=""
LD_RUN_PATH=""
WISH_EXE=""
@@ -1987,9 +1987,25 @@ if test $usingTcl ; then
fi
if test "$GCC" = "yes" ; then
DEPEND_FLAG="-MM"
fi
dnl Automatic per-file dependency generation. Compilers that support -MMD -MP
dnl write a .deps/<stem>.d listing the (non-system) headers a source used, as a
dnl side effect of compiling it -- replacing the old serial "make depend" pass
dnl and its sed post-processing, and parallelising with the compile. Best
dnl effort: empty if unsupported, and the build proceeds without incremental
dnl header tracking. Probed (not assumed from $GCC) so clang and others are
dnl covered only when they actually produce the file.
AC_MSG_CHECKING([whether $CC generates dependencies with -MMD -MP])
magic_save_cflags="$CFLAGS"
CFLAGS="$CFLAGS -MMD -MP -MF conftest.autodep.d"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
[if test -f conftest.autodep.d ; then
AC_MSG_RESULT([yes]); AUTODEP_FLAGS="-MMD -MP"
else
AC_MSG_RESULT([no (produced no .d)])
fi],
[AC_MSG_RESULT([no])])
rm -f conftest.autodep.d
CFLAGS="$magic_save_cflags"
dnl Substitute all variables
@@ -2032,7 +2048,7 @@ AC_SUBST(CFLAGS)
AC_SUBST(CPPFLAGS)
AC_SUBST(CXX)
AC_SUBST(CXXFLAGS)
AC_SUBST(DEPEND_FLAG)
AC_SUBST(AUTODEP_FLAGS)
AC_SUBST(SHLIB_CFLAGS)
AC_SUBST(LDFLAGS)
AC_SUBST(LD_RUN_PATH)
+5 -4
View File
@@ -200,8 +200,10 @@ LDFLAGS = @LDFLAGS@
READLINE_DEFS = @rl_defs@
READLINE_LIBS = @rl_libs@
DEPEND_FILE = Depend
DEPEND_FLAG = @DEPEND_FLAG@
# Per-file dependency flags ("-MMD -MP" when the compiler supports it, else
# empty); used by the %.o rule in rules.mak to write .deps/<stem>.d as a compile
# side effect. Replaces the old serial "make depend" / Depend-file machinery.
AUTODEP_FLAGS = @AUTODEP_FLAGS@
EXEEXT = @EXEEXT@
GR_CFLAGS = @X_CFLAGS@ @gr_cflags@
@@ -214,12 +216,11 @@ GR_HELPER_PROG = @gr_hprog@
OA = @OA@
OA_LIBS = @OA_LIBS@
DEPSRCS = ${SRCS}
C_OBJS = ${SRCS:.c=.o}
CXX_OBJS = ${CXXSRCS:.cpp=.o}
OBJS = ${CXX_OBJS} ${C_OBJS}
LIB_OBJS = ${LIB_SRCS:.c=.o}
CLEANS = Depend ${OBJS} ${LIB_OBJS} lib${MODULE}.a lib${MODULE}.o ${MODULE}
CLEANS = ${OBJS} ${LIB_OBJS} lib${MODULE}.a lib${MODULE}.o ${MODULE}
# allows Makefile to be selective
MAKE_TCL = @MAKE_TCL@