# Is it possible to compile a *TeX document with a single command?

Let's say I have a document that uses cross-references and also bibtex/biblatex to manage the bibliography. Currently I need to run `pdflatex + bibtex/biber + pdflatex` to generate the final document.

It gets kinda boring to do that; is it possible to only need one invocation? Perhaps with the scripting capabilities of LuaTeX?

Unlike this question, I'm not interested in abstraction layers, only in making it happen within *TeX itself.

EDIT: What about the \write18 command? I know that it is possible to it use to at least avoid one call to `bibtex`.

EDIT2: Two people asked me why I don't want an abstraction layer.

1 - Should you need one? It is the most basic functionality of *TeX. It is bloody archaic to have to manage yourself the details of the compilation process. I want to make *TeX better; in this case it means easier to use.

2 - Abstraction layers add complexity and reduce flexibility. You have to worry about its bugs as well (I've been bitten by unreliable error reporting). And what if you want to compile with LuaTeX instead of pdfTeX? Or use biber instead of BibTeX?

-
I am curious why you want to do it in *TeX. What is missing in the various other solutions that use an external language? –  Aditya Sep 21 '10 at 0:01
Does `texinfo` count as `*TeX`? Does `texi2pdf` count as a valid solution? –  Willie Wong Nov 2 '10 at 16:26
why not use something like latexmk to handle multiple compiling passes? –  Mica Nov 2 '10 at 22:24

Sure ... it is even surprisingly easy:

``````\$ pdflatex --fmt=pdftex --shell-escape '\write18{pdflatex hello}\write18{bibtex hello}\write18{pdflatex hello}\bye'
``````

But kidding aside, the answer is no, realistically. As Will, Patrick and TH wrote already, the macro format needs to support it, and there are (in practise) no macro packages that do that.

-

No. Because of the nonlinear flow of cross referencing, you always need multiple passes, and TeX is not designed to perform them in one go. Even LuaTeX can only (at time of writing) perform a single pass of typesetting.

ConTeXt uses LuaTeX as a scripting language to compile its documents as necessary until everything converges, but it still consists of multiple typesetting passes.

For LaTeX things are rather more archaic; recently, Philipp Lehman has written a package called `logreq` to help indicate when more compilations and other programs need to be run.

-
...nonlinear? Nevermind. Do you know of any other packages that builds up upon `logreq`? –  Mateus Araújo Sep 20 '10 at 13:00

Have you looked at latexmk?

http://www.phys.psu.edu/~collins/software/latexmk-jcc/

-
I'd assume so because the OP explicitly excluded options from tex.stackexchange.com/questions/64/…, whose top answer is latexmk. –  doncherry Nov 5 '11 at 10:12

If you drop the references and citations, then sure. Entire books can be compiled with but a single pass.

It's not too hard to come up with a TeX document that changes after every compilation (and I don't just mean using the time) so your invocation of pdflatex, bibtex, pdflatex is not sufficient in every case (or even many cases which is why you often see people suggest pdflatex, bibtex, pdflatex, pdflatex; this is also not sufficient for every case—see the first part of this run-on sentence—but works in many).

Regarding your edit about `\write18`, you can probably arrange for bibtex to run (something like `\write18{bibtex \jobname}`) after the .aux file is closed. You might be able to run pdflatex after the bibtex too. But how does that answer your question? It's not a single pass.

-
I'm aware that a single pass is impossible, I'm just interested in a single invocation of `pdflatex`. I changed the question accordingly. –  Mateus Araújo Sep 20 '10 at 12:57
@araujoms: But one command like `rubber` or `make` is not acceptable? I'm sort of confused about what you want. –  TH. Sep 20 '10 at 17:39
In your .bashrc or .whateverrc file your shell uses, add `alias pdflatex rubber`. –  Jan Hlavacek Nov 2 '10 at 17:05
It's not even possible to get it to converge in general -- even without intentional pathology! –  SamB Dec 1 '10 at 4:05

LaTeX is not setup for that. But if you can control your output (= write your own macro package), then you can do that. Typeset material does not neet to be placed in the PDF the first time. You can typeset your document, throw away the result (but remember the cross references etc.) and then typeset your document again with the correct cross references. If you have forward references (like table of contents), then you need to know on what page the destination will be, this is one thing you can't do (in most of the times) in advance.

-
In theory I think this is hypothetically possible—but do you know any actual system that uses this technique? It'd be a hell of a hack of an output routine. –  Will Robertson Sep 20 '10 at 9:48
Yes, I know two systems that uses this technique, at least to some extend. Not necessarily hacking the output routine, but using other methods. One is the system I/we develop at my company, the other one I am not going to make advertisement for :) –  topskip Sep 20 '10 at 11:29
@Will Robertson: It doesn't seem like it'd be that hard to do the output routine. The output routine would just check some condition and either do the `\shipout` or not. What you'd really need is some way to reset all state and then `\input\jobname` at the end of the document. –  TH. Sep 23 '10 at 0:50
Sure. perhaps it's easier than I'm making it out to be; I'm not too familiar with output routines myself, actually. I'd just be surprised that no-one's done it yet (although with `pdflatex -no-pdf` I guess there are few performance benefits). –  Will Robertson Sep 23 '10 at 1:45

Approaching the question from a shell point of view:

``````# pdflatex -halt-on-error yourdoc.tex && bibtex yourdoc.tex && pdflatex yourdoc.tex
``````

Meaning: if the command `pdflatex yourdoc.tex`is successful, execute `bibtex yourdoc.tex`, and if that is successful, execute `pdflatex yourdoc.tex`

-
You may want something like `-halt-on-error`; else the first command may not even exit if the the compilation of the document is unsuccessful. –  Willie Wong Nov 2 '10 at 19:00

I do this with a makefile.

``````MASTER = foo.pdf

all:\$(MASTER)
@open \$<

%.tex: %.rnw
@echo + Sweaving \$@ from \$< ...
knit '\$<'

%.pdf: %.tex
@ echo + Writing \$@ from \$< ...
@ texi2pdf '\$<'
``````

Or as you have it,

``````foo.pdf: foo.tex
@ echo + Writing \$@ from \$< ...
@ pdflatex \$<
@ bibtex \$*
@ pdflatex \$<
``````

Now you can compile with `make all`, or directly from within `vim` or `emacs` with appropriate bindings.

-