类似于 CMake 的 LaTeX 构建系统

类似于 CMake 的 LaTeX 构建系统

假设我有一个 LaTeX repo,其中包含主文件和许多图像文件,也是 LaTeX 格式(里面有 tikz)。我想实现多个目标:

  1. 单独编译。所有图像都可以单独编译为各自的 pdf,然后包含在主文档中。
  2. 没有无意义的重新编译 - 如果图像源没有改变,就不会重新编译。
  3. 无黑客攻击。(包括 shell 转义)
  4. 一个命令。它必须编译所有被改变的图像,然后编译主文件。
  5. 可移植性。该解决方案应适用于 Windows 和 Linux。

在我看来,我需要一个构建系统,一些简单版本的 cmake。问题是,有吗?

更新#1:

尝试了 latexmk,正如评论所建议的那样。因此,有两种可能的方法可以解决我的问题:

  1. 使用自定义依赖项功能。在我的例子中它看起来像这样:
add_cus_dep('tex', 'pdf', 1, 'texinclude2pdf');
sub texinclude2pdf {
  system("pdflatex -synctex=1 -aux-directory \"$aux_dir\" -output-directory \"$out_dir/images\" \"$_[0].tex\"");
}

这个解决方案有几个问题:

  • 它对主文档中包含的所有内容 *.pdf 都有反应。
  • 不允许指定 tex 图像文件的搜索目录
  • 它是配置文件中的脚本 - 那么为什么还要使用 latexmk 呢?
  • 该脚本使用“system”命令——它并不比shell escape好。
  1. 使用@default_files:
@default_files = ();
push @default_files, 'images/picture1.tex';
push @default_files, 'main.tex';

这样做效果更好,但它不允许为图像文本输入指定自定义输出目录(即 build/images)。

答案1

我确实喜欢使用 Docker+Make(或任何构建自动化工具)来实现这一点。

  1. 单独编译。我们在一个单独的 Docker 容器中单独编译图表,在另一个容器中编译文档本身。如果需要,将编译文档latexmk(或无论您想要什么)。
  2. 无需进行无意义的重新编译。我们使用 GNU Make 来实现这一点。如果代码发生变化,图形将被重建。
  3. 禁止黑客攻击。好吧,你把我吸引到这里了。
  4. 一个命令make figures render
  5. 可移植性. Docker 当然是可移植的,而且GNU Make 应该但 ymmv。

如何惹恼你的合著者:LaTeX 的 Gitlab CI 管道如何实现这一点 - 包括使用Gitlab 持续集成。这里使用Gitlab CI的好处是增加可移植性。

构建系统

一个最小的例子

目录结构是

.
├── Makefile
├── images
│   ├── Makefile
│   └── image1.tex
└── main.tex

其中第一个Makefile包含

all: main.pdf

.PHONY: images
main.pdf: images

images:
    docker run -it --rm -w /data/ -v`pwd`:/data  martisak/texlive:2022 -- sh -c "make -C images"

%.pdf: %.tex
    docker run --rm -w /data/ -v`pwd`:/data martisak/texlive:2022 -- sh -c "latexmk -pdf $<"

clean:
    -make -C images clean
    latexmk -CA
    -rm -rf build

images/Makefile包含

IMAGES_DIR = ../images
BUILD_DIR = ../build/images

IMAGES_TEX_FILES = $(wildcard $(IMAGES_DIR)/*.tex)
IMAGES_PDF_FILES = $(patsubst $(IMAGES_DIR)/%.tex, $(BUILD_DIR)/%.pdf, $(IMAGES_TEX_FILES))

.PHONY: all clean

all: $(IMAGES_PDF_FILES)

$(BUILD_DIR)/%.pdf: $(IMAGES_DIR)/%.tex
    @mkdir -p $(BUILD_DIR)
    latexmk -pdf -output-directory=$(BUILD_DIR) $<

clean:
    latexmk -CA

为了完整性images/image1.tex

\documentclass[tikz, border=2pt]{standalone}

\begin{document}

\begin{tikzpicture}
  \draw (0,0) circle (1);
  \fill (0,0) circle (2pt);
\end{tikzpicture}

\end{document}

main.tex

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\title{An example}
\begin{document}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=0.5\textwidth]{build/images/image1.pdf}
    \caption{caption}
    \label{fig:label}
\end{figure}

\end{document}

如果愿意,可以省略Docker容器并latexmk直接运行。

使用 开始编译make

相关内容