假设我有一个 LaTeX repo,其中包含主文件和许多图像文件,也是 LaTeX 格式(里面有 tikz)。我想实现多个目标:
- 单独编译。所有图像都可以单独编译为各自的 pdf,然后包含在主文档中。
- 没有无意义的重新编译 - 如果图像源没有改变,就不会重新编译。
- 无黑客攻击。(包括 shell 转义)
- 一个命令。它必须编译所有被改变的图像,然后编译主文件。
- 可移植性。该解决方案应适用于 Windows 和 Linux。
在我看来,我需要一个构建系统,一些简单版本的 cmake。问题是,有吗?
更新#1:
尝试了 latexmk,正如评论所建议的那样。因此,有两种可能的方法可以解决我的问题:
- 使用自定义依赖项功能。在我的例子中它看起来像这样:
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好。
- 使用@default_files:
@default_files = ();
push @default_files, 'images/picture1.tex';
push @default_files, 'main.tex';
这样做效果更好,但它不允许为图像文本输入指定自定义输出目录(即 build/images)。
答案1
我确实喜欢使用 Docker+Make(或任何构建自动化工具)来实现这一点。
- 单独编译。我们在一个单独的 Docker 容器中单独编译图表,在另一个容器中编译文档本身。如果需要,将编译文档
latexmk
(或无论您想要什么)。 - 无需进行无意义的重新编译。我们使用 GNU Make 来实现这一点。如果代码发生变化,图形将被重建。
- 禁止黑客攻击。好吧,你把我吸引到这里了。
- 一个命令。
make figures render
。 - 可移植性. 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
。