【问题标题】:Need help understanding makefile pattern rule % : %.o需要帮助理解 makefile 模式规则 % : %.o
【发布时间】:2018-04-25 09:10:42
【问题描述】:

我想使用我在书中读到的模式规则将这个 makefile 更改为更简单的东西:

VPATH = src
CPPFLAGS = -I include

main.o: main.cpp
    g++ $(CPPFLAGS) $<
TwoDimensionalShape.o: TwoDimensionalShape.cpp
    g++ -c $(CPPFLAGS) $<
Square.o: Square.cpp Square.h
    g++ -c $(CPPFLAGS) $<
Circle.o: Circle.cpp Circle.h
    g++ -c $(CPPFLAGS) $<
Rectangle.o: Rectangle.cpp Rectangle.h
    g++ -c $(CPPFLAGS) $<
Triangle.o: Triangle.cpp Triangle.h
    g++ -c $(CPPFLAGS) $<
ShapeStack.o: ShapeStack.cpp ShapeStack.h
    g++ -c $(CPPFLAGS) $<
ScreenManager.o: ScreenManager.cpp ScreenManager.h
    g++ -c $(CPPFLAGS) $<
ScreenState.o: ScreenState.cpp ScreenState.h
    g++ -c $(CPPFLAGS) $<
SquareState.o: SquareState.cpp SquareState.h
    g++ -c $(CPPFLAGS) $<
CircleState.o: CircleState.cpp CircleState.h
    g++ -c $(CPPFLAGS) $<

读完这本书后,我可以使用这样的模式规则编写上述内容。但我不明白它是如何工作的:

#source files are in "src" folder.
VPATH = src
#header files are in "include" folder.
CPPFLAGS = -I include -Wall

all: main.o TwoDimensionalShape.o Square.o Circle.o Rectangle.o Triangle.o ShapeStack.o ScreenManager.o ScreenState.o SquareState.o CircleState.o
    g++ $(CPPFLAGS) $^

%.o: %.cpp
    g++ -c $(CPPFLAGS) $<

%: %.o
    g++ $<

这个 makefile 是正确的,但是我不明白它是如何工作的。

  1. 如果我更改例如 2 个源文件,这个 makefile 如何理解只编译更改的两个源文件而不是所有源文件?
  2. 在我阅读的书中,示例是关于 C 而不是 C++,最后一行是 %: %.c。那为什么我的%: %.o 行还在工作?不应该是%: %.cpp吗?

【问题讨论】:

  • 向后工作。查看您的 all 规则,将首先检查该规则。接下来,make 需要确定每个列出的 .o 依赖项是否是最新的,因此它会查找匹配它们的规则,该规则始终是 %.o: %.cpp 规则。因此,它会查看 main.cpp 以确定 main.o 是否是最新的,并且对于其他每个人来说都是一样的
  • 哦,用-d 运行它来调试你的makefile,这将显示它为每个文件考虑的规则
  • @jamek - make 跨平台的。更改为 cmake 只会更改您要询问的工具,它不能解决任何问题。
  • 如果正确设置CXXCXXFLAGS,就可以使用Make内置的%.o: %.cpp规则。您可以设置LINK.o = $(LINK.cc) 以使用内置链接器规则。 Slim makefile 是更好的 makefile!
  • @Jerome - 关于如何获得答案的建议是评论。只有实际答案才应作为答案发布。

标签: c++ makefile


【解决方案1】:

这个 makefile 是正确的,但是我不明白它是如何工作的。

如果你的新 Makefile 是旧 Makefile 的替代品,那它肯定是行不通的。

在您拥有的“旧”中,例如

ShapeStack.o: ShapeStack.cpp ShapeStack.h

这告诉 ShapeStack.o 依赖于 .cpp 和头文件。您的新 Makefile 对其他文件没有任何依赖关系,这将导致很多麻烦。只需触摸其中一个标题并输入 make。什么都不会发生!

所以至少你必须引入你的源文件依赖项,可能是像你旧的 makefile 中那样手动或者使用来自编译器的依赖项检查的更多自动化,使用 gcc 它与“gcc -MM”一起使用。

要获得自动化的先决条件,请参阅https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html

而且使用 vpath 会带来很多麻烦。有一些文章,例如: http://make.mad-scientist.net/papers/how-not-to-use-vpath/

可以在这里找到一些示例 Makefile: minimum c++ make file for linux

【讨论】:

  • 非常感谢。我使用了g++ -MM,但给了我很多警告...我必须阅读您提供的链接,手动引入头文件也会导致与文本相同的墙第一个makefile ...
  • @mhm:对于小型项目,编写自动生成 deps 的所有规则比手工规则要多。但是您应该考虑编写 once 一个具有此功能的通用 Makefile 并在您的所有项目中使用它。每个新项目只需要一行代码:OBJS=a.o, b.o... 和通用代码的包含。手动编写 deps 很容易出错,根本不应该这样做!
  • @mhm:添加了一个资源来查找带有 autodep 生成的简单 Makefile。注意:接受的答案不正确!
  • 建议不要错误地使用VPATH。看来这里用的不错。
  • @TobySpeight:这里提到它是因为它经常被错误地使用。我没说这里用错了。
猜你喜欢
  • 2021-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-01
  • 2013-11-09
  • 2020-05-29
  • 1970-01-01
相关资源
最近更新 更多