With explicit targets I can combine several rules like
foo.o bar.o: $(SOURCES)
cc $< -o $@
This is equivalent of
foo.o: $(SOURCES)
cc $< -o $@
bar.o: $(SOURCES)
cc $< -o $@
But I want to use pattern rules.
I have several troff documents (man, README) and I want to generate .html and .ascii files.
Naive approach is
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)
But it doesn't work, because make believes that all files are created with one command (much like & in modern make: https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html)
Obviously I can do
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)
But it is a kind of copy-paste.
Could it be solved with GNU make?
This is exactly how this works; it's a long-standing feature. From the documentation:
As example states, it was meant to deal with programs that generate more than one output in one invocation, like
bison. You can either update your recipe to generate both files in one shot, or keep the rules separated as you do now.