【问题标题】:Makefile Pattern Rules unable to matchMakefile 模式规则无法匹配
【发布时间】:2020-12-06 01:48:36
【问题描述】:

自大学以来,我一直无法让模式规则为我工作。我完全按照这些例子所说的去做,但它永远不会奏效。我得到的只是错误:

make: *** No rule to make target '<whatever>.o', needed by 'all'.  Stop.

这是我当前的制作文件:

all: test clean

test : $(ODIR)/weight_nodeTest.o
    $(LINK) $(RUN)/$@ $^

$(ODIR)/%.o : $(TEST)/%.cpp $(SRC)/%.h
    $(COMPILE) $(ODIR)/$@ $^

clean :
    rm -f $(RUN)/*
    rm -f $(ODIR)/*

当我输入特定文件而不是通配符时,它可以完美运行。谁能告诉我我做错了什么??

【问题讨论】:

  • “自大学以来,我一直无法让模式规则发挥作用”。这太相关了。
  • 为什么all 依赖于clean?此外,$@ 已经包含目录,因此通常不应以 1 为前缀。
  • 如果&lt;whatever&gt;.o 没有规则,那是因为您的模式规则不匹配。让我们看看可能的原因。您的模式规则中有 3 个术语。 &lt;whatever&gt;.o 是否匹配 $(ODIR)/%.o?如果是的话,你能告诉我们真正的&lt;whatever&gt;.o吗?接下来,有没有真正对应的$(TEST)/%.cpp$(SRC)/%.h?你能告诉我们吗?你能创建一个MCVE吗?

标签: c++ makefile gnu-make gnu


【解决方案1】:

我认为人们一定对模式规则感到困惑,因为他们认为它们非常复杂。但模式规则实际上非常简单:它们只是匹配文本。正如 Renaud 所说,由于您在这里没有完整的示例,因此很难解释,但让我们假设它是这样的:

ODIR = obj
TEST = test
SRC = src

test : $(ODIR)/weight_nodeTest.o
        ...

$(ODIR)/%.o : $(TEST)/%.cpp $(SRC)/%.h
        $(COMPILE) $(ODIR)/$@ $^

解析makefile并展开规则后,make在其内部数据库中具有此等价物:

test : obj/weight_nodeTest.o
        ...

obj/%.o : test/%.cpp src/%.h
        $(COMPILE) $(ODIR)/$@ $^

所以,make 想要构建 test。要构建test,它想构建obj/weight_nodeTest.o

obj/weight_nodeTest.o 没有显式规则,因此 make 会查看其隐式规则目录。它会找到您的模式规则,并看到obj/%.o 与它要构建的目标obj/weight_nodeTest.o 匹配。这里的STEM是匹配%的部分,所以stem就是weight_nodeTest

但是,比赛过程还没有结束。考虑到有很多不同的方法来构建目标文件:make 可以有从 C 源文件、C++ 源文件、Fortran、COBOL、Rust 等构建目标文件的模式。换句话说,相同的模式 target 可能有许多与之匹配的规则,具有不同的先决条件。所以在我们知道这个模式规则是否正确之前,首先要检查一下先决条件。

在本例中,词干为 weight_nodeTest,我们将其替换为先决条件中的模式,因此先决条件为 test/weight_nodeTest.cppsrc/weight_nodeTest.h

Make 将检查这些文件是否存在(或者它可以找出如何从其他先决条件构建它们)。

如果 ALL 存在或可以构建先决条件,则模式匹配。

如果 ANY 的先决条件不存在且无法构建,则该模式不匹配,make 会寻找其他无法使用的模式。

就是这样,就是这样。

大多数情况下,当我看到人们编写包含 BOTH 源文件和头文件作为先决条件的模式规则时,问题是他们没有每个源文件的头文件。这意味着它们的模式将正确匹配以构建同时存在源文件和头文件的任何对象文件,并且不会正确匹配以构建缺少头文件的任何对象。

通常,您不希望将头文件作为模式添加到目标规则中,除非您 100% 确定总会有关联的头文件。

另外,Renaud 说的很对,你永远不希望你的编译规则使用普通的$@ 以外的任何东西作为要构建的目标。该变量将设置为目标 make 期望您的配方构建的路径。如果您构建其他文件,它将无法正常工作。如果纯 $@ 不是您想要的路径,那么您的模式规则没有正确编写。

【讨论】:

  • 只是为了完整性——可以有多个模式规则匹配您的目标。在这种情况下,make 选择具有最短词干的模式规则。 (如果词干长度相同,那么它会选择第一个最短词干模式规则)。我相信最短词干匹配是在 Make 3.81 中添加的,在此之前它只是匹配的第一个模式规则。
猜你喜欢
  • 2012-07-17
  • 2022-11-10
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多