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'
这正好位于问题中引用的输出之上。
可能的解决方案:
这些更改与最终输出无关,因此您必须
latexmk
忽略它们。这可以通过将以下行添加到适当的文件来完成latexmkrc
:$hash_calc_ignore_pattern{'pdf'} = '^/CreationDate |^/ModDate |^/ID \\[<';
然而,仍然存在一个问题,即使用发布的 MWE 时,
.pdf
每次运行时都会重新创建文件pdflatex
,无论是否需要,这都会非常耗时。或者,您可以通过在第一个示例中的选项列表中替换 来停止每次运行时
pstool
重新创建。在第二个示例中,您删除了之后的。但如果替换发生变化,这不会更新 pdf 文件;只有在文件发生变化时才会更新。trial.pdf
process=all
process=auto
pstool
*
\psfragfig
psfrag
.eps
另一个解决方案是将文件的制作委托
.pdf
给latexmk
。为此,您应该关闭 选项的使用-shell-escape
。pdflatex
要做到这一点,需要在文件中使用一些技巧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
。