default
每个单独的输出都应该是一个 make 目标,而不是让一个目标完成所有事情。这允许 make 正常工作,一次构建一件事,以正确的顺序(或者如果依赖关系图允许,则并行构建)并在每个步骤正确报告错误。此外,非常重要的是,通过告诉 make 关于每个单独的目标以及它们所依赖的内容,您可以确保当依赖项更改时,make 将准确地知道由于更改的依赖项需要重建哪些目标。这是 Make 的最大特点。
在您的情况下,最终目标是main
您希望default
目标构建它,您可以说这main
是一个先决条件main
:
default: main
现在你需要说如何构建main
,它取决于各种目标文件,所以我们告诉 make:
main: main.o sample.o sample_2.o sample_3.o
这表示它取决于那些目标文件(它们是它的先决条件),因此它们将首先被构建。这些对象中的每一个都是另一个将单独构建的 make 目标。
当所有的先决条件都建立好后,将使用一个配方将它们链接到main
中,因此我们需要向上述目标添加一个配方:
main: main.o sample.o sample_2.o sample_3.o
g++ main.o sample.o sample_2.o sample_3.o -o main
Make 有很多缩写来简化事情,例如$(CXX)
C++ 编译器,$@
表示当前目标和$^
当前目标的先决条件,因此您可以将该规则简化为:
main: main.o sample.o sample_2.o sample_3.o
$(CXX) $^ -o $@
这实际上就是你所需要的,Make 已经知道如何.o
使用其内置规则构建先决条件,因此它会看到一个名为的文件main.cpp
,并且知道它可以将其编译为 create main.o
,并查看sample.cpp
并将其编译为sample.o
等。它将创建一个依赖关系图用于决定构建需要哪些目标的makefile default
(这意味着它决定它需要main
和那个需要main.o
等等sample.o
,他们需要main.cpp
等等sample.cpp
已经存在,所以它可以开始构建先决条件,直到它拥有链接所需的一切main
然后它可以做到这一点并完成。)
现在,如果您更改sample_2.cpp
并make
再次运行,它将看到该文件sample_2.o
已过期并需要重新编译,但其他.o
文件仍然可以(它们比.cpp
它们所依赖的文件更新),因此它将重新编译sample_2.o
并重新链接main
而不是重建所有文件否则。
实际上,您可以通过使用将对象链接到可执行文件的默认配方来进一步简化它:
LINK.o = $(CXX)
default: main
main: main.o sample.o sample_2.o sample_3.o
这就是你所需要的!但通常更清楚,尤其是对于初学者来说,使用更详细的版本,因为当您不熟悉 Make 的所有自动规则和变量时更容易自定义。
告诉 make 关于头文件的依赖关系也很有帮助,以便在头文件更改时重新构建。这可以使用编译器自动生成先决条件,但对于简单的情况,您可以直接将其添加到 makefile 中,例如
sample.o: sample.hpp sample.cpp