2015-04-03 889 views
0

我觉得有一种基本的我缺少关于GNU make(我使用3.81,如果它很重要)静态模式规则匹配(显然有人做了我在哪里工作,因为这被发现是因为我试图修复已被评论过的规则)。我试图简化我的例子,直到它的症结所在(希望我没有错过任何真正的例子中的重要东西)。Makefile静态模式规则匹配问题

所以这似乎工作,我会期望

JUNK:=foo bar 
BINS:=$(patsubst %,bin/%,$(JUNK)) 

all : $(BINS) 
.PHONY : all 

# This works 
$(BINS) : bin/% : % 
     mkdir -p bin && cp $< [email protected] 

但这(这是接近我的真正的Makefile中)不会根据我的理解

JUNK:=foo bar 
BINS:=$(patsubst %,bin/%,$(JUNK)) 

all : $(BINS) 
.PHONY : all 

# This doesn't work 
$(JUNK) : bin/% : % 
     mkdir -p bin && cp $< [email protected] 

# This doesn't work either 
#bin/$(JUNK) : bin/% : % 
#  mkdir -p bin && cp $< [email protected] 

在这两种情况下我应该会发生什么事情,我预料到两种Makefiles都会表现得完全一样;但是,只有第一个行为如我所料(即正确将文件复制到垃圾桶)和第二给出了下面的输出

Makefile:12: target `foo' doesn't match the target pattern 
Makefile:12: target `bar' doesn't match the target pattern 
make: *** No rule to make target `bin/foo', needed by `all'. Stop. 

什么是更令人困惑的是,有几乎相同的其他静态模式规则在make我正在检查那个工作。

所以我显然知道如何解决这个问题,但是我想知道为什么第二个代码块(以及第二个代码块中的注释掉的部分)没有按照我期望的那样做至。

在此先感谢您的帮助/见解。

回答

2

第一个不起作用,因为,扩大JUNK变量后,让看到这个:

foo bar : bin/% : % 

静态模式规则的工作方式是,第一图案(目标图案)必须比赛目标列表中的每个单词。这表明目标名称的哪一部分是词干(与%匹配的部分)。如果目标模式不匹配,make就不知道该词干是什么。模式bin/%与文本foo(文本foo中没有bin/)不匹配,因此您会看到您看到的错误。

第二个不起作用,因为在这个例子中的exanding JUNK变量的结果(bin/$(JUNK) : bin/% : %)看起来像这样:

bin/foo bar : bin/% : % 

这里,bin/foo模式匹配,但bar不匹配和所以你会得到和上一次一样的错误。

为了使它工作,你必须有bin/前置到目标,不只是第一目标,因此,使用的patsubst(或addprefix会工作为好)。