Makefile 依赖,什么应该是依赖?

MrK*_*Kev 2 c c++ makefile

我有一个关于 makefile 依赖项的概念性问题,这是因为我在网上看到了关于此的不一致。

假设我有以下文件:

main.cpp         uses->     my_math.cpp and my_strings.cpp
my_math.cpp      uses->     my_math.h
my_strings.cpp   uses->     my_strings.h
Run Code Online (Sandbox Code Playgroud)

如果我有一个 makefile,一般支出为:

program: $(all_objs)
     g++ $(all_objs) -o program
main.o: ...
     .......
my_math.o: ...
     .......
my_strings.o: ...
     .......
Run Code Online (Sandbox Code Playgroud)

我不知道每个依赖项应该包含什么。比如,math.o #includes my_math.h 和 my_strings.h,这是否意味着如果我更改 my_math.h,main.cpp 需要重新编译?但为什么?它像图书馆一样使用它,对吧?它不需要重新编译 main.cpp 或者是吗?

如,main.o 的结果应该是:

1) main.o: main.cpp
         gcc -c main.cpp

2) main.o: main.cpp my_strings.cpp my_strings.h my_math.cpp my_math.h
         gcc -c main.cpp

3) main.o: main.cpp my_strings.cpp my_strings.h my_math.cpp my_math.h
         gcc -c main.cpp my_strings.cpp my_math.cpp
Run Code Online (Sandbox Code Playgroud)

我对依赖项和链接的工作方式有点迷失。

任何帮助,将不胜感激!谢谢!

Bas*_*tch 5

依赖项是其更改需要重新编译源代码的所有内容。这不仅包括您的#include-d 头文件,还包括间接包含的系统头文件,甚至(原则上)编译器和构建链本身(当您升级 C++ 编译器时,您应该重新编译所有软件)。如果您的某些 C++ 代码是从某个源生成的(例如,通过GNU bison或 Qt moc 之类的工具,或您自己的脚本),则源和生成工具都是依赖项。另请阅读有关包管理器的信息

实际上,GCC编译器能够输出大多数make依赖项,尤其是-M 和相关的处理器选项。另请阅读有关自动依赖项生成的信息。另请参见

(在实践中,您通常不会Makefile在对编译器本身的某些显式依赖项中进行编码;但是make clean当编译器升级时您不应忘记)

除非您main.cpp包含my_strings.cpp(这不是传统的并且非常糟糕),make否则您的规则不会依赖于my_strings.cppto main.o。但可能你main.cpp#include-ing(直接或间接)my_strings.h所以main.o应该不仅取决于main.cpp而且还取决于my_strings.h

根据经验,您的目标文件my_strings.o取决于源文件my_strings.cpp和其中直接或间接-d 的所有头文件#include。您的主要program可执行文件取决于它的所有目标文件和您链接到其中的库。程序参数的顺序g++很重要。

它像图书馆一样使用它,对吧?

从您所展示的内容来看,您没有任何自己的(但您可能使用标准 C++ 库,也可能使用其他一些系统库)。在 Linux 上,这些是lib*.a文件(静态库)或lib*.so文件(共享库)。库是目标代码和其他资源的有组织的集合。

我对依赖项和链接的工作方式有点迷失。

了解源代码文件、目标文件(它们包含重定位信息)和可执行文件(在 Linux 上,目标文件和可执行文件以及共享库都使用ELF格式)之间的区别。另请阅读有关编译器链接器(该g++程序可以同时运行两者)和构建自动化(您正在使用的make)的作用。

阅读Program Library HowTo以及更多关于翻译单元链接器(和名称修改)的内容,特别是 Levine 关于链接器和加载器的书。

另见this & that & this(关于MakefileC++程序的例子)。

顺便说一句,您应该在编译 C++ 代码时使用g++(not gcc)。有显著差异(即使gcc有时能够编译C ++或Fortran代码,你会大多使用gcc编译C代码)。并且(假设您专门使用 GNU make)您Makefile应该提及$(CXX)(不是g++)。您需要了解make(运行一次make -p以获取它们)的内置规则,并且您将更好地利用它们(例如使用$(COMPILE.cc)$(COMPILE.cpp)等...)。您当然应该通过-Wall -Wextra(以获取所有警告,甚至更多)和-g(以获取调试信息)到g++. 实际上,您应该CXXFLAGSMakefile.

花时间仔细阅读GNU make 文档Invoking GCC

查看Makefile现有自由软件项目的-s。由于各种原因,一些项目正在使用或 之类的工具生成它们的Makefile-s 。但是大多数简单的项目不需要这种通用性,您应该能够为您的 C++ 项目编写自己的项目。当然,从现有代码中获取灵感。autoconfcmakeMakefile