不扩展模式匹配变量

时间:2017-04-19 17:00:34

标签: pdf makefile pattern-matching gnu-make

我尝试使用Sphinx在 Makefile 中构建一些PDF。生成的PDF已经破坏了引用,因此我想使用pdftk来修复它们。

目标

所以我想为我构建的所有PDF做的是:

# Creates the PDF files.
$(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) source/pdf/ $(BUILDDIR)/pdf_broken

# Go through all PDFs and fix them.
pdftk $(BUILDDIR)/pdf_broken/thepdf.pdf output $(BUILDDIR)/pdf/thepdf.pdf

尝试使用

所以要通过制作来做到这一点我写了 Makefile

# Build PDF (results in broken references)
$(BUILDDIR)/pdf_broken/%.pdf:
    $(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) source/pdf/ $(BUILDDIR)/pdf_broken

# This fixes the broken pdfs and produces the final result.
$(BUILDDIR)/pdf/%.pdf: $(BUILDDIR)/pdf_broken/%.pdf
    mkdir -p $(BUILDDIR)/pdf/
    pdftk $^ output $@

pdf: $(BUILDDIR)/pdf/%.pdf

预期结果

我正在使用模式匹配,因为我从阅读手册中了解到: http://www.tack.ch/gnu/make-3.82/make_91.html

根据我的理解,$<应该是从上面的例子扩展的先决条件:

$(BUILDDIR)/pdf_broken/thepdf.pdf

然后$@应该是目标:

$(BUILDDIR)/pdf/thepdf.pdf

所以我的食谱pdftk $^ output $@应该运行命令:

pdftk $(BUILDDIR)/pdf_broken/thepdf.pdf output $(BUILDDIR)/pdf/thepdf.pdf

实际结果

但这不是正在发生的事情。相反,这是运行:

pdftk build/pdf_broken/%.pdf output build/pdf/%.pdf

这显然给了我一个错误:

Error: Unable to find file.
Error: Failed to open PDF file:
   build/pdf_broken/%.pdf

问题

所以我的问题是,我对模式匹配的工作原理有什么看法,以及使用制作来解决这个问题的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

您应该查找模式规则。在任何情况下,看起来您只有一个命令来生成损坏目录中的所有文件。这应该有自己的规则,并且应该输出一个虚拟文件来指示它是完整的。修复pdf文件的规则应该依赖于正在创建的虚拟目标。

应该是这样的:

// get a list of expected output files:
PDF_SOURCES:=$(wildcard source/pdf/*)
PDF_OUTS:=$(patsubst $(PDF_SOURCES),source/pdf/%.pdf,$(BUILDDIR)/pdf/%.pdf);

// just for debugging:
$(info PDF_SOURCES = $(PDF_SOURCES))
$(info PDF_OUTS = $(PDF_OUTS))


// default rule
all: $(PDF_OUTS)
    @echo done

// rule to build BUILDIR:
$(BUILDDIR)/pdf:
     mkdir -p $@

// rule to build all broken files in one go:
// (note: generates a file .dosphynx, which is used to keep track
// of when the rule was run last.   This rule will be run if the 
// timestamp of any of the sources are newer. 
.do_sphynx: $(PDF_SOURCES) | $(BUILDDIR)/pdf
     $(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) source/pdf/ $(BUILDDIR)/pdf_broken
     touch $@

// create a dependency of all output files on do_sphynx
$(PDF_OUTS): .do_sphynx

// patern rule to fix pdf files
$(BUILDDIR)/pdf/%.pdf : $(BUILDDIR)/pdf_broken/%.pdf
    pdftk $< output $@

我没有对此进行测试,因此可能会出现语法错误..

----------------------编辑-------------

好的,既然在makefile读取时无法确定$(PDF_OUTS),也许你应该这样做:

// get a list of expected output files:
PDF_SOURCES:=$(wildcard source/pdf/*)

all: .do_fix
    @echo done

$(BUILDDIR)/pdf:
     mkdir -p $@

.do_sphynx: $(PDF_SOURCES) | $(BUILDDIR)/pdf
    $(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) source/pdf/ $(BUILDDIR)/pdf_broken
    touch $@

.do_fix: .do_sphynx
    @for src in $$(ls source/pdf/*.pdf); do \
         trg=$${src/#"source/pdf"/"$(BUILD_DIR)/pdf"}; \
         [[ $$src -nt $$trg ]] && \
            echo "$$src ==> $$trg" && pdftk $$src output $$trg; \
    done
    touch $@

一个注意事项 - 如果-nt不存在,if中的$trg比较器将返回true,因此它将涵盖文件丢失或目标早于源的情况。再次没有测试,但它应该工作。