如何使用 pdflatexmk 脚本通过 pstool 包编译文档?

如何使用 pdflatexmk 脚本通过 pstool 包编译文档?

psfrag为了与 pdflatex 一起使用,我使用了pstool包。使用 TeXShop 3.25,我可以编译给出的两个最小工作示例当我使用常规 LaTeX 排版机时,我会回答。

来自第一个答案如下所示:

% compiled by `pdflatex --shell-escape` enabled
\documentclass{book}
\listfiles % to show the list of packages loaded in .log file
\usepackage[crop=pdfcrop,process=all,cleanup={.tex,.dvi,.ps,.pdf,.log}]{pstool} 
% Good options for pstool package
\EndPreamble % Will help to pick the right preamble in pstool auxillary process 
\usepackage{color}
\begin{document}
\begin{figure}
\centering
\includegraphics[width=0.8\linewidth]{trial.eps}
\caption{Tagged eps image}
\end{figure}
\begin{figure}
\centering
\psfragfig[width=0.8\linewidth]{trial}{\color{red}
  \psfrag{[Mp]}{$M_A$}%
  \psfrag{[hb]}{$H_B$}} 
\caption{Replacing tags with real labels with psfrag}
\end{figure}
\end{document}

来自第二个答案是:

\documentclass{article}
\usepackage{color}
\usepackage{pstool}
\def\a{A}
\EndPreamble
\begin{document}

\psfragfig*[mode=nonstop]{trial}{%
  \color{red}
  \tiny
  \psfrag{[Mp]}{$M_\a$!}%
}

\end{document}

当我使用pdflatexmk脚本时 - 我已经根据这个答案包含所需的 shell 转义选项pstool- 上述两个示例的编译总是以此错误消息结束:

Latexmk: Maximum runs of pdflatex reached without getting stable files
Latexmk: Did not finish processing file 'trialctan2.tex':
   'pdflatex' needed too many passes
Latexmk: Use the -f option to force complete processing,
 unless error was exceeding maximum runs of latex/pdflatex.
Latexmk: applying rule 'pdflatex'...
Latexmk: All targets (trialctan2.pdf) are up-to-date

为什么会发生此错误?我该如何消除它?
我尝试将-f选项添加到pdflatexmk脚本中,如下所示:

"${LTMKBIN}"/latexmk -pdf -r "${LTMKEDIT}/latexmkrcedit" -r "${TSBIN}/pdflatexmkrc" -f -pdflatex="pdflatex --shell-escape %O %S" "$1"

但同样的错误仍然存​​在。

更新 1:

经过一番挖掘,我发现罪魁祸首是process=all选项。在第二个 MWE 中,它由 后面的星号本地启用psfragfig
使用此选项,每次运行时都会重新创建每个 eps 图形的 pdf 文件。我怀疑脚本pdflatexmk注意到了这一点,并决定需要再次运行,因为有些东西已经发生了变化,触发了新的 eps 到 pdf 转换,再次注意到它,等等……
我想我需要找出如何将process=all选项限制在第一次运行。

答案1

问题是trial.pdf每次运行时都会创建该文件,并且它总是与以前的版本不同。由于latexmk注意到了变化,它假定pdflatex必须再次运行。其输出的末尾是原因:

Rule 'pdflatex': File changes, etc:
Changed files, or newly in use since previous run(s):
  'trial.pdf'

这正好位于问题中引用的输出之上。

可能的解决方案:

  1. 这些更改与最终输出无关,因此您必须latexmk忽略它们。这可以通过将以下行添加到适当的文件来完成latexmkrc

    $hash_calc_ignore_pattern{'pdf'} = '^/CreationDate |^/ModDate |^/ID \\[<';
    

    然而,仍然存在一个问题,即使用发布的 MWE 时,.pdf每次运行时都会重新创建文件pdflatex,无论是否需要,这都会非常耗时。

  2. 或者,您可以通过在第一个示例中的选项列表中替换 来停止每次运行时pstool重新创建。在第二个示例中,您删除了之后的。但如果替换发生变化,这不会更新 pdf 文件;只有在文件发生变化时才会更新。trial.pdfprocess=allprocess=autopstool*\psfragfigpsfrag.eps

  3. 另一个解决方案是将文件的制作委托.pdflatexmk。为此,您应该关闭 选项的使用-shell-escapepdflatex要做到这一点,需要在文件中使用一些技巧latexmkrc。以下是放入其中一个latexmkrc文件的适当代码:

    $pdf_mode = 1;
    $dvi_mode = $postscript_mode = 0;
    # Don't use the following files for a default make
    # by latexmk (i.e., with no files on the command line):
    @default_excluded_files = ( '*-pstool.tex' );
    add_cus_dep( 'eps', 'pdf', 0, eps2pdf_pstool );
    $pdflatex = 'internal pdflatex_pstool %O %S';
    # Patterns to ignore in detecting changes in pdf files made by pstool
    $hash_calc_ignore_pattern{'pdf'} = '^/CreationDate |^/ModDate |^/ID \\[<';
    
    sub pdflatex_pstool {
       # This subroutine runs pdflatex with some pre- and post-processing
       #    that is appropriate when the  pstool package is used.
       #
       # Ensure that there is a dummy pstool-statusfile.txt file so that 
       #   during the run of pdflatex, the pstool package isn't unhappy
       #   enough to report an error.
       if ( ! -e "pstool-statusfile.txt" ) {
          system( "echo 1 > pstool-statusfile.txt" );
       }
       # The actual run of pdflatex, with the specified arguments this
       #   subroutine has  been given
       my $return = system( 'pdflatex', @_ );
       # Fix up the dependencies on eps files given special processing by
       #    pstool.  These are flagged by the existence of files named
       #    "*-pstool.tex".  To get latexmk to use these, it is sufficient
       #    to tell it that there is a corresponding pdf file that needs
       #    to be made. 
       foreach my $cand ( glob "*-pstool.tex" ) {
          # Get the basename of the associated graphics file.
          # This is done by Perl regex on the r.h.s. of the assignment in
          #    the next statement.  The variable $base is surrounded by
          #    parentheses, so that ($base) is a one-element array to
          #    which is assigned the first pattern ($1) in parentheses in
          #    the regex. Without the parentheses around $base, $base
          #    would be set to an essentially boolean value for a
          #    successful search.
          my ($base) = ($cand =~ /^(.*)-pstool.tex$/ );
          if ( -e "$base.eps" ) {
             # We get here if we know that both a $base-pstool.tex file
             #   and a $base.eps file exists.  This indicates that there
             #   is a file $base.pdf that needs to be made from $base.eps
             #   with the aid of applying latex to $base-pstool.tex.
             # The important thing is that this pdf file is a source file
             #   of the main run of pdflatex (and hence for the rule used
             #   to invoke the current subroutine).
             # Once the dependency on the pdf file is set, latexmk
             #   will do the rest, by finding the eps file from which the
             #   pdf file is made and setting a suitable rule to make the
             #   pdf file, by the custom dependency method.
             rdb_ensure_file( $rule, "$base.pdf" );
          }
       }
       return $return;
    }
    
    sub eps2pdf_pstool {
       # Note that when this subroutine is invoked, $rule is set to the
       #   name of the current rule (which is an eps to pdf custom
       #   dependency). 
       my $base = $_[0];
       my $source = "$base.eps";
       my $dest = "$base.pdf";
       my $pstool_base = "$base-pstool";
       if ( -e "$pstool_base.tex" ) {
          # Use pstool processing chain
          #
          # This rule needs a dependency on the tex file used to make
          #    the pdf file:
          rdb_ensure_file( $rule, "$pstool_base.tex" );
          my $return = 0;
          # Generate the pdf file by the method used by pstool
          # I assume that the image is to be cropped.
          # The following code copies what pstool would do directly from
          #   the main run of pdflatex if it were allowed by a option
          #   shell-escape to pdflatex.
          $return = 
             system( "latex",
                     "-output-format=dvi",
                     "-interaction=batchmode",
                     "-shell-escape",
                     "$pstool_base.tex" )
             || system( "dvips", "-q", "-Ppdf", "$pstool_base.dvi" )
             || system( "ps2pdf",
                        "-dAutoFilterColorImages=false",
                        "-dAutoFilterGrayImages=false",
                        "-dColorImageFilter=/FlateEncode",
                        "-dGrayImageFilter=/FlateEncode",
                        "-dPDFSETTINGS=/prepress",
                        "$pstool_base.ps",
                        "$pstool_base.pdf" )
             || system( "pdfcrop", "$pstool_base.pdf", "$base.pdf" );
          # The pstool package likes the result of the commands to be
          #    stored in a status file:
          system( "echo $return > pstool-statusfile.txt" );
          if ( $return == 0 ) {
             # If there was no error, clean up intermediate files, but
             #   leave them as they if there was an error; the user may
             #   want to  use the files to diagnose the error.  
             # But leave the aux file, since pstool wants to read it.
             foreach my $ext ( "log", "dvi", "ps", "pdf" ) {
                unlink "$pstool_base.$ext";
             }
          }
          return $return;
       }
       else {
          # Use standard epstopdf processing
          return system( "epstopdf $_[0].eps --outfile=$_[0].pdf" );
       }
    }
    

    注意:使用此解决方案时,最好通过以下方式pstool在主文档中调用该包latex

    \usepackage[crop=pdfcrop,process=auto,cleanup={.dvi,.ps,.pdf,.log}]{pstool}
    

    这将确保如果您碰巧调用pdflatex-shell-escape选项,它不会对所做的工作造成太多干扰latexmk

相关内容