我使用TikZ为我的文档绘制各种矢量图形。它相当慢,每个绘图使主LaTeX文档的编译时间更长。因此,我将所有数据作为独立文件。它们是独立编译的,PDF文件包含在主文档中。这允许根据需要并行运行LaTeX。
该过程如下:
实际的TikZ代码位于Figures/fig.tex
的LaTeX代码段文件中。 Python脚本(tikzpicture_wrap.py
)会将代码段包装到包含前导码的独立文档中。这些文件进入build/page/fig.tex
。
lualatex
在文件build/page/fig.tex
上运行,生成build/page/fig.pdf
。
由于我使用与同一文档相同的文档类(scrartcl
),因此该图形设置在A4纸上,因此需要在将其包含在文档中之前进行裁剪。为此,我使用pdfcrop
作为最后一步。结果将放入build/fig.pdf
我的完整makefile如下所示:
# Copyright © 2015-2016 Martin Ueding <dev@martin-ueding.de>
.PRECIOUS: %.tex %.pdf build/page/%.pdf
document_tex := $(wildcard physics*.tex)
document_pdf := $(document_tex:%.tex=%.pdf)
figures_tex := $(wildcard Figures/*.tex)
figures_pdf := $(figures_tex:Figures/%.tex=build/%.pdf)
all: $(figures_pdf)
#all: $(document_pdf) # Disabled to only typeset figures right now.
test:
@echo "document: $(document_pdf)"
@echo "figures_tex: $(figures_tex)"
@echo "figures_pdf: $(figures_pdf)"
$(document_pdf): $(figures_pdf)
$(figures_pdf): build
build:
mkdir -p build/page
build/page/%.tex: Figures/%.tex
../build-system/tikzpicture_wrap.py $< $@
build/%.pdf: build/page/%.pdf
pdfcrop $< $@
touch $@ # Added in an attempt to work around the problem, does not make any difference, though.
%.pdf: %.tex
cd $$(dirname $@) && lualatex --halt-on-error $$(basename $<)
clean:
$(RM) *-blx.bib
$(RM) *.aux
$(RM) *.log
$(RM) *.run.xml
$(RM) *.out
$(RM) *.svg
$(RM) *.pdf
$(RM) -r build
它确实有效,它会对所有数字进行排版,最终会出现在build/*.pdf
。问题是pdfcrop
步骤一次又一次地运行,即使没有其他事可做。在输出中,您可以看到以下内容:
pdfcrop build/page/propagator.pdf build/propagator.pdf
PDFCROP 1.38, 2012/11/02 - Copyright (c) 2002-2012 by Heiko Oberdiek.
==> 1 page written on `build/propagator.pdf'.
touch build/propagator.pdf
对于我Figures
目录中的每一个数字,都会重复此操作。
我认为这可能是chained rules的一个问题,并将中间文件添加到.PRECIOUS
目标中,以便保留它。现在,pdfcrop
使用的文件不会在中途删除。
接下来我认为文件上的时间戳可能有问题。如果源比目标更新,make将运行它。因此,我添加了touch
以确保目标比源更新。这不是问题,因为我今天早上跑完后可以看到这个问题。从昨天开始,我没有改变该图中的任何内容。
源文件。 stat Figures/propagator.tex
:
File: 'Figures/propagator.tex'
Size: 102 Blocks: 8 IO Block: 4096 regular file
Device: fd03h/64771d Inode: 17432618 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ mu) Gid: ( 1000/ mu)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2016-01-16 10:58:34.384515470 +0100
Modify: 2016-01-16 10:58:34.369515566 +0100
Change: 2016-01-16 10:58:34.373515540 +0100
Birth: -
排版PDF文档。 stat build/page/propagator.pdf
:
File: 'build/page/propagator.pdf'
Size: 6265 Blocks: 16 IO Block: 4096 regular file
Device: fd03h/64771d Inode: 17432636 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ mu) Gid: ( 1000/ mu)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2016-01-16 10:59:04.317323576 +0100
Modify: 2016-01-16 10:59:04.261323935 +0100
Change: 2016-01-16 10:59:04.261323935 +0100
Birth: -
裁剪的最终文件。 stat build/propagator.pdf
:
File: 'build/propagator.pdf'
Size: 6612 Blocks: 16 IO Block: 4096 regular file
Device: fd03h/64771d Inode: 17301550 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ mu) Gid: ( 1000/ mu)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2016-01-17 09:54:32.102511429 +0100
Modify: 2016-01-17 09:54:30.943517396 +0100
Change: 2016-01-17 09:54:30.943517396 +0100
Birth: -
它仍然一次又一次地执行所有pdfcrop
操作。我不懂为什么。与此同时,我添加了以下kludge,以便在没有任何操作时使编译过程更快完成:
build/%.pdf: build/page/%.pdf
if [ $< -nt $@ ]; then \
pdfcrop $< $@; \
fi
这里的实际问题是什么?如何解决?
答案 0 :(得分:2)
@Tsyvarev走在正确的轨道上。这确实是问题所在:
$(figures_pdf): build
但是,这不是因为 build
与特定文件无关。 build
确实存在:它是使用规则创建的目录:
build:
mkdir -p build/page
这构建了子目录build/page
,这意味着build
存在(作为目录),因此在后续构建中,当检查它是否存在时,它将确定是,它确实存在。当列为目标时,不要将目录与任何其他文件区别开来。
但是,先决条件的存在并不是唯一可以使用的测试:它还会检查先决条件是否比目标更新。这是目录和文件行为不同的地方,以及为什么你几乎从不(除了在某些特殊情况下)想要使用目录作为目标的正常先决条件。
目录有一个&#34;时间最后修改&#34;就像文件一样,目录的TLM值就像文件一样更新:当目录被修改时。什么构成&#34;修改&#34;一个目录?好吧,添加新文件,删除现有文件或重命名文件都会修改目录并导致其更改TLM。
您现在可以看到问题:每次makefile添加,删除或重命名build
目录中的文件时,其修改时间都会更新。这意味着目录build
总是比其中的几乎所有文件都新,这意味着它们每次都会重建。
有两种方法可以解决这个问题。一种是始终将目录创建为副作用;从先决条件列表中删除build
并删除上面的规则,而只是在解析makefile时强制通过make强制创建目录:
__dummy := $(shell mkdir -p build/page)
第二种方式,如果你有一个足够新的GNU make版本,就是使用order-only prerequisites:
$(figures_pdf): | build