背景
因此,我了解到 latexmk 会运行 pdflatex 直到“所有文件都是最新的”。
问题与动机
假设我有一些动态内容,应该只运行一次。动态是指每次运行时都会发生变化的内容。
原则上:假设您有一个\randomNumber
每次运行时都会发生变化的命令,为您提供一个随机数,从而导致 latexmk 永远运行。
一个现实世界的例子是编译Rnw
具有随机性的文件。
\immediate\write18{compileMyKnitr}\input{myRnw.tex}
问题
有没有
- 一个 latex 命令可以告诉我 latexmk 已经运行了多少次
和/或
- 可以使用一些奇特的逻辑,例如 .aux 文件来确定这是否是第一次运行?
理想情况下\ifFirstRun{\doSomething}
或\LatexmkRunOnce{\doSomething}
答案1
解决方案分为两部分。
首先是制作一个 .tex 文件,检测它是否在第一次运行时被编译:
\documentclass{article}
\makeatletter
\AtEndDocument{\write\@auxout{\gdef\string\notfirstrun{}}}
\newcommand{\iffirstrun}{%
\@ifundefined{notfirstrun}}
\makeatother
\begin{document}
foo
\iffirstrun{yes}{no}
\end{document}
(请注意,使用的语法\iffirstrun
与标准构造的语法不同\iff...
。当然,这可以修复。)
该解决方案在 .aux 文件中放置一行\gdef\notfirstrun{}
,以标记下一次运行不是第一次。
但是,仅使用解决方案的这一部分,当latexmk
在源文件更改后再次调用时,第一次实际运行将不会被视为文档的第一次运行。这通常是不希望的。可以通过删除 .aux 文件来避免这种情况,这可能会导致大量额外的处理(并且很容易忘记)。此问题通过文件中的以下代码解决latexmkrc
:
$latex = 'internal my_latex latex %O %S';
$lualatex = 'internal my_latex lualatex %O %S';
$pdflatex = 'internal my_latex pdflatex %O %S';
$xelatex = 'internal my_latex xelatex -no-pdf %O %S';
sub my_latex {
if ( ( -e $aux_main ) && ($pass{$rule} == 1) ) {
print "========Remove any 'notfirstline' line from aux file\n";
my $aux_bak = "$aux_main.bak";
rename $aux_main, $aux_bak;
my $auxold = new FileHandle;
my $auxnew = new FileHandle;
open $auxold, "<$aux_bak";
open $auxnew, ">$aux_main";
while (<$auxold>) {
if ( ! /^\\gdef \\notfirstrun\{\}$/ ) { print $auxnew $_; }
}
close $auxold;
close $auxnew;
}
return system( @_ );
}
它使用了几个内部变量latexmk
:$aux_main
和$pass{$rule}
。
答案2
这里有一个解决方案。删除.aux
意味着重新启动计数器(即使这里没有使用计数器)。
1)
\documentclass{article}
\providecommand\runsnumber{1}
\makeatletter
\AtEndDocument{%
\write\@auxout{%
\xdef\string\runsnumber{\the\numexpr\runsnumber+1\relax}}}
\makeatother
\begin{document}
foo
\runsnumber
\end{document}
2)
\documentclass{article}
\makeatletter
\AtEndDocument{\write\@auxout{\gdef\string\notfirstrun{}}}
\newcommand{\iffirstrun}{%
\@ifundefined{notfirstrun}}
\makeatother
\begin{document}
foo
\iffirstrun{yes}{no}
\end{document}