我想使用预编译序言方法,我想知道是否有任何自动文档编译工具对此表示支持。
主要思想是:
将文档拆分为“静态”部分和“动态”部分,
preamble.tex
然后main.tex
main.fmt
使用以下方法从静态部分创建自定义格式文件pdflatex -ini -jobname=main "&pdflatex preamble.tex\dump"
使用以下方式编译您的文档
pdflatex -fmt main main
因此,main.tex
在“常规”编译中仅处理的内容,从而加速构建。但是,如果preamble.tex
或其中使用的任何文件更改,格式文件必须重建。我想自动执行此操作:main.fmt
仅在必要时重建。当然,main.tex
如果静态部分(=格式文件)已更改,也会重新编译和/或如果动态部分的内容或包含内容已经发生变化。
我尝试过 latexmk 和 scons,它们都是非常出色的工具,但目前为止还没有成功。
编辑:Philipp 的回答提醒我,平台之间的可移植性并非理所当然。我正在运行 Linux,但我对完全可移植的解决方案最感兴趣。
平均能量损失
preamble.tex
:
\documentclass{article}
\usepackage{lipsum}
main.tex
:
\begin{document}
\lipsum
\end{document}
答案1
请参阅我的解决latexmk
方案Latexmk 无法看到 .fmt 格式文件的依赖关系. 它现在跟踪用于制作格式文件的文件中的变化。
答案2
如果任何依赖项(传递闭包)发生了变化,则以下基于 make 的方法可以自动重新生成预编译前言。
它基于这样-recorder
的选项pdflatex
:在编译文件时生成一个在编译过程中访问过的所有 INPUT 和 OUTPUT 文件的列表。然后,该列表由某个sed
脚本转换以提取与 make 兼容的依赖项列表。使用此列表,make
如果其中一个输入文件发生更改,则自动重建前言。
最小工作示例
首先,测试方法所需的源文件(MWE)
preamble.tex
:
\documentclass{article}
\usepackage{lipsum}
\usepackage{tikz}
\input{figure}
请注意,除了一些包之外,preamble.tex
还有\input
一个本地文件figure.tex
:
\newcommand{\myfig}{%
\tikz \draw[thick,rounded corners=8pt]
(0,0) -- (0,2) -- (1,3.25) -- (2,2) -- (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);
}
在示例中,这充当了预编译前言的本地依赖项。因此,编辑figure.tex
或简单操作touch figure.tex
应导致重新生成预编译前言。
最后,我们有main.tex
\begin{document}
\myfig
\lipsum
\end{document}
因此,下面是Makefile
将所有内容组合在一起的。只需执行make
,它就会生成预编译的前导码main.fmt
,然后main.pdf
。对 的后续更改main.tex
将不会触发 的重新生成main.fmt
。但是,如果您触摸preamble.tex
或figure.tex
,则会检测到并main.fmt
重新生成:
#####################################################################
#
# Generate depencendcies for precompiled preamble
#
#####################################################################
# standard options passed to sed: include only lines beginning with INPUT,
# remove the INPUT as well as trailing ./ from paths
CREATE_DEPS_OPTIONS = -e '/^INPUT /!d' -e 's/^INPUT //' -e 's/^\.//'
# in order to not check large parts of the local/global texmf-tree we exclude all paths that start with:
# / or texmf/
DEPS_EXCLUDE ?= ^/ ^texmf/
CREATE_DEPS_OPTIONS += $(foreach d,$(DEPS_EXCLUDE), -e '/$(subst /,\/,$(d))/d')
# This includes the extracted deps
MAIN_DEPS= $(shell touch main.fls ; \
cat main.fls | \
sed $(CREATE_DEPS_OPTIONS) | \
sort -u | \
xargs)
all: main.pdf
main.fmt : $(MAIN_DEPS)
@echo "****************************************"
@echo $? changed, hence recompiling precompiled preamble
@echo "****************************************"
@pdflatex -recorder -ini -jobname=main "&pdflatex preamble.tex\dump"
main.pdf : main.fmt main.tex
@pdflatex -fmt ./main main
clean :
@rm *.log *.aux *.pdf *.fmt *.fls
实现细节
命令
pdflatex -recorder -ini -jobname=main "&pdflatex preamble.tex\dump"
main.fmt
使用选项构建预编译前言-recorder
。使用此选项,pdflatex
生成在运行期间访问的输入和输出文件列表main.fls
,如下所示:
PWD /Users/lohmann/projects/stackexchange/precompiled
INPUT /opt/local/etc/texmf/texmf.cnf
INPUT /opt/local/var/db/texmf/web2c/pdftex/pdflatex.fmt
INPUT preamble.tex
OUTPUT main.log
INPUT /opt/local/share/texmf-texlive-dist/tex/latex/base/article.cls
INPUT /opt/local/share/texmf-texlive-dist/tex/latex/base/article.cls
INPUT /opt/local/share/texmf-texlive-dist/tex/latex/base/size10.clo
INPUT /opt/local/share/texmf-texlive-dist/tex/latex/base/size10.clo
INPUT /opt/local/share/texmf-texlive-dist/tex/latex/lipsum/lipsum.sty
INPUT /opt/local/share/texmf-texlive-dist/tex/latex/lipsum/lipsum.sty
... <lots of more data>
INPUT figure.tex
INPUT figure.tex
OUTPUT main.fmt
在变量的定义中MAIN_DEPS
,INPUT
此列表中的行被提取(通过sed
和xargs
)成可用作 make 依赖项的文件名序列。可以使用正DEPS_EXCLUDE
则表达式传递应忽略的模式;在示例中,我使用它来忽略全局 texmf 树中的依赖项,以加快 make 中的推理过程。如果你真的想要全部每次都要检查依赖项,只需将其设置为空字符串。
答案3
根据@Yossi 的建议,您可以使用make
类似以下规则:
main.pdf: main.fmt main.tex <other dependencies>
pdflatex -fmt main main
main.fmt: preamble.tex <other dependencies>
pdflatex -ini -jobname=main "&pdflatex preamble.tex\dump"
当然,您可以pdflatex -fmt main main
用其他能更好地完成工作的命令替换生成文档的命令,例如latexmk
确保引用得到解析。
答案4
WhizzyTeX(对于 Emacs)就是这样做的。通常它只用于编译文件的一部分,但也可以让它运行整个文件。它实际上在每个“片段”(WhizzyTex 正在编译的代码部分,例如节、小节、幻灯片)的开头保存一个格式文件。
WhizzyTeX 是一种实时更新,这可能正是您想要的。这可能不是您的解决方案(例如,如果您不使用 Emacs),但它可能会给您一些启发。