了解Makefile(C+;+;)的依赖关系 在C++项目上工作时,我注意到我正在对我的主代码中链接的头文件进行更改,但make实用程序没有注册它。考虑到使用“make-B”进行的更改,我不得不强制它以不同的方式编译

了解Makefile(C+;+;)的依赖关系 在C++项目上工作时,我注意到我正在对我的主代码中链接的头文件进行更改,但make实用程序没有注册它。考虑到使用“make-B”进行的更改,我不得不强制它以不同的方式编译,c++,c++11,makefile,dependencies,conceptual,C++,C++11,Makefile,Dependencies,Conceptual,我想知道为什么会这样;这是因为我的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) g

我想知道为什么会这样;这是因为我的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没有注意到它应该再次编译?因为我觉得这是一个概念上的误解,所以我觉得没有必要包括我在“make-B”中所做的更改或输出差异。它们是一些简单的东西,比如cout's和cerr's,包含在新的pairing_heap.h中,在强制之前不会被拾取

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


多谢各位

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

target: dependencies
        actions
它从中所知道的是,文件
目标
取决于
依赖项
中列出的文件,如果这些文件中有任何文件较新,则应运行
操作
中的命令来更新
目标
。就是这样——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
文件较新时,its才会运行这些操作

现在,你说,“我的其他规则呢——它们做什么?”结果是它们什么也没做。它们是生成名为
game
zombie
main
的文件的规则,而且由于您从未要求生成这些文件,并且没有其他依赖于它们的文件,因此它们什么也不做。你不妨删除它们

您还会问“如果头文件发生更改,我如何使其重新生成?”如果您添加一个没有操作的规则(只有目标和依赖项),它将只将这些依赖项添加到另一个有操作的规则(在本例中是内置的)。因此,如果您添加一行,如:

main.o: pairing_heap.h

(不执行任何操作),
make
将此依赖项添加到内置规则中,该规则知道如何从
main.cpp
生成
main.o
,并将运行该规则(重新编译
main.cpp
)如果
main.cpp
pairing\u hep.h
main.o
新,这正是您想要的。

您在
main
的配方中列出了
pairing\u 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的自动依赖生成来生成一个名为
main

的可执行文件,感谢您解释了全局,然后深入到更精细的细节。很有教育性;我能挖出来。我预见我和makefiles之间会有更好的关系。