如何通过一条规则解决依赖列表中的多个目标?

How to address multiple targets from dependency list by one rule?

我有以下 Makefile 的例子:

all: foo1.gz foo2.gz bar1.gz bar2.gz
  @echo Done.

foo1.gz:
  touch foo1 && gzip foo1

foo2.gz:
  touch foo2 && gzip foo2

bar1.gz:
  touch bar1 && gzip bar1

bar2.gz:
  touch bar2 && gzip bar2

旨在创建和 gzip 某些文件。这不是少量文件的问题,但是当你有数百个文件时,你不想将每个文件指定为给定目标的依赖项。

所以我想通过只指定一个依赖项来简化上述语法,而不是为每个文件指定。

因此我希望语法如下:

all: %.gz

应该匹配多个目标,但是它不起作用并且失败:

make: *** No rule to make target %.gz, needed by `all'. Stop.

知道如何实现吗?

您想制作一些文件并压缩它们。不管怎样,你有 告诉 make 它们是什么,或者如何算出它们。

模式规则无法做到这一点。一个规则是一个模式规则当且仅当存在 在它的 target 一侧正好是一个 %。参见 10.5 Defining and Redefining Pattern Rules。所以

%.o: %.c
    $(CC) -c -o $@ $<

是模式规则,

也是
%.xyz: foobar
    cp -f $< $@

他们告诉你,如果某个目标匹配左侧 %-wise,part 匹配 %,那么该目标 具有将整个右侧的 % 替换为 part 的先决条件, 该目标的配方是模式规则中的配方。

他们不会告诉你任何东西都是目标,无论如何:

all: %.gz
根据定义,

不是模式规则。左边没有%,就是一个普通的 旧规则说目标 all 具有先决条件 %.gz.

一般来说,您有两种方法可以让 make 知道您想要的文件名列表 处理:

拼写出来,例如:

files = foo1 foo2 bar1 bar2 ...

或者告诉make一些计算它们的方法,例如

files = $(wildcard ...) # `make` globbing
files = $(shell ....) # shell filter

8.2 Functions for String Substitution and Analysis8.3 Functions for File Names 用于计算文件名列表(或更一般的字符串列表)的 makes 内置资源的文档。

一旦您为 make 选择了一种方式来识别您想要创建和压缩的文件, 然后你可以使用模式规则来节省代码,例如:

生成文件

zips := foo1.gz foo2.gz bar1.gz bar2.gz

.PHONY: all clean

all: $(zips)
    @echo Done.

%.gz:
    touch $(basename $@) && gzip $(basename $@)

clean:
    rm -f $(zips)