From 9bd4957fa9ae7a2946cb7ae9a706541c3e42aaf6 Mon Sep 17 00:00:00 2001 From: "Darryl L. Miles" Date: Wed, 22 Jul 2026 19:59:42 +0000 Subject: [PATCH] =?UTF-8?q?build:=20-j=20correctness=20=E2=80=94=20databas?= =?UTF-8?q?e=20archive=20edge=20+=20serial=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes make a parallel `make -jN` deterministic: 1. lib@database: module@tiles module@utils. libdatabase.a physically archives tiles/libtiles.o and utils/libutils.o (database/Makefile.in LIB_OBJS +=), so lib@database must wait for those module objects. A serial build got this from prerequisite order; under -j it was a latent race (it happened to win most of the time because tiles/utils are quick). Audited all Makefile.in: no other default-built module archives another module's objects (magic's EXTRA_LIBS is covered by main@: modules libs; the ext2*/router tools are not in the default build). 2. docs runs the doc/latexfiles sub-make with -j1. Those rules share per-run .aux/.log files in one directory and are not parallel-safe; under an inherited jobserver they raced and dropped documents (5-9 of 28 failed under -j vs 1 serial). Doc regeneration is best-effort (pre-built PostScript is the install fallback), so forcing it serial costs nothing. Verified: 5x clean out-of-tree `make -j12` all rc=0 with zero core-build errors and a stable 27/28 docs; in-tree -j12 installs 375 files; --without-tcl -j12 builds readline + magic. Serial behaviour unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- Makefile.in | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Makefile.in b/Makefile.in index 7508841d..34c9a389 100644 --- a/Makefile.in +++ b/Makefile.in @@ -107,14 +107,18 @@ $(MODULE_TARGETS): module@%: depend $(LIB_TARGETS): lib@%: depend @$(call submake,$*,lib) +# Cross-module archive edge (-j correctness): libdatabase.a physically archives +# tiles/libtiles.o and utils/libutils.o (database/Makefile.in: LIB_OBJS += ...), +# so lib@database must not run until those module objects exist. A serial build +# got this from prerequisite order; under -j it needs the explicit edge. No other +# default-built module archives another module's objects. +lib@database: module@tiles module@utils + .PHONY: modules modules: $(MODULE_TARGETS) .PHONY: libs -# libdatabase.a needs the tiles/utils module objects first. Listing them before -# $(LIB_TARGETS) orders a serial build correctly; the explicit per-target -j edge -# is added in a later commit. -libs: module@tiles module@utils $(LIB_TARGETS) +libs: $(LIB_TARGETS) # # extcheck - utility tool @@ -148,11 +152,15 @@ $(TECH_TARGETS): tech@%: depend techs: $(TECH_TARGETS) # Regenerate the PostScript documentation from its .tex sources (only reached -# from "all" when configure found latex+dvips; see DOCS_TARGET). +# from "all" when configure found latex+dvips; see DOCS_TARGET). Force -j1: the +# latexfiles rules share per-run aux files (.aux/.log) in one directory and are +# not parallel-safe, so under a parallel top-level build they would race and drop +# documents. Doc regeneration is best-effort anyway (pre-built PostScript is the +# install fallback), so serializing it costs nothing and keeps -j deterministic. .PHONY: docs docs: @echo --- making documentation - @${MAKE} -k -C doc/latexfiles all || \ + @${MAKE} -j1 -k -C doc/latexfiles all || \ echo "--- WARNING: some documents did not regenerate; the pre-built PostScript will be used for those at 'make install'" install: $(INSTALL_TARGET)