Skip to content

tex.mk: put preprocessing output where the targets are; fix the plain-name links - #91

Open
dbosk wants to merge 2 commits into
fix/texmk-robustnessfrom
fix/texmk-outdir-and-links
Open

tex.mk: put preprocessing output where the targets are; fix the plain-name links#91
dbosk wants to merge 2 commits into
fix/texmk-robustnessfrom
fix/texmk-outdir-and-links

Conversation

@dbosk

@dbosk dbosk commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Fixes #89. Stacked on #88 (base branch of this PR); merge #84#88
this.

  • The .aux/.bcf/.idx/.nlo preprocess rules ran LaTeX without
    -output-directory, so their outputs landed in cwd and the rules' own
    targets never appeared (bibtex: "I couldn't open file name"; the .bcf
    rule even exited 0 while silently creating nothing). PREPROCESS.tex now
    carries -output-directory — which exposed one more grouped-rule
    instance (.dtx aux-family), split per target like tex.mk grouped pattern rules trigger GNU Make 4.4 peer-target warnings #83.
  • The -${LN} ${TEX_OUTDIR}/$@ $@ link line destroyed freshly built
    prefixed targets (ln -sf ltxobj/ltxobj/x.pdf ltxobj/x.pdf → dangling
    self-symlink, exit 0). The link now exists only in the plain-name
    rules, guarded by the same -ef . idiom clean-tex uses.

A/B evidence: 17-configuration sweep (TEX_OUTDIR = ltxobj / "." / "",
both target forms, bibtex/biber/xindy/makeindex paths) with
byte-identical outputs where behavior must not change and
SOURCE_DATE_EPOCH-frozen PDFs; the #83/#85/#86/stabilization behaviors
re-verified unregressed; makefiles' own 116-page PDF builds clean.
Real-world gate: nytid's full doc build with this branch — exit 0,
0 peer warnings, 0 failed recipes, 0 bibtexu, 1106 pages.

Note: TEX_OUTDIR="" remains globally unusable (documented, matching
87d470f's stance), and the TEX_OUTDIR=. case depends on rule order
within each pair (called out in the prose so a reorder can't silently
regress it).

🤖 Generated with Claude Code

https://claude.ai/code/session_01AhWZp3q1126cvw9bW8VBB5

dbosk and others added 2 commits August 26, 2026 13:11
The rules making an .aux, a .bcf, an .idx or an .nlo all name their target
inside TEX_OUTDIR, and all ran PREPROCESS.tex -- a bare latexmk invocation.
A bare latexmk writes beside the source, so each of these rules created an
empty TEX_OUTDIR, left its file in the working directory, and exited zero.
make judges a recipe by its exit status and not by what appeared on disk,
so it took that for a success and went on with a target that did not exist.

Who noticed was whoever asked for the file next, one step removed from the
rule at fault.  bibtex is handed ${TEX_OUTDIR}/x.aux and answers "I couldn't
open file name"; texindy and makeindex say as much of the .idx and the .nlo.
The .bcf has no downstream complaint of its own to make, so there the file
simply stayed missing and the build carried on as though it were not.

Pass -output-directory, which is what the compilation commands already do.
Measured on TeX Live 2025 with GNU Make 4.4.1: "make ltxobj/doc.bbl" on a
document with a bibliography went from bibtex "Error 1" to a .bbl
byte-identical to the one the same document yields with TEX_OUTDIR set to
".", and the .ind, .nls and .bcf rules likewise now produce the file they
promise.  With TEX_OUTDIR set to "." the option names the working directory
and the output is byte-identical to before.  With it set to the empty string
these rules were unreachable and remain so, their targets reading /%.aux and
the like -- as broken as they were, not differently broken.

Splitting the .dtx preprocessing rule comes along with the fix rather than
beside it.  Its three targets sat on one pattern rule, which to GNU Make 4.4
means one recipe producing all three; the rule got away with the claim only
for as long as its recipe wrote none of them.  With the run put where the
targets are it writes one, and make begins reporting the two peers it did
not -- the shape 55a6efb and 19291fb took out of the other rules.  One rule
per name, sharing the recipe through a chunk, and the count is zero again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every document rule ended with "-${LN} ${TEX_OUTDIR}/$@ $@", the twins of
55a6efb and 19291fb included.  On the plain name that is what it looks like:
doc.pdf becomes a link to the file compiled in ltxobj.  On the name that
already carries the prefix it is not.  There $@ is ltxobj/doc.pdf, so the
line reads

	ln -sf ltxobj/ltxobj/doc.pdf ltxobj/doc.pdf

and the freshly compiled PDF is replaced by a symbolic link to a path that
does not exist.  The leading "-" swallowed ln's complaint, and make reported
success over a document that was no longer there.  Both twins of all four
pairs did it: .tex to PDF and to DVI, .dtx to PDF and to DVI.

The plain name has its own version of the accident when TEX_OUTDIR is the
empty string, where ${TEX_OUTDIR}/$@ reads /doc.pdf and links the one real
file away to it.  Set TEX_OUTDIR to "." and ln(1) saves us instead, refusing
to link a file to itself -- at the price of an error line on every build.

Both are the same question asked too late: whether the two names are two
files at all.  Ask it first, and of the directories rather than the names,
with the -ef test clean-tex already uses; and give the link to the rule for
the plain name alone, since a rule whose target carries the prefix has been
handed the file under the name it was asked for.  Nothing is lost with it:
the link that rule used to make was never a usable one.

Measured on TeX Live 2025 with GNU Make 4.4.1, timestamps frozen through
SOURCE_DATE_EPOCH.  Asking for ltxobj/doc.pdf, ltxobj/doc.dvi,
ltxobj/demo.pdf or ltxobj/demo.dvi now yields the compiled file rather than
a dangling link, byte-identical to what the plain name yields; with
TEX_OUTDIR empty, doc.pdf is the compiled file rather than a link to
/doc.pdf, byte-identical to the "." configuration; with TEX_OUTDIR "." the
output is byte-identical to before and the ln error line is gone; and the
default ltxobj configuration is unchanged in every respect.  The
peer-target count stays zero, and the good/broken/oscillating trio still
exits 0 silently, fails, and warns while succeeding.

One thing the split makes newly load-bearing: with TEX_OUTDIR set to "." the
two patterns of a pair coincide, make keeps the later rule, and the later
rule is the one without the link -- which is the right one there, but only
because of the order they are written in.

Fixes #89.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant