自定义格式文件:当其中一个文件发生更改时,如何自动生成“预编译前言”

自定义格式文件:当其中一个文件发生更改时,如何自动生成“预编译前言”

我想使用预编译序言方法,我想知道是否有任何自动文档编译工具对此表示支持。

主要思想是:

  • 将文档拆分为“静态”部分和“动态”部分,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.texfigure.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_DEPSINPUT此列表中的行被提取(通过sedxargs)成可用作 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),但它可能会给您一些启发。

相关内容