5f47cb8c328b76c41a9a21599477bfacf4d91a37
braney
  Sun Sep 6 16:57:16 2026 -0700
makefiles: let the compiler write the header dependencies

The tree had 72 hand-written "foo.o: bar.h" lines across 15 makefiles, so
almost every object was rebuilt only when its own .c file changed.  Editing a
header left every other object that included it holding the old layout, and the
crash landed somewhere the change never touched.

The %.o: %.c rule in inc/common.mk now passes -MMD -MP.  The compiler writes
foo.d beside foo.o listing the headers that compile really read, and an
-include reads them back.  Nine makefiles keep a compile rule of their own,
because they add -DGBROWSE, -DGFSERVER_HUGE or -DCGI_BIN=; each got ${DEPGEN}
too.  lib and hg/lib are the only two that build objects into a subdirectory,
and each reads its own subdirectory .d files at the foot of its own file.

Touching hg/hgTracks/wigCommon.h used to rebuild 2 objects.  It now rebuilds
11, which is every .c file in that directory that includes the header.

A .d file holds rules, and make takes its default goal from the first rule it
reads, included files and all.  common.mk is read before a makefile's own
rules, so the include has to save $(.DEFAULT_GOAL) and set it back afterwards;
without that, make in lib built adjacency.o and stopped.

Fifteen link rules in directories the build enters named a library on the
command line without depending on it.  Each now lists it.  hg/hgPhyloPlace,
hg/visiGene/hgVisiGene and hg/orthoMap were the three whose target is a real
file and could go stale.

make clean still leaves the .d files.  A shared clean:: rule in common.mk would
first mean converting about 320 single-colon clean: rules, since make refuses
to mix the two forms on one target.  A leftover .d cannot break a build: -MP
writes an empty target for each header, so a deleted or renamed one does not
leave make asking for a file no rule can build.

refs #36621

diff --git .gitignore .gitignore
index 4af1a081f1a..0148c0dd55f 100644
--- .gitignore
+++ .gitignore
@@ -1,72 +1,76 @@
 *.o
+# generated header dependencies, written beside each .o by -MMD.  refs #36621
+*.d
+# ...but that pattern also matches a directory, and this one is checked in
+!src/browserbox/etc/sudoers.d/
 *.a
 *~
 foo
 *.foo
 *.exe
 *.bak
 core
 core.*
 *.pyc
 *.pyo
 tags
 *.gcno
 
 .emacs.bak/
 .claude/
 src/hg/pslCDnaFilter/algo.h
 src/hg/pslCDnaFilter/usage.h
 
 compiled/
 
 # for those that build kent/bin/
 /bin
 
 # build droppings
 src/submodules/zlib-ng-configure.log
 src/hg/hgGateway/hgGateway.html.h
 src/hg/hgPhyloPlace/phyloPlace
 src/isPcr/webPcr/webPcr
 src/utils/pslMap/usage.h
 src/utils/pslMap/usage.msg
 src/webBlat/webBlat
 
 # test results
 **/tests/output/
 **/test/output/
 src/lib/tests/bin/
 src/hg/lib/tests/loader
 
 # other tests output follow conventions
 src/hg/autoDtd/test/chado/out.atree
 src/hg/autoDtd/test/chado/out.dtd
 src/hg/autoDtd/test/chado/out.stats
 src/hg/autoDtd/test/chado/out.tree
 src/hg/autoDtd/test/hotnews/out.atree
 src/hg/autoDtd/test/hotnews/out.dtd
 src/hg/autoDtd/test/hotnews/out.stats
 src/hg/autoDtd/test/hotnews/out.tree
 src/hg/autoDtd/test/shapes/out.atree
 src/hg/autoDtd/test/shapes/out.dtd
 src/hg/autoDtd/test/shapes/out.stats
 src/hg/autoDtd/test/shapes/out.tree
 src/hg/cgilib/tests/bin/
 src/hg/cgilib/tests/udcCache/
 src/hg/liftAcross/tests/testErr.out
 src/hg/liftAcross/tests/testOut.bed
 src/hg/liftAcross/tests/testOutput.gp
 src/hg/sqlToXml/test/visiGeneXml/out.xml
 src/hg/utils/bedMergeAdjacent/tests/output.bed
 src/hg/utils/overlapSelect/usage.h
 src/utils/bedGeneParts/firstCodingSplice.out
 src/utils/bedGeneParts/firstExon.out
 src/utils/bedGeneParts/introns.out
 src/utils/bedGeneParts/promoter.out
 src/utils/clusterMatrixToBarChartBed/tests/test.output
 src/utils/cpgIslandExt/tests/testOutput.bed.gz
 src/utils/matrixMarketToTsv/tests/out.tsv
 src/utils/pslRemoveFrameShifts/tests/out/
 src/utils/pslScore/tests/NP_149062.tab
 src/utils/pslScore/tests/NP_149062Pl.tab
 src/utils/trackDbIndexBb/tests/out/