GNU Make 与隐式规则有关

GNUMake trouble with implicit rules

我遗漏了一些关于隐式规则的信息。这是 Makefile (GNU Make 4.2.1)

heimdall /tmp 1670> cat Makefile

PARTS= a b c

.SECONDEXPANSION:

data/events2: $$(patsubst %,$$(@D)/%.ppd,$(PARTS))
        /bin/ls -l $^

%/events2: $$(patsubst %,$$(@D)/%.ppd,$(PARTS))
        /bin/ls -l $^

以下是用来说明情况的捏造数据:

heimdall /tmp 1671> ls -1 data data1
data:
a.ppd
b.ppd
c.ppd

data1:
a.ppd
b.ppd
c.ppd

这里是 make 使用显式规则,它的工作方式与我预期的一样。

heimdall /tmp 1672> make data/events2
/bin/ls -l data/a.ppd data/b.ppd data/c.ppd
-rw-rw-r-- 1 bennett None 0 Feb  4 12:19 data/a.ppd
-rw-rw-r-- 1 bennett None 0 Feb  4 12:19 data/b.ppd
-rw-rw-r-- 1 bennett None 0 Feb  4 12:19 data/c.ppd

最后,这个:

heimdall /tmp 1673> make data1/events2
make: *** No rule to make target 'data1/events2'.  Stop.

为什么隐式规则不匹配?我觉得我错过了一些基本的东西。

谢谢。

-E

%/events2: $$(patsubst %,$$(@D)/%.ppd,$(PARTS))

不是与您的示例结构匹配的模式规则。来自 docs:

% in a prerequisite of a pattern rule stands for the same stem that was matched by the % in the target. In order for the pattern rule to apply, its target pattern must match the file name under consideration and all of its prerequisites (after pattern substitution) must name files that exist or can be made. These files become prerequisites of the target.

但是在您的目标中 % 将匹配 data1。但实际上没有任何 % 可以在先决条件方面匹配,因为存在的 patsubst 函数和目录(词干)被称为 $(@D)

我尝试使用 foreach 函数编写这样的规则:

%/events2: $(foreach part,$(PARTS), %/$(part).ppd)
        /bin/ls -l $^

如果您想坚持使用 patsubst,这也应该有效:

%/events2: $(patsubst %,\%/%.ppd,$(PARTS))
        /bin/ls -l $^

并不是说 % 用于与目标中的目录名称匹配的目录名称,它使用 \ 进行了转义以使其毫发无损地通过 patsubst

GNU make yielding 似乎两种方式都进展顺利:

$ make data1/events2
/bin/ls -l data1/a.ppd data1/b.ppd data1/c.ppd
-rw-r--r-- 1 ondrej users 0 Feb  4 22:00 data1/a.ppd
-rw-r--r-- 1 ondrej users 0 Feb  4 22:00 data1/b.ppd
-rw-r--r-- 1 ondrej users 0 Feb  4 22:00 data1/c.ppd