确定在 LaTeX 中 latexmk 运行了多少次

确定在 LaTeX 中 latexmk 运行了多少次

背景

因此,我了解到 latexmk 会运行 pdflatex 直到“所有文件都是最新的”。

问题与动机

假设我有一些动态内容,应该只运行一次。动态是指每次运行时都会发生变化的内容。

原则上:假设您有一个\randomNumber每次运行时都会发生变化的命令,为您提供一个随机数,从而导致 latexmk 永远运行。

一个现实世界的例子是编译Rnw具有随机性的文件。

\immediate\write18{compileMyKnitr}\input{myRnw.tex}

问题

有没有

  1. 一个 latex 命令可以告诉我 latexmk 已经运行了多少次

和/或

  1. 可以使用一些奇特的逻辑,例如 .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} 

相关内容