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/