了解 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
进行了更改,#included 在我的主文件中。
为什么 make 没有注意到它应该重新编译?因为我觉得这是一个概念上的误解,所以我觉得没有必要包括我所做的更改或我做时的输出差异"make - B"。它们是简单的东西,例如新 pairing_heap.h 中包含的 cout 和 cerr,直到被迫才被拾起。
如果我需要提供更多信息,请告诉我。
谢谢。
Make 并不真正了解任何特定的编程语言或工具,因此它不了解 C/C++ 文件依赖于头文件和源文件。它只有
形式的规则
target: dependencies
actions
它从这里知道的是文件 target
依赖于 dependencies
中列出的文件,如果这些文件中的任何一个较新,则 actions
中的命令应该是运行 更新 target
。确实如此——make 所做的一切都来自目标文件、依赖项和操作的简单概念。
现在 更重要了 -- make 有一堆内置规则,用于您经常想做的常见事情,以及指定方法 'pattern' 规则 -- 目标包含通配符的规则,因此可用于许多依赖于具有相关名称的其他文件的不同目标。
现在在你的情况下,你有规则:
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
结尾,所以它的 运行s当(且仅当).cpp
文件较新时这些操作。
现在,你说,"what about my other rules -- what do they do?" 好吧,事实证明他们什么也没做。它们是构建名为 game
、zombie
和 main
的文件的规则,并且由于您从不要求构建这些文件并且没有其他文件依赖于它们,因此它们什么也不做。你不妨删除它们。
你还问 "How do I make it rebuild if the header file changes?" 那么,如果你添加一个没有操作的规则(只有目标和依赖项),它只会将这些依赖项添加到另一个规则(在这种情况下是内置的) 有动作吗?所以如果你添加一行:
main.o: pairing_heap.h
(不执行任何操作),make
会将此依赖项添加到知道如何从 main.cpp
构建 main.o
的内置规则中,并将 运行规则(重新编译 main.cpp
)如果 main.cpp
或 pairing_hep.h
比 main.o
更新——这正是您想要的。
您在 main
的配方中列出 pairing_heap.h
,这不会使其成为 main
的依赖项(此外,您永远不应将 headers 传递给像这样的编译器),为此你需要编写如下规则:
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 的 s/clang 的自动依赖生成来生成名为 main
.
的可执行文件
在处理 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
进行了更改,#included 在我的主文件中。
为什么 make 没有注意到它应该重新编译?因为我觉得这是一个概念上的误解,所以我觉得没有必要包括我所做的更改或我做时的输出差异"make - B"。它们是简单的东西,例如新 pairing_heap.h 中包含的 cout 和 cerr,直到被迫才被拾起。
如果我需要提供更多信息,请告诉我。
谢谢。
Make 并不真正了解任何特定的编程语言或工具,因此它不了解 C/C++ 文件依赖于头文件和源文件。它只有
形式的规则target: dependencies
actions
它从这里知道的是文件 target
依赖于 dependencies
中列出的文件,如果这些文件中的任何一个较新,则 actions
中的命令应该是运行 更新 target
。确实如此——make 所做的一切都来自目标文件、依赖项和操作的简单概念。
现在 更重要了 -- make 有一堆内置规则,用于您经常想做的常见事情,以及指定方法 'pattern' 规则 -- 目标包含通配符的规则,因此可用于许多依赖于具有相关名称的其他文件的不同目标。
现在在你的情况下,你有规则:
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
结尾,所以它的 运行s当(且仅当).cpp
文件较新时这些操作。
现在,你说,"what about my other rules -- what do they do?" 好吧,事实证明他们什么也没做。它们是构建名为 game
、zombie
和 main
的文件的规则,并且由于您从不要求构建这些文件并且没有其他文件依赖于它们,因此它们什么也不做。你不妨删除它们。
你还问 "How do I make it rebuild if the header file changes?" 那么,如果你添加一个没有操作的规则(只有目标和依赖项),它只会将这些依赖项添加到另一个规则(在这种情况下是内置的) 有动作吗?所以如果你添加一行:
main.o: pairing_heap.h
(不执行任何操作),make
会将此依赖项添加到知道如何从 main.cpp
构建 main.o
的内置规则中,并将 运行规则(重新编译 main.cpp
)如果 main.cpp
或 pairing_hep.h
比 main.o
更新——这正是您想要的。
您在 main
的配方中列出 pairing_heap.h
,这不会使其成为 main
的依赖项(此外,您永远不应将 headers 传递给像这样的编译器),为此你需要编写如下规则:
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 的 s/clang 的自动依赖生成来生成名为 main
.