GNU make:一个模式规则中的多个目标

GNU make: several targets in one pattern rule

有了明确的目标,我可以组合几个规则,比如

foo.o bar.o: $(SOURCES)
    cc $< -o $@

这相当于

foo.o: $(SOURCES)
    cc $< -o $@
bar.o: $(SOURCES)
    cc $< -o $@

但是我想使用模式规则。

我有几个 troff 文档(manREADME),我想生成 .html.ascii 文件。

天真的做法是

GROFF := groff
DOCS := man README

DOC_FILES = $(foreach doc,$(DOCS),$(doc).html $(doc).ascii)
CALL_GROFF = $(GROFF) -T$(subst $*.,,$@) -mman $< > $@

%.html %.ascii: %.doc
        $(CALL_GROFF)

.DEFAULT: all
all: $(DOC_FILES)

.PHONY: clean
clean:
        rm $(DOC_FILES)

但它不起作用,因为make认为所有文件都是用一个命令创建的(很像现代make中的&https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html)

显然我可以做到

GROFF := groff
DOCS := man README

DOC_FILES = $(foreach doc,$(DOCS),$(doc).html $(doc).ascii)
CALL_GROFF = $(GROFF) -T$(subst $*.,,$@) -mman $< > $@

%.ascii: %.doc
        $(CALL_GROFF)

%.html: %.doc
        $(CALL_GROFF)

.DEFAULT: all
all: $(DOC_FILES)

.PHONY: clean
clean:
        rm $(DOC_FILES)

但它是一种复制粘贴。

可以用GNU make解决吗?

这正是它的工作原理;这是一个长期存在的功能。来自 documentation:

Pattern rules may have more than one target; however, every target must contain a % character. Pattern rules are always treated as grouped targets (see Multiple Targets in a Rule) regardless of whether they use the : or &: separator.

如示例所述,它旨在处理在一次调用中生成多个输出的程序,例如 bison。您可以更新配方以一次性生成两个文件,也可以像现在一样将规则分开。