我不确定这是否是众所周知的事实,但是如果使用与该文档的文件名不同的作业名来编译 LaTeX 文档,则使用 tikz 外部化库效果不佳。
例如,如果使用pdflatex
(请注意参数)编译以下 MWE,则除非文件已命名(为方便起见,我们假设它名为),-jobname output
否则它将无法工作:output.tex
main.tex
%& -jobname=output
\documentclass{book}
\usepackage{tikz,pgfplots}
\usetikzlibrary{external}
\tikzset{external/only named=true}
\pgfplotsset{compat=newest}
\tikzexternalize
\begin{document}
\begin{figure}[h]
\tikzsetnextfilename{sample_tikz}
\begin{tikzpicture}[scale=1.50]
\begin{axis}\addplot {x^3};\end{axis}
\end{tikzpicture}
\caption{Sample tikz picture.}
\end{figure}
\end{document}
如果编译时没有-jobname
参数,它可以正常工作,而如果有参数,我就会收到如下错误:
===== 'mode=convert with system call': Invoking 'pdflatex -shell-escape -halt-o
n-error -interaction=batchmode -jobname "sample_tikz" "\def\tikzexternalrealjob
{output}\input{output}"' ========
! Package tikz Error: Sorry, the system call 'pdflatex -shell-escape -halt-on-e
rror -interaction=batchmode -jobname "sample_tikz" "\def\tikzexternalrealjob{ou
tput}\input{output}"' did NOT result in a usable output file 'sample_tikz' (exp
ected one of .pdf:.jpg:.jpeg:.png:).
从错误信息中,也可以很明显地看出哪里出了问题。默认的外部化系统调用如下所示:
pdflatex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource"
其中宏\texsource
为\edef
\string\def\string\tikzexternalrealjob{\tikzexternal@realjob}\string\input{\tikzexternal@realjob}
并根据编译时使用\tikzexternal@realjob
的值进行设置。当使用 进行编译时,会扩展为\jobname
main.tex
main.tex
-jobname output
\texsource
\def\tikzexternalrealjob{output}\input{output}
这是有问题的,因为main.tex
没有被调用output.tex
。
可能的解决方案
我尝试查看 tikz 外部源代码,并尝试如何解决这个问题。我的理由是,我希望以\texsource
某种方式扩展到
\def\tikzexternalrealjob{output}\input{main}
而是(请注意,\tikzexternalrealjob
仍然必须\def
将其添加到实际的\jobname
,因为它在 tikz 外部化代码中用于决定当前作业是针对主文档还是针对 tikz 图像的外部化)。
我受到启发这个帖子使用该currfile
包(感谢@martin-scharrer)自动检索名称main
。
到目前为止我想到的是(似乎有效)如下:
将 MWE 更改为:
%& -jobname=output -recorder
\documentclass{book}
\usepackage{tikz,pgfplots}
\usetikzlibrary{external}
\tikzset{external/only named=true}
\pgfplotsset{compat=newest}
\input{externalize-hack.tex} % <---- THIS WAS ADDED
\tikzexternalize
\begin{document}
\begin{figure}[h]
\tikzsetnextfilename{sample_tikz}
\begin{tikzpicture}[scale=1.50]
\begin{axis}\addplot {x^3};\end{axis}
\end{tikzpicture}
\caption{Sample tikz picture.}
\end{figure}
\end{document}
并让文件externalize-hack.tex
定义如下:
\usepackage{currfile-abspath}
\getmainfile
\usepackage{xpatch}
\makeatletter
\AtEndDocument{%
\newwrite\maindeffile%
\immediate\openout\maindeffile=\jobname.maindef%
\immediate\write\maindeffile{%
\noexpand\ifcsname mymainfile\noexpand\endcsname\noexpand\else%
\noexpand\gdef\noexpand\mymainfile{\mymainfile}%
\noexpand\fi%
}%
\immediate\closeout\maindeffile%
}
\@input{\jobname.maindef}
\ifcsname mymainfile\endcsname%
\ifx\mymainfile\@empty%
% Make a second attempt at extracting the real file name
% (necessary because currfile needs two runs on MiKTeX..)
\filename@parse{\themainfile}%
\let\mymainfile\filename@base%
\ifx\mymainfile\@empty%
% If still empty, fallback to default behavior
\def\mymainfile{\tikzexternal@realjob}%
\fi%
\fi%
\else%
% First attempt at extracting real file name
\filename@parse{\themainfile}%
\let\mymainfile\filename@base%
\fi%
\xpatchcmd{\tikzexternal@assemble@systemcall}%
{%
\edef\texsource{%
\string\def\string\tikzexternalrealjob{\tikzexternal@realjob}%
\string\input{\tikzexternal@realjob}%
}%
}%
{%
\edef\texsource{%
\string\def\string\tikzexternalrealjob{\tikzexternal@realjob}%
\string\def\string\mymainfile{\mymainfile}%
\string\input{\mymainfile}%
}%
}%
{}
{}
\let\old@tikzexternalize@opt@withname\tikzexternalize@opt@withname%
\def\tikzexternalize@opt@withname[#1]#2{%
% Suppress externalization as long as \mymainfile is empty
% (This will only be the case the one or two first compilation runs!)
\ifx\mymainfile\@empty\else%
\old@tikzexternalize@opt@withname[#1]{#2}%
\fi%
}
\makeatother
还请注意-recorder
,根据currfile
包的要求,添加了选项。
但是,我觉得这个 hack 有点笨拙。因此,我非常感谢你们的任何意见!
答案1
您知道 tikz 用来\jobname
编写生成外部图片的命令行。因此重新定义\jobname
并同时使用 tikz 外部化太麻烦了。
可能的解决方法:
- 用于
\tikzsetfigurename{something}
设置外部 tikz 图片的基本名称; - 称呼
pdflatex
没有-jobname output
每次你改变 tikzpicture 时它都会正确生成图形; - 使用生成的外部图形,您可以随意更改文本中的所有内容并调用,
pdflatex -jobname output
因为只计算校验和而不需要真实的作业名称。
它与我的 MWE 一起工作:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize
\tikzsetfigurename{something}
\begin{document}
\tikz \draw (0,0) -- (1,0.5);
\tikz \draw[red] (0,0) -- (1,0.5);
\end{document}
调用顺序:
pdflatex -shell-escape main
(此处somethingN
生成数字)pdflatex -shell-escape -jobname output main