build: -j correctness — database archive edge + serial docs

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) <noreply@anthropic.com>
This commit is contained in:
Darryl L. Miles 2026-07-22 19:59:42 +00:00 committed by R. Timothy Edwards
parent e84e353a40
commit 9bd4957fa9
1 changed files with 14 additions and 6 deletions

View File

@ -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)