让我们考虑一下这个小例子。没有VILLAIN,一切都应该正常工作。实际上这个词会导致一个错误,但不是我所期望的那样.
错误:
$ make
mkdir -p obj
zip out.exe obj/foo.o obj/bar.o obj/baz.o
zip warning: name not matched: obj/foo.o
zip warning: name not matched: obj/bar.o
zip warning: name not matched: obj/baz.o
zip error: Nothing to do! (out.exe)
Makefile:9: recipe for target 'out.exe' failed
make: *** [out.exe] Error 12似乎make希望通过执行一个还没有建立依赖项的菜谱(obj/foo.o .)来加快速度。实际上,我以为会有这样的错误:“找不到坏蛋来制造obj/foo.o”
The Makefile:
#!/usr/bin/env make
SRCDIR = src
OBJDIR = obj
SRC = $(addsuffix .c,foo bar baz)
OBJ = $(addprefix $(OBJDIR)/, $(notdir $(SRC:c=o)))
out.exe: $(OBJ)
zip $@ $^
$(OBJDIR)/%.o: $(SRCDIR)/%.c VILLAIN
cp $< $@
$(OBJ) : | $(OBJDIR)
$(OBJDIR):
mkdir -p $@
clean:
rm -f *.c
rm -rf $(OBJDIR)/ $(SRCDIR)/
mkdir -p $(SRCDIR)/
touch $(addprefix $(SRCDIR)/,$(SRC))然而,如果我移除恶棍,一切都很好:
$ make clean
rm -f *.c
rm -rf obj/ src/
mkdir -p src/
touch src/foo.c src/bar.c src/baz.c
$ make
mkdir -p obj
cp src/foo.c obj/foo.o
cp src/bar.c obj/bar.o
cp src/baz.c obj/baz.o
zip out.exe obj/foo.o obj/bar.o obj/baz.o
adding: obj/foo.o (stored 0%)
adding: obj/bar.o (stored 0%)
adding: obj/baz.o (stored 0%)为什么在建立一个目标的前提条件之前,就试着去做一个目标?
发布于 2015-02-16 15:11:40
在这方面,模式规则不像显式规则那样工作。可以使用许多不同的模式规则来创建相同的目标(考虑一下,可以从C源文件、C++源文件、FORTRAN源文件等创建一个C++)。
因此,当make试图找到模式规则来构建目标时,为了决定模式是否匹配,make将尝试构建所有的先决条件。如果其中一个先决条件无法构建,那么它不是一个错误!Make简单地继续下一个模式规则,该规则匹配并尝试该规则。因此,VILLIAN不存在且无法构建,这意味着make将永远不会选择此模式规则,因为前提条件不能满足.但这不是一个错误,也不会输出任何消息(如果您查看make的调试输出,就会看到有关它的注释)。
因此,make将发现它没有知道如何构建obj/foo.o的规则。你会希望在那个时候出错.但你不会因为你加入了这条规则
$(OBJ) : | $(OBJDIR)通过这样做,您已经声明obj/foo.o是一个让人知道的目标,因此如果目标不存在,它就不会抱怨。如果将此更改为将仅限顺序的先决条件添加到模式规则中,那么您将得到更易于理解的行为:
$(OBJDIR)/%.o: $(SRCDIR)/%.c VILLAIN | $(OBJDIR)
cp $< $@
$(OBJDIR):
mkdir -p $@给予:
make: *** No rule to make target 'obj/foo.o', needed by 'out.exe'. Stop.https://stackoverflow.com/questions/28544058
复制相似问题