在某些不明确的条件下,acmart 类与 tikzexternalize 和 lualatex 不兼容,这是 acmart 还是 hyperref 的 bug?

在某些不明确的条件下,acmart 类与 tikzexternalize 和 lualatex 不兼容,这是 acmart 还是 hyperref 的 bug?

我对这个错误感到非常困惑,尤其是它对诸如章节标题中的字符数以及我是否在\begin{abstract}和之间留出任何空格之类的敏感度\end{abstract}

考虑以下文档test.tex

\RequirePackage{luatex85}
\documentclass{acmart}
\usepackage{tikz}
\usepackage{pgfplots}
\usepgfplotslibrary{external}
\tikzexternalize
\begin{document}
\title{}
\begin{abstract} \end{abstract}
\maketitle
\section{XXXXXXXXX}\subsection{X XXXXXXXXXX XXXXXXX}\subsection{XXXXXXXX XX XXXXXXXXXXXXXXXXX XXXX}\subsection{XXX XXXXXXXX}
\section{XXXXXX XXXXXXXXXX XXX XXXXXXXXX}\subsection{XXX XXXXXXXX XX XXXX XXXXX}
\section{XXX XXXXXXXXX XX X XXXXXXXX}\subsection{XXXXXXXXXXXXXXXX XXXXXXXXXXX XXX XXXXXXXXXX}
\subsection{XXXXXX XXXXXXXXXXXX XXXXXXXX}
\section{XXXXXXX XXXXXXXXXX}\subsection{XXXXXXXX XXXXXXXXXXXX XXXX XX XXXXX}\subsection{XXXXXXX XXXXXXX XX XXXXXXX}
\subsection{XXXXX XXXX XXXX XXXXXXXXXX}\subsection{XXXX XXXXXXXXXX XXXX XXXXXXXX XXXXXXXXXXXXXX}
\subsection{XXXXXXXXXXX XXX XXXXXXXXXXXXX}
\section{XXXXXXXXXX}\subsection{XXXXXXXXXXXXXXX}
\begin{tikzpicture}
    \begin{axis}
        \addplot [color=black,solid,line width=1.0pt,domain=0:1,samples=11]{x+x^2};
        \addlegendentry{Eq. \ref{eq:equation}};
    \end{axis}
\end{tikzpicture}
\subsubsection{XXXXXXXXX XXXXX XXXXXXX}\subsubsection{XXXXXXXXXXX XXXXXXXXXXX XX XXXXXXXXXXXXXXX XXXXXXXXX}
\subsubsection{XXXXXXX XXX XXXXXXXXX XXXXXXXXX}\subsubsection{XXXX XXXXXXXXX}\subsection{XXXXXXXXXXXXXXX XXXX XXXXXXXXXXXX}
\section{XXXXXXX XXXX}
\section{XXXXXX XXXX}
\end{document}

运行rm -f test-* test.a* test.b* test.p* test.s* test.o* test.l*; lualatex -shell-escape test.tex后会给出以下日志

LaTeX Warning: Reference `TotPages' on page 1 undefined on input line 10.

(/usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msa.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msb.cfg)
===== 'mode=convert with system call': Invoking 'lualatex -shell-escape -halt-o
n-error -interaction=batchmode -jobname "test-figure0" "\def\tikzexternalrealjo
b{test}\input{test}"' ========
This is LuaTeX, Version 1.10.0 (TeX Live 2019/Debian)
 system commands enabled.
LaTeX Warning: External picture `test-figure0' contains undefined references on
 input line 24.

===== The previous system call resulted in undefined references inside of the o
utput file. Rescheduling it for \end{document}. ========

Underfull \vbox (badness 10000) has occurred while \output is active

LaTeX Warning: Reference `LastPage' on page 1 undefined on input line 24.

[1.1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] [2.2<./test-figure0.pd
f>] [3.3] (./test.aux

Package atenddvi Warning: Rerun LaTeX, last page not yet found.

)
===== tikzexternal: \end{document} reached. Working on rescheduled images to re
solve references... ========
===== 'mode=convert with system call': Invoking 'lualatex -shell-escape -halt-o
n-error -interaction=batchmode -jobname "test-figure0" "\def\tikzexternalrealjo
b{test}\input{test}"' ========
This is LuaTeX, Version 1.10.0 (TeX Live 2019/Debian)
 system commands enabled.

! Package tikz Error: Sorry, the system call 'lualatex -shell-escape -halt-on-e
rror -interaction=batchmode -jobname "test-figure0" "\def\tikzexternalrealjob{t
est}\input{test}"' did NOT result in a usable output file 'test-figure0' (expec
ted one of .pdf:.jpg:.jpeg:.png:). Please verify that you have enabled system c
alls. For pdflatex, this is 'pdflatex -shell-escape'. Sometimes it is also name
d 'write 18' or something like that. Or maybe the command simply failed? Error
messages can be found in 'test-figure0.log'. If you continue now, I'll try to t
ypeset the picture.

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

l.28 \end{document}

?

导致此错误的直接原因是,此时,的内容test.out

\BOOKMARK [1][-]{section.6}{\376\377\0006\000\040\000X\000X\000X\000X\000X\000X\000X\000\040\000X\000X\000X\000X}{}% 20
\BOOKMARK [1][-]{section.7}{\376\377\0007\000\040\000X\000X\000X\000X\000X\000X\000\040\000X\000X\000X\000X}{

是的,它以 的中间结束\BOOKMARK,正如 中的错误所暗示的那样test-figure0.log

(./test.out)
Runaway argument?
{
! File ended while scanning use of \@@BOOKMARK.
<inserted text>
\par
l.7 \begin{document}

我不知道为什么会发生这种情况(我想了解一下),但更奇怪的是,这些小改动导致代码顺利通过。以下是非详尽的列表:

  • 我认为在文档中用 替换任何实例X XXX删除任何章节标题中的一个空格)都可以消除错误。(我没有足够的耐心去测试这一点,但我尝试了三个不同的实例,所有三个实例都使错误消失。)
  • 我认为删除任何内容X(将任何标题的长度缩短一)都会导致代码顺利通过。(同样,我没有足够的耐心来测试这一点,但我尝试了三个不同的实例,所有三个都使错误消失。)
  • 在某些情况下,替换X XXXX(将章节标题中的单个空格替换为X)会导致错误消失(在其他地方则不会)。
  • \begin{abstract}删除和之间的空格\end{abstract}可以消除错误。

更重要的是:

  • 使用pdflatex而不是lualatex使错误消失(但我不能pdflatex在我的真实例子中使用,因为我的一些图太大)
  • 使用article而不是acmart使错误消失,但我提交的会议需要 acmart。

我已经举报了作为 acmart 上的一个错误,但我完全不确定这是该软件包中的一个错误,因为命中该错误的条件非常脆弱;它似乎也可能是 hyperref 和 tikzexternalize 交互中的一个错误,只有通过 acmart 所做的事情才能揭示出来。

有人能解释一下这里发生了什么吗?

答案1

tikz 图片包含引用,因此 tikz 在钩子中重新安排编译enddocument/afteraux

===== tikzexternal: \end{document} reached. Working on rescheduled images to re
solve references... ========

重新安排的编译还会读取辅助文件。这对于已经关闭的辅助文件来说没有问题,但对于其他辅助文件来说可能是一个问题。在此之前,并非所有文件都已明确关闭:通常软件包只是让编译结束时自动关闭文件。

这里的问题是来自 hyperref 的输出文件:来自主编译的版本仍然打开,并且它处于或多或少随机的状态,这取决于时间和分页符等条件,当重新安排的编译再次读取它时,它可能会中断(或不会)。

可以通过添加(在加载 tikz 之前)强制 hyperref 关闭文件

\makeatletter
\AddToHook{enddocument/afteraux}[hyperref]{\@ifundefined{@outlinefile}{}{\immediate\closeout\@outlinefile}}
\makeatother

muzimuzhi 建议的替代方案https://github.com/pgf-tikz/pgf/issues/1127可以隐藏外部图形的书签(它们根本没有意义),方法是

\tikzset{external/system call={%
  pdflatex \tikzexternalcheckshellescape -halt-on-error-interaction=batchmode -jobname "\image"
  "\string\PassOptionsToPackage{bookmarks=false}{hyperref}\texsource"}}

这两种解决方案都只处理.out文件,仍然可能与其他文件发生类似的冲突。

相关内容