品牌问题 [英] Issue with make

查看:51
本文介绍了品牌问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们考虑这个小例子.没有VILLAIN,一切都应该正常工作.其实这个词会导致错误,但不是我期望的地方...

Let's consider this tiny example. Everything should work fine without the VILLAIN. Actually this word leads to an error but not where I was expecting it...

错误:

$ 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"

It seems make wants to go a bit too fast by executing a recipe where its dependencies are not already made (obj/foo.o ...). Actually I was expecting an error like: "Unable to find VILLAIN to make 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))

但是,如果我移除小人,一切都将正常运行

However if I remove the villain everything works fine:

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

为什么在建立前提条件之前先尝试使其成为目标?

Why make try to make a target before building its prerequisite?

推荐答案

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

Pattern rules don't work like explicit rules in this respect. There can be many, many different pattern rules that could be used to create the same target (consider, a .o can be created from a C source file, C++ source file, FORTRAN source file, etc. etc.)

因此,当make尝试找到构建目标的模式规则时,为了确定模式是否匹配,make会尝试构建所有先决条件.如果其中一个先决条件无法建立,那么这不是错误! Make继续执行下一个匹配并尝试的模式规则.因此,VILLIAN不存在且无法构建的事实,仅意味着make永远不会选择此模式规则,因为无法满足先决条件...但这不是错误,也不会打印任何消息(好吧,如果您查看make的调试输出,将会看到关于它的注释.)

So, when make tries to find a pattern rule to build a target, in order to decide whether the pattern matches or not make will try to build all the prerequisites. If one of the prerequisites cannot be built, then it is not an error! Make simply goes on to the next pattern rule that matches and tries that. So the fact that VILLIAN doesn't exist and can't be built, just means that make will never select this pattern rule because the prerequisites cannot be satisfied... but this is not an error and no message will be printed (well, if you look at make's debug output you'll see a note about it).

因此make会发现它没有知道如何构建obj/foo.o的规则.您可能会在那时遇到错误...但是不会,因为您添加了以下规则:

So make will discover it has no rules that know how to build obj/foo.o. You'd expect to get an error at that point... but you won't because you've added this rule:

$(OBJ) : | $(OBJDIR)

通过执行此操作,您已声明obj/foo.o为已知的目标,因此如果目标不存在,它将不会抱怨.如果更改此选项以将仅订购的先决条件添加到模式规则中,则将获得更多可理解的行为:

By doing this you've declared obj/foo.o to be a target that make knows about and so it won't complain if the target doesn't exist. If you change this to add the order-only prerequisite into the pattern rule, then you'll get more comprehensible behavior:

$(OBJDIR)/%.o: $(SRCDIR)/%.c VILLAIN | $(OBJDIR)
        cp $< $@

$(OBJDIR):
        mkdir -p $@

赠予:

make: *** No rule to make target 'obj/foo.o', needed by 'out.exe'.  Stop.

这篇关于品牌问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆