【问题标题】:Understanding the Dependencies of a Makefile (C++)了解 Makefile 的依赖关系 (C++)
【发布时间】:2015-02-10 14:31:41
【问题描述】:

在处理 C++ 项目时,我注意到我正在更改我的主代码中链接的头文件之一,但 make 实用程序没有注册它。鉴于使用“make - B”的更改,我不得不强制它以不同的方式编译。

我想知道为什么会这样;是因为我的 makefile 是如何编写的,我的文件如何相互依赖,两者都依赖,还是两者都不依赖?

这是我的生成文件:

CXXFLAGS = -Wall -Werror -std=c++11 -pedantic -Wvla -g
//CXXFLAGS = -std=c++11

all:    main.o game.o zombie.o
        g++ $(FLAGS)  game.o main.o zombie.o -o main $(CXXFLAGS)

game:   game.cpp 
        g++ $(FLAGS) -c game.cpp $(CXXFLAGS)

zombie: zombie.cpp
        g++ $(FLAGS) -c zombie.cpp $(CXXFLAGS)

main:   main.cpp
        g++ $(FLAGS) -c main.cpp pairing_heap.h $(CXXFLAGS)

我对pairing_heap.h
进行了更改,它包含在我的主文件中。

为什么 make 没有注意到它应该再次编译?因为我觉得这是一个概念上的误解,所以我觉得没有必要包括我所做的更改或我做“make - B”时的输出差异。它们是简单的东西,例如新的 pairing_heap.h 中包含的 cout 和 cerr,直到被强制才被拾取。

如果我需要提供更多信息,请告诉我。

谢谢。

【问题讨论】:

    标签: c++ c++11 makefile dependencies conceptual


    【解决方案1】:

    您在 main 的配方中列出了 pairing_heap.h,这不会使其成为 main 的依赖项(此外,您不应该像这样将标头传递给编译器),因为您需要编写规则如下:

    main:   main.cpp pairing_heap.h 
            g++ $(FLAGS) -c main.cpp $(CXXFLAGS)
    

    您的文件中还有许多其他不正确的地方,例如您的目标不是实际文件(main: 应该是 main.o: 等),并且您没有使用自动变量或模式规则,但将所有内容替换为以下内容可能更容易

    CPPFLAGS := -MMD -MP
    CXXFLAGS := -Wall -Werror -std=c++11 -pedantic -Wvla -g
    SOURCES  := $(wildcard *.cpp)
    
    main: $(SOURCES:.cpp=.o)
    
    -include $(SOURCES:.cpp=.d)
    

    它利用 make 的 implicit rules 和 gcc 的/clang 的自动依赖生成来生成一个名为 main 的可执行文件。

    【讨论】:

      【解决方案2】:

      Make 并不真正了解任何特定的编程语言或工具,因此它不理解 C/C++ 文件依赖于头文件和源文件。它只是有形式的规则

      target: dependencies
              actions
      

      它所知道的是文件target 依赖于dependencies 中列出的文件,如果这些文件中的任何一个更新,则应该运行actions 中的命令来更新target。就是这样 - make 所做的一切都来自目标文件、依赖项和操作的简单概念。

      现在还有更多内容 - make 有一堆内置规则,用于您经常想做的常见事情,以及指定“模式”规则的方法 - 规则在哪里目标包含通配符,因此可用于许多不同的目标,这些目标依赖于具有相关名称的其他文件。

      现在你的情况,你有规则:

      all:    main.o game.o zombie.o
              g++ $(FLAGS)  game.o main.o zombie.o -o main $(CXXFLAGS)
      

      表示要重新制作文件all,如果它比文件main.ogame.ozombie.o 旧,它应该运行该命令。这是文件中的第一条规则,因此当您键入 make 时,它会默认生成。

      现在,您可能没有名为 all 的文件(如果您有 make 可能不会做任何事情),但这通常很好,好像它不存在一样,它显然达不到日期,所以该命令需要运行。 当命令需要运行时,它还会检查任何依赖项,以查看它们是否又具有较旧的依赖项(因此需要重新构建)。由于这些文件都以.o 结尾,它们匹配一个知道如何从具有相同名称的文件构建它们的内置规则,除了以.cpp 结尾,因此当(且仅当) .cpp 文件较新。

      现在,你说,“我的其他规则呢?它们是做什么用的?”好吧,事实证明他们什么也没做。它们是构建名为gamezombiemain 的文件的规则,并且由于您从不要求构建这些文件,并且没有其他依赖于它们,它们什么都不做。您不妨删除它们。

      您还问“如果头文件更改,我如何使其重建?”好吧,如果你添加一个没有操作的规则(只是目标和依赖项),它只会将这些依赖项添加到另一个确实有操作的规则(在这种情况下是内置的)。因此,如果您添加如下一行:

      main.o: pairing_heap.h
      

      (无操作),make 将把这个依赖添加到知道如何从main.cpp 构建main.o 的内置规则中,并且如果 要么运行该规则(重新编译 main.cpp main.cpppairing_hep.hmain.o 更新——这正是你想要的。

      【讨论】:

      • 感谢您解释大局,然后深入了解细节。非常有教育意义;我可以挖。我预见到我和 makefile 之间的关系会更好。
      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多