我认为gnu make有一些基本的遗漏(如果重要的话,我使用的是3.81)静态模式规则匹配(显然其他人也在我工作的地方做了,因为这是在我尝试时发现的修复已注释掉的规则)。我试图简化我的例子到它的关键(希望我没有错过真实例子中的任何必要的东西)。
所以这看起来像我期望的那样工作
JUNK:=foo bar
BINS:=$(patsubst %,bin/%,$(JUNK))
all : $(BINS)
.PHONY : all
# This works
$(BINS) : bin/% : %
mkdir -p bin && cp $< $@
但是(这比我在真正的Makefile中找到的更接近)不是
JUNK:=foo bar
BINS:=$(patsubst %,bin/%,$(JUNK))
all : $(BINS)
.PHONY : all
# This doesn't work
$(JUNK) : bin/% : %
mkdir -p bin && cp $< $@
# This doesn't work either
#bin/$(JUNK) : bin/% : %
# mkdir -p bin && cp $< $@
根据我对两种情况下应该发生的事情的理解,我原本预计两个Makefile的行为都会完全相同;但是,只有第一个表现符合我的预期(即正确地将文件复制到bin),第二个表示以下输出
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文件中有几乎相同的其他静态模式规则正在运行。
所以我显然知道如何在需要时“解决”这个问题,但我想了解为什么第二个(以及第二个代码块中已注释掉的部分)没有按照我的期望去做
提前感谢任何帮助/见解。
答案 0 :(得分:2)
第一个不起作用,因为在展开JUNK
变量之后,make会看到:
foo bar : bin/% : %
静态模式规则的工作方式是第一个模式(目标模式)必须匹配目标列表中的每个单词。这告诉make目标名称的哪一部分是词干(与%
匹配的部分)。如果目标模式不匹配,则make不知道词干是什么。模式bin/%
与文字foo
不匹配(文字bin/
中没有foo
),因此您会收到错误。
第二个不起作用,因为在此示例(JUNK
)中扩展bin/$(JUNK) : bin/% : %
变量的结果如下所示:
bin/foo bar : bin/% : %
此处bin/foo
与模式匹配,但bar
不匹配,因此您得到的错误与之前的错误相同。
要使其发挥作用,您必须在每个目标前加bin/
,而不仅仅是第一个目标,因此使用patsubst
(或addprefix
也会起作用。)