c++ - Makefile 模式规则无法匹配

标签 c++ makefile gnu-make gnu

自从大学以来,我一直无法让模式规则对我有用。我完全按照例子所说的去做,但它从来没有奏效。我得到的只是错误:

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

这是我当前的 make 文件:

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)/*

当我输入特定文件而不是通配符时,它工作得很好。谁能告诉我我做错了什么?

最佳答案

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

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,它需要构建 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 等构建目标文件的模式。换句话说,相同的模式 目标可能有许多与之匹配的规则,并且具有不同的先决条件。因此,在我们知道这个模式规则是否正确之前,首先要检查先决条件。

在本例中,主干是 weight_nodeTest,我们用它替换先决条件中的模式,因此先决条件是 test/weight_nodeTest.cppsrc/Weight_nodeTest.h.

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

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

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

就是这样,就是这样。

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

通常,您不希望将 header 文件添加为目标规则中的模式,除非您 100% 确定始终存在关联的 header 。

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

关于c++ - Makefile 模式规则无法匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65163894/

相关文章:

c# - 在 C# 委托(delegate)中编码 va_list

C++ 将 const char * 与字符串连接,仅打印 const char *

c++ - 如何在编译或运行时检测非虚拟覆盖

Laravel 5 制作 :controller creating controller in app folder instead of controller folder

c++ - 如何在 CentOS 7.3 64bit 上安装 boost 库?

c++ - 访问头文件中定义的命名空间中的元素

makefile - makefile 中的路径不起作用

testing - Gnu Makefile,编译应该失败

c - 未定义对 `ceilf' 的引用

macos - 在 Mac 上更新 Make 版本