了解Makefile(C++)的依赖关系
Understanding the Dependencies of a Makefile (C++)
在处理C++项目时,我注意到我正在对主代码中链接的一个头文件进行更改,但make实用程序没有注册它。考虑到使用"make-B"进行的更改,我不得不强制它以不同的方式编译。
我想知道为什么会出现这种情况;这是因为我的makefile是如何编写的,我的文件是如何相互依赖的,两者都依赖,还是两者都不依赖?
这是我的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没有注意到它应该重新编译?因为我觉得这是一个概念上的误解,所以我觉得当我"做-B"时,没有必要包括我所做的更改或输出差异。它们是一些简单的东西,比如cout和cerr,包含在新的pairing_heap.h中,直到被迫才被提取。
如果我需要提供更多信息,请告诉我。
谢谢。
您在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的隐式规则和gcc/clang的自动依赖生成来生成一个名为CCD_ 6的可执行文件。
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.o
、game.o
或zombie.o
旧,它应该运行该命令。这是文件中的第一条规则,因此当您键入make
时,默认情况下会生成它。
现在,您可能没有一个名为all
的文件(如果您使用make
,则可能不会执行任何操作),但这通常是可以的,就好像它不存在一样,它显然不是最新的,因此需要运行该命令。当一个命令需要运行时,它还会检查任何依赖项,看看它们是否有更旧的依赖项(因此需要重新生成)。由于这些文件都以.o
结尾,因此它们与一个内置规则相匹配,该规则知道如何从具有相同名称的文件构建它们,但以.cpp
结尾除外,因此,如果(且仅当).cpp
文件较新,它会运行这些操作。
现在,你说,"我的其他规则呢——它们做什么?"事实证明,它们什么都不做。它们是构建名为game
、zombie
和main
的文件的规则,由于您从不要求构建这些文件,而且其他文件都不依赖于它们,因此它们什么也不做。你不妨把它们删除。
您还会问"如果头文件发生更改,我如何重建它?"好吧,如果您添加一个没有操作的规则(只有目标和依赖项),它只会将这些依赖项添加到有操作的另一个规则(在本例中是内置的)中。所以,如果你加上一行,比如:
main.o: pairing_heap.h
(无需任何操作),make
将把这个依赖项添加到知道如何从main.cpp
构建main.o
的内置规则中,并且如果main.cpp
或pairing_hep.h
比main.o
新,则将运行该规则(重新编译main.cpp
)——这正是您想要的。
- C++GTKMM gui循环依赖关系
- 如何在头文件中声明类模板(由于循环依赖关系)
- 对在不同二进制文件中创建的对象文件的依赖关系
- 使用Bazel构建具有不同编译器/链接器选项的C/C++依赖关系
- OpenVINO - 推理库插件 libMKLDNNPlugin.so 无法解析依赖关系
- 模拟测试中类的依赖关系
- C++模板方法中的循环依赖关系
- 解析正交模块的依赖关系
- 如何在 Mac OS 上安装 boost-mpi 及其对 clang 的依赖关系?
- Wt::D bo 中的循环依赖关系
- 在包含窗口标头时难以解决循环依赖关系问题
- 当依赖关系和依赖关系都是多态时,在哪个继承级别存储依赖关系指针?
- 解决循环依赖关系 c++ 的想法
- C++循环依赖关系,未声明的标识符
- C++ 中的循环依赖关系问题
- 为什么包含需要进一步的依赖关系?
- 使用 cmake 获取外部依赖关系
- CMake 外部和内部静态库的循环依赖关系
- 在没有Xcode的macOS中开发具有依赖关系的应用程序
- "std::shared_ptr"循环依赖关系是如何导致问题的