使用 lualatex 结合自动 inkscape 导入实现 tikz 外部化

使用 lualatex 结合自动 inkscape 导入实现 tikz 外部化

我有一份包含大量图表的大型文档。对于图表,我使用 matlab,然后使用 matlab2tikz 将图表转换为 tikz(之后进行一些修改),对于大多数其他图表,我更喜欢 Inkscape 及其 pdf_tex 导出。对于 tikz 和 Inkscape,如果图表中确实发生了变化,我都希望自动重新生成图表。我有两个自定义命令,\includetikz 和 \includesvg。一切都运行良好,直到我不得不将 tikz 图表从 pdflatex 更改为 lualatex。我有一些图表,我无法进一步减少数据,而且我无法使用 pdflatex 排版这些图表(也增加了内存设置)。使用 lualatex 效果很好。现在的问题是,lualatex 的 \includetikz 命令会以某种方式干扰我的 \includesvg 命令。

我有以下 MWE:

\documentclass[11pt,a4paper,english]{scrbook}
\usepackage{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\RequirePackage{luatex85}

% inkscape
\usepackage{import}
\newcommand{\executeiffilenewer}[3]{%
    \ifnum\pdfstrcmp{\pdffilemoddate{#1}}%
    {\pdffilemoddate{#2}}>0%
    {#3}\fi%
}
\newcommand{\includesvg}[2]{%
    \immediate\write18{if not exist #1.svg_external/ (mkdir "#1.svg_external/")}%
    \executeiffilenewer{#1#2.svg}{#1.svg_external/#2.pdf}{%
        \immediate\write18{"C:/Program Files (x86)/Inkscape/inkscape.exe" -z -C --file=#1#2.svg --export-pdf=#1.svg_external/#2.pdf --export-latex}}%
    \import{#1.svg_external/}{#2.pdf_tex}%
}

\usepackage{filemod}
\newlength{\figheight}
\newlength{\figwidth}
\usepackage{tikz}
\usepackage{pgf}
\usepackage{pgfplots}
\usepgfplotslibrary{external}
\pgfplotsset{compat=1.14}
\tikzexternalize % activate externalization
\tikzset{external/system call={lualatex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource"}}
\tikzset{external/figure list=true}
\tikzset{external/up to date check=simple}
\newcommand{\tikzcustomremake}[2]{\tikzset{external/remake next}}
\newcommand{\includetikz}[2]{%
    \tikzsetnextfilename{#1.tikz_external/#2}%
    \filemodCmp{#1#2.tikz}{#1.tikz_external/#2.pdf}%
    {\tikzcustomremake{#1}{#2}}{}%
    \input{#1#2.tikz}%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\begin{document}

\figwidth=5cm
\figheight=5cm
\includetikz{fig/ch1/}{plot2}

%\footnotesize\includesvg{fig/ch1/}{inkscape1}

\end{document}

不幸的是,Inkscape 命令包含它的绝对路径,因此您可能需要更改它。plot2.tikz 的代码如下:

\begin{tikzpicture}
\begin{axis}[%
width=\figwidth,
height=\figheight,
xmin=0,xmax=10,
xlabel=\pgfactualjobname,
ymin=-1,ymax=5,
axis background/.style={fill=white}
]
\addplot [color=red,solid,forget plot]
  table[row sep=crcr]{%
0   0\\
10  1\\
};
\end{axis}
\end{tikzpicture}%

文件 inkscape1.svg 可以是任何 svg,例如:https://de.wikipedia.org/wiki/LaTeX#/media/File:LaTeX_logo.svg

我现在的问题是:如果我按原样运行代码,一切都会正常工作。svg 被注释掉,生成的 pdf 仅包含图。之后,再次删除 \includesvg 命令的注释,一切正常。生成了 pdf_tex,pdf 中有两个图。但是,如果我在 tikz 文件中进行一些更改,例如必须重新生成图,lualatex 就会失败。

日志文件对我没有任何帮助。在主文档的日志文件中,错误部分如下:

Writing 'fig/ch1/.tikz_external/plot2' to 'diss01lua.figlist'.
\openout3 = `diss01lua.auxlock'.

===== 'mode=convert with system call': Invoking 'lualatex -shell-escape -halt-o
n-error -interaction=batchmode -jobname "fig/ch1/.tikz_external/plot2" "\def\ti
kzexternalrealjob{diss01lua}\input{diss01lua}"' ========
runsystem(lualatex -shell-escape -halt-on-error -interaction=batchmode -jobname
 "fig/ch1/.tikz_external/plot2" "\def\tikzexternalrealjob{diss01lua}\input{diss
01lua}")...executed.

\openout3 = `diss01lua.auxlock'.


! Package tikz Error: Sorry, the system call 'lualatex -shell-escape -halt-on-e
rror -interaction=batchmode -jobname "fig/ch1/.tikz_external/plot2" "\def\tikze
xternalrealjob{diss01lua}\input{diss01lua}"' did NOT result in a usable output 
file 'fig/ch1/.tikz_external/plot2' (expected one of .pdf:.jpg:.jpeg:.png:). Pl
ease verify that you have enabled system calls. For pdflatex, this is 'pdflatex
 -shell-escape'. Sometimes it is also named 'write 18' or something like that. 
Or maybe the command simply failed? Error messages can be found in 'fig/ch1/.ti
kz_external/plot2.log'. If you continue now, I'll try to typeset the picture.

See the tikz package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.16 \end{tikzpicture}
                      %
This error message was generated by an \errmessage
command, so I can't give any explicit help.
Pretend that you're Hercule Poirot: Examine all clues,
and deduce the truth by order and method.

plot2 日志文件的最后几行是:

LaTeX Font Info:    External font `lmex10' loaded for size
(Font)              <10.95> on input line 15.
LaTeX Font Info:    External font `lmex10' loaded for size
(Font)              <8> on input line 15.
LaTeX Font Info:    External font `lmex10' loaded for size
(Font)              <6> on input line 15.
[1

{C:/ProgramData/MiKTeX/2.9/pdftex/config/pdftex.map}])
if not exist fig/ch1/.svg_external/ (mkdir "fig/ch1/.svg_external/")
! Undefined control sequence.
\executeiffilenewer #1#2#3->\ifnum \pdfstrcmp 
                                              {\pdffilemoddate {#1}}{\pdffil...
l.51 \footnotesize\includesvg{fig/ch1/}{inkscape1}


Here is how much of LuaTeX's memory you used:
 25909 strings out of 494568
 100000,953878 words of node,token memory allocated
 1158 words of node memory still in use:
   4 hlist, 1 rule, 7 disc, 1 local_par, 1 dir, 23 glue, 4 kern, 2 penalty, 85 g
lyph, 7 attribute, 47 glue_spec, 7 attribute_list, 1 if_stack nodes
   avail lists: 2:739,3:212,4:5,5:13,7:182,8:2,9:78,10:1
 29028 multiletter control sequences out of 65536+200000
 27 fonts using 1573183 bytes
 65i,11n,111p,8876b,1869s stack positions out of 5000i,500n,10000p,200000b,50000s
!  ==> Fatal error occurred, no output PDF file produced!

我发现有趣的是,lualatex 以某种方式看到了 inkscape 的东西,我不明白。

我在这里上传了完整的日志文件,希望它们有帮助:http://www.uni-ulm.de/~pqa62/tex/

有人知道该如何修复此行为吗?我真的很喜欢我进行外部化和自动重建的方式,尤其是因为在我的包含命令的完整实现中涵盖了一些更高级的内容,而且在我不得不切换到 lualatex 之前一切都正常。

编辑:

我做了更多测试,发现自定义命令\executeiffilenewer显然是问题所在,这也是错误发生的原因。不知何故,lualatex(它应该只排版 tikz-plot)也会查看以下\includesvg命令并尝试执行它。在这里,它不知道这个自定义命令,因为它没有在其调用中定义。如果我\includesvg像这样修改命令:

\newcommand{\includesvg}[2]{%
    \immediate\write18{"C:/Program Files (x86)/Inkscape/inkscape.exe" -z -C --file=#1#2.svg --export-pdf=#1.svg_external/#2.pdf --export-latex}%
    \import{#1.svg_external/}{#2.pdf_tex}%
}

我不再收到错误。问题是,它总是执行 Inkscape。而且,我仍然不明白为什么 lualatex 在 tikz-plot 完成后不停止。

答案1

如果您更改-interaction=batchmode为并向文档-interaction=scrollmode添加一些错误或\show命令,则可以看到 luatex 运行编译了整个 tex 文件。并且它在此过程中扩展了命令 - 它能够在 \includetikz 中找到图片,因此自然也必须在 \includesvg 中查找。这意味着 luatex 不知道的命令可能会导致问题。

\pdfstrcmp在 luatex 中没有定义。您可以加载 pdftexcmds 包来获取实现https://tex.stackexchange.com/a/158612/2388。注意:我没有检查 pdftexcmds 是否已经适应 luatex 0.95/1.0,但在我的精简示例中它似乎可以工作。

\documentclass[11pt,a4paper,english]{scrbook}
\usepackage{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{ifluatex}
\ifluatex
\RequirePackage{luatex85}
\usepackage{pdftexcmds}
  \makeatletter
  \let\pdfstrcmp\pdf@strcmp
  \let\pdffilemoddate\pdf@filemoddate
  \makeatother
\fi

\newcommand{\includesvg}{\pdfstrcmp{1}{2}}

\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize % activate externalization
\tikzset{external/system call={lualatex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource"}}
\tikzset{external/force remake}

\newcommand{\includetikz}{%
 \begin{tikzpicture}
  \draw[red](0,0)--(1,1);
 \end{tikzpicture}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\begin{document}

blub 

\includesvg

\includetikz

\end{document}

相关内容