make的问题

时间:2015-02-16 14:50:46

标签: makefile

让我们考虑一下这个小例子。没有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 ...)来加快速度。实际上我期待的错误如下:"无法找到VILLAIN来制作obj / foo.o"

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%)

为什么在构建其先决条件之前尝试制作目标?

1 个答案:

答案 0 :(得分:2)

在这方面,模式规则不像显式规则那样工作。可以使用许多不同的模式规则来创建相同的目标(考虑,可以从C源文件,C ++源文件,FORTRAN源文件等创建.o。)< / p>

因此,当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.