使通配符找不到我刚才复制的文件

时间:2017-08-09 16:06:28

标签: makefile

我想将几个目录中的pdf文件复制到构建目录中,然后使用pdfunite将它们编译成一个pdf。下面的配方工作,但我必须运行两次,因为第一次通过,我从pdfunite得到一个错误 - 在构建目录中找不到文件(PDFS变量是空的),即使它们只是在以前复制过线。我如何解决这个问题,以便一次通过?为了清晰起见,我简化了配方;我实际上是从各种文件夹中提取并在运行中制作一些pdf,因此我无法轻松地连接各种子文件夹(示例中的folder1和folder2)的完整文件列表以传递给pdfunite。

notebook: 
    mkdir -p $(out)
    mkdir -p $(build)/notebook
    $(eval PR := $(sort $(wildcard $(data)/folder1/*.pdf)) )
    cp  $(PR) $(build)/notebook
    $(eval SR := $(sort $(wildcard $(data)/folder2/*.pdf)) )
    cp  $(SR) $(build)/notebook
    $(eval PDFS := $(sort $(wildcard $(build)/notebook/*.pdf)) )
    pdfunite $(PDFS) $(out)/notebook.pdf

2 个答案:

答案 0 :(得分:0)

我会采取另一种方式。

PR:=$(sort $(wildcard $(data)/folder1/*.pdf))
SR:=$(sort $(wildcard $(data)/folder2/*.pdf))
PDFS=$(sort $(wildcard $(build)/notebook/*.pdf))

all: copy
    pdfunite $(PDFS) $(out)/notebook.pdf

copy:
    mkdir -p $(out)
    mkdir -p $(build)/notebook
    cp $(PR) $(build)/notebook
    cp $(SR) $(build)/notebook

.PHONY: all copy

请检查:PDFS= PDFS:=。如果你使用简单的=,变量的值将在需要时计算(不会更快!)。

当您运行make时,它想要构建allall的要求是copy - 所以make执行了一些mkdircp。返回all后:需要PDFS的值,以便评估现在 - 我们在$(build)/notebook中有多个pdf:)

答案 1 :(得分:0)

您的Makefile不符合make的理念。您正在使用make作为另一种脚本语言,而make不仅仅是这种语言。它根据必须构建或重新构建的决定来比较目标和先决条件日期,并将配方传递给shell。所以,对于你的特殊问题,你应该尝试类似的东西:

PR    := $(wildcard $(data)/folder1/*.pdf)
SR    := $(wildcard $(data)/folder2/*.pdf)
PDFS1 := $(patsubst $(data)/folder1/%.pdf,$(build)/notebook/%.pdf,$(PR))
PDFS2 := $(patsubst $(data)/folder2/%.pdf,$(build)/notebook/%.pdf,$(SR))
PDFS  := $(sort $(PDFS1) $(PDFS2))

.PHONY: notebook

notebook: $(out)/notebook.pdf

$(PDFS1): $(build)/notebook/%.pdf: $(data)/folder1/%.pdf | $(build)/notebook
    cp $< $@

$(PDFS2): $(build)/notebook/%.pdf: $(data)/folder2/%.pdf | $(build)/notebook
    cp $< $@

$(build)/notebook $(out):
    mkdir -p $@

$(out)/notebook.pdf: $(PDFS) | $(out)
    pdfunite $(PDFS) $@

变量定义相当简单:正如其名称所示,patsubst替换字符串。 target: pattern: prerequisitesstatic pattern rule|之后的先决条件是order-only prerequisites

这个makefile基本上说,$(out)/notebook.pdf取决于$(build)/notebook/中的一组pdf文件,并且这些pdf文件依赖于$(data)/folder1/中具有相同基本名称的源pdf文件和$(data)/folder2/。它还说必须在填充之前创建目录。多亏了这一切,只需要做的就是做,不多也不少。而且它更符合make的理念。

如果您有许多源文件夹但又不想复制复制规则,则可以使用更高级的功能,例如:

FOLDERS := folder1 folder2

.PHONY: notebook

notebook: $(out)/notebook.pdf

define MY_rule
$(1)_SRCS := $$(wildcard $$(data)/$(1)/*.pdf)
$(1)_DSTS := $$(patsubst $$(data)/$(1)/%.pdf,$$(build)/notebook/%.pdf,$$($(1)_SRCS))
PDFS      += $$($(1)_DSTS)

$(1)_DSTS: $$(build)/notebook/%.pdf: $$(data)/$(1)/%.pdf | $$(build)/notebook
    cp $$< $$@
endef

$(foreach f,$(FOLDERS),$(eval $(call MY_rule,$(f))))

$(build)/notebook $(out):
    mkdir -p $@

$(out)/notebook.pdf: $(PDFS) | $(out)
    pdfunite $(PDFS) $@