我对gnu make的行为有疑问。具体来说,如果依赖关系目标生成一个尚不存在的文件,则在“主”目标完成时将删除该文件。
我确信有很好的理由说明为什么会这样,但我该如何解决呢?
我已经详细说明了下面的情况,并添加了一个示例Makefile,显示了我想要做的事情的概念。
感谢您的意见。
情况:
下面的示例文件(实际Makefile的“虚拟示例”)的目的是从Markdown文件生成“html”和“pdf”。
默认目标是pdf
,它将递归调用目标%.pdf
,而目标%.html
依次为%.md
,因此%.pdf
。到目前为止一切顺利,如果目录中只包含markdown文件,我将在生成“pdf”之前生成“html”文件。
如果您运行该示例,您会注意到在usr@cmptr $ make
Generated: sof_example.md
Generated: sof_example.html
Generated: sof_example.pdf
rm sof_example.html sof_example.md
usr@cmptr $
目标完成后删除了“html”文件。终端输出为:
make
但是,如果文件在执行usr@cmptr $ make clean
usr@cmptr $ touch sof_example.html sof_example.md
usr@cmptr $ make
Generated: sof_example.pdf
usr@cmptr $
之前存在,则输出为:
html
有没有办法可以优雅地解决这个问题,即不添加更多递归调用,或者特定于%.pdf
作为依赖项的示例,因为make
每次都会执行# --------------------------------------------------------------------------- #
# summary: Make file generating 'html' and 'pdf' from a markdown ('md') file
# usage: make
# note: Recursive
# --------------------------------------------------------------------------- #
TARGETS := sof_example
SHELL=/bin/bash
.PHONY: all clean
all: pdf
# Dummy target, the markdown file will normally located in TARGETS
%.md:
@touch $(@)
@printf "Generated: %s\n" $(@)
# HTML target: Generates HTML file from markdown
%.html: %.md
@touch $(@)
@printf "Generated: %s\n" $(@)
# PDF target: Generates pdf version of the HTML, e.g. using `wkhtmltopdf`
%.pdf: %.html
@touch $(@)
@printf "Generated: %s\n" $(@)
pdf html:
@$(MAKE) --no-print-directory $(addsuffix .$(@), $(TARGETS))
# Will remove ALL files with name TARGETS, regardless of suffix
clean:
@$(RM) $(TARGETS).*
# EoF
Option::margin()
1}}被执行。
示例文件:
Margin
答案 0 :(得分:1)
您所看到的是因为您隐含的模式规则的链接:
%.md -> %.html -> %.pdf
引导make
推断出%.md
和%.html
仅仅是中间的
对于任何给定的%.pdf
,制作%
的副产品。在那种情况下它
默认假设是您不想保留中间体。
如果你做想要保留中间人,你可以告诉make
通过声明
makefile中任意位置的特殊目标.SECONDARY:
。
.SECONDARY:
没有先决条件的将保留所有中间体。有先决条件, e.g。
.SECONDARY: $(addsuffix .html,$(TARGETS))
只保留那些先决条件的中间体。