GNUMake隐式规则带来麻烦

时间:2019-02-04 20:41:58

标签: makefile gnu-make

我缺少有关隐式规则的信息。这是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

1 个答案:

答案 0 :(得分:1)

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

这不是与您的样本结构匹配的模式规则。来自docs

  模式规则的先决条件中的

%代表与目标中的%匹配的词干。为了应用模式规则,其目标模式必须与所考虑的文件名匹配,并且其所有先决条件(在模式替换之后)必须命名存在或可以创建的文件。这些文件成为目标的先决条件。

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

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

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

如果您想坚持使用patsubst,这应该也可以:

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

不是%用于与目标中的目录名称匹配的目录名,并且使用\进行了转义,以使其毫不费力地通过patsubst

这两种方法在GNU make yield中似乎都进展顺利:

$ 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
相关问题