使用带有指定 --output-directory 的 memoize 包

使用带有指定 --output-directory 的 memoize 包

我正在尝试配置 memoize 包,但在尝试将 --output-directory 选项传递给 LuaLatex 时遇到问题。从查看输出文件及其最终结果来看,似乎 memoize 错误地写入了输出目录,但没有从中读取。使用下面的 MWE:

\documentclass{article}
\usepackage[memo dir]{memoize}
\usepackage[linguistics]{forest}
\usepackage{fontspec}
\setmainfont{Charis SIL}

\begin{document}
A test document. 

\begin{forest}
[S
    [NP]
    [VP]
]
\end{forest}


\end{document}

该包使用简单命令正常运行,但却因一般错误lualatex untitled.tex而失败。lualatex --output-directory=output untitled.tex

我也尝试过添加,\mmzset{prefix=output/}但没有成功。

答案1

好消息:Memoize 确实支持了--output-directory,或者更准确地说,一旦 TeXLive 2024 发布,它就会支持它。让我解释一下。

Memoize 的提取脚本尊重环境变量的值TEXMF_OUTPUT_DIRECTORY将要由 TeXLive 2024 引入(所以,很快!)。(事实上,新变量被认为是解决 Memoize 问题的解决方案--output-directory,我非常感谢 Karl Berry 找出解决方案并实施它!)在 TeXLive 2024 中,(a)设置TEXMF_OUTPUT_DIRECTORY将是指定 的替代方法--output-directory,并且(b)无论输出目录如何设置,其值都将由嵌入式作业(如 Memoize 提取脚本)接收的环境变量反映TEXMF_OUTPUT_DIRECTORY。底线:11 天内,一切将立即可用。

同时,解决方法是TEXMF_OUTPUT_DIRECTORY手动设置:

TEXMF_OUTPUT_DIRECTORY=output lualatex --output-directory=output untitled.tex

现在坏消息:虽然这已经过测试,并且适用于pdftex引擎,但似乎不适用于luatex。或者更确切地说,只要正确生成和提取了外部变量,一切就都正常,但利用外部变量会失败,因为lualatex不会在输出目录中搜索它们(与不同pdflatex)。我会尽快调查。

一种解决方法是将备忘录目录从输出目录软链接到当前目录,但我意识到 OP 的设置可能不允许这样做。从包含untitled.tex运行的目录中:

ln -s output/untitled.memo.dir

答案2

我想补充一下 Sašo Živanović 的回答,可以配置 latexmk 以使用带有输出目录的 memoize。

以下是 latexmkrc 文件中的内容。 (请注意,此配置的改进版本将在下一个版本的 latexmk(v. 4.84)中出现。此处的解决方案仅适用于 Unix 类型操作系统(linux 和 macOS)上的 TeXLive,并且仅当 latexmk 使用 lualatex for pdflatex 来编译 .tex 文件时才有效。)

$pdf_mode = 4;  # Use lualatex.  Set to 1 for pdflatex, 5 for xelatex.

# You can have separate build and output directories, or they can be
# the same, e.g., by $out_dir = $aux_dir = 'output';
$out_dir = 'output';
$aux_dir = 'build';
$emulate_aux = 1;

# Get latexmk -C to delete memoize-generated files, at least
# when the default setting in memoize for the prefix of .memo
# and .pdf files is used.
push @generated_exts, 'mmz', 'mmz.log', '%R.*.memo', '%R.*.pdf';
&set_tex_cmds( 'internal latex_memoize %C %B %S -synctex=1 %O' );

sub latex_memoize {
  print "============= I am latex_memoize \n";
  # Ensure TEX_OUTPUT_DIRECTORY is set. (In v. >=4.84 of latexmk, this
  # will not be necessary, since latexmk will make the setting itself.)
  local %ENV = %ENV;
  foreach ( 'TEXMF_OUTPUT_DIRECTORY' ) {
    $ENV{$_} = $aux_dir;
    print "latex_memoize: ENV{$_} = '$ENV{$_}'\n";
  }

  my ($cmd, $base, $source, @args) = @_;
  my $tex_log = "$aux_dir1$base.log";
  my $mmz_file = "$aux_dir1$base.mmz";
  my @tex_cmd = ($cmd, @args, $source );
  my @memo_cmd = ("memoize-extract.pl", '-F', 'latex', $mmz_file );

  print "latex_memoize: Running\n  '@tex_cmd'\n";
  my $ret = system @tex_cmd;

  if (! -e $mmz_file) {
    print "latex_memoize: No mmz file '$mmz_file', so memoize is not being used.\n";
    return $ret;
  }

  # Use (not-currently-documented) latexmk subroutine to determine
  #   whether mmz file was generated in current run: 
  if ( ! test_gen_file_time( $mmz_file) ) {
    warn "latex_memoize: Mmz file '$mmz_file' exists, but wasn't generated\n",
         "  in this run so memoize is not **currently** being used.\n";
    return $ret;
  }

  # Fix up dependency information in log file:
  my $mmz_fh = undef;
  my $tex_log_fh = undef;
  if (! open( $mmz_fh, '<', $mmz_file ) ) {
    print "latex_memoize: Cannot open mmz file '$mmz_file':\n $!\n";
    return $ret;
  }
  if (! open( $tex_log_fh, '>>', $tex_log ) ) {
    warn "latex_memoize: Cannot open log file '$tex_log': $!\n";
    close $mmz_fh;
    return $ret;
  }
  while ( <$mmz_fh> ) {
    s/\s*$//;
    my $source = undef;
    if ( /^\\mmzNewExtern\s+{([^}]+)}/ ) {
      # We have a new memo item without a corresponding pdf file
      # Put a suitable message in the log file, so that latexmk will
      # know to run *latex again, when it analyzes the results of 
      # the current run.
      $file = "$aux_dir1$1";
      print "latex_memoize: new extern for memoize: '$file'\n";
      print $tex_log_fh "No file $file\n";
    }
  }
  close $tex_log_fh;
  close $mmz_fh;

  # Run memoize-extract.pl now.  Then missing pdf files are
  # created, which will provoke latexmk into rerunning *latex.
  # It also handles the case that the memoize package is used
  # with the external=no option.  (But gives no problem when
  # the option is not used.)
  # It also allows the use of separate aux and output directories
  # which would otherwise give a problem, since in that situation
  # latexmk will move the pdf file from the aux directory to the
  # output directory, where it is no longer accessible to 
  # memoize-extract.pl.
  print "Running\n @memo_cmd\n";
  my $ret2 = system @memo_cmd;
  if ($ret2) { return $ret2; }

  return $ret;
}

这已在 TeXLive 2023 和 2024 以及所有 pdflatex、lualatex 和 xelatex 上进行了测试。(在 Windows 上,当文件名称中包含非 ASCII 字符时可能会出现一些问题,但我尚未检查。)

正如问题评论中提到的,使用输出目录有一些复杂性。使事情正常工作的方法已经编入 latexmk 中;这是许多年前完成的,非常简单,但不是您想从命令行定期执行的操作。我发现使用 latexmk 可以让我避免提到的困难。

相关内容