tex.mk: put preprocessing output where the targets are; fix the plain-name links - #91
Open
dbosk wants to merge 2 commits into
Open
tex.mk: put preprocessing output where the targets are; fix the plain-name links#91dbosk wants to merge 2 commits into
dbosk wants to merge 2 commits into
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #89. Stacked on #88 (base branch of this PR); merge #84 → #88 →
this.
-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.
-${LN} ${TEX_OUTDIR}/$@ $@link line destroyed freshly builtprefixed 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