简体   繁体   English

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

[英]Makefile Dependencies, What Should Be a Dependency?

I have a conceptual question regarding makefile dependencies and this is because I see inconsistency online about this. 我有一个关于Makefile依赖项的概念性问题,这是因为我在网上看到有关此问题的不一致之处。

Let's say I have the following files: 假设我有以下文件:

main.cpp         uses->     my_math.cpp and my_strings.cpp
my_math.cpp      uses->     my_math.h
my_strings.cpp   uses->     my_strings.h

If I have a makefile, with the general outlay of: 如果我有一个makefile,则一般费用如下:

program: $(all_objs)
     g++ $(all_objs) -o program
main.o: ...
     .......
my_math.o: ...
     .......
my_strings.o: ...
     .......

I don't know what should go into each dependency. 我不知道每个依赖项应该包含什么内容。 Like, math.o #includes my_math.h and my_strings.h, does that mean that main.cpp needs to recompile if I change my_math.h? 就像math.o #includes my_math.h和my_strings.h一样,这是否意味着如果我更改my_math.h,main.cpp需要重新编译吗? But why? 但为什么? It uses it like a library, right? 它像图书馆一样使用它,对不对? It doesn't need to recompile main.cpp or does it? 它不需要重新编译main.cpp还是对?

As in, should the result for main.o be: 像这样,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

I'm a bit lost on dependencies and how linking works. 我对依赖项以及链接的工作方式有些迷失。

Any help would be appreciated! 任何帮助,将不胜感激! Thank you! 谢谢!

The dependencies are everything whose change requires recompiling the source code. 依赖项是需要更改源代码才能进行更改的所有内容。 That includes not only your #include -d headers, but also the indirectly included system headers, and even (in principle) the compiler and build chain itself (when you upgrade your C++ compiler, you should recompile all your software). 这不仅包括您的#include -d标头,还包括间接包含的系统标头,甚至(原则上)还包括编译器和构建链本身(在升级C ++编译器时,应重新编译所有软件)。 If some of your C++ code is generated from some source (eg by tools like GNU bison or Qt moc , or by your own script), both the sources and the generating tools are dependencies. 如果您的某些C ++代码是从某些源生成的(例如,通过GNU bison或Qt moc之类的工具或您自己的脚本生成),则源和生成工具都是依赖项。 Read also about package managers . 另请参阅有关程序包管理器的信息

Practically speaking, the GCC compiler is able to output most make dependencies, notably with -M and related processor options . 实际上, GCC编译器能够输出大多数make依赖项,尤其是使用-M和相关的处理器选项 Read also about auto dependencies generation . 阅读有关自动依赖项生成的信息 See also this . 另请参见

(in practice, you generally don't code in your Makefile some explicit dependency on the compiler itself; but you should not forget to make clean when the compiler has been upgraded) (实际上,您通常不会在Makefile编写对编译器本身的某些显式依赖关系;但是,在升级编译器时,请不要忘记make clean

Unless your main.cpp is including my_strings.cpp (which is not conventional and is very bad taste), your make rule won't have a dependency from my_strings.cpp to main.o . 除非您的main.cpp包含my_strings.cpp (这不是常规的并且味道很差),否则您的make规则将不会从my_strings.cppmain.o进行依赖。 But probably your main.cpp is #include -ing (directly or indirectly) my_strings.h so main.o should depend not only on main.cpp but also on my_strings.h 但是您的main.cpp可能是#include -ing(直接或间接) my_strings.h因此main.o应依赖于main.cpp还应依赖于my_strings.h

As a rule of thumb, your object file my_strings.o depends on the source file my_strings.cpp and all the header files which are directly or indirectly #include -d in it. 根据经验,目标文件my_strings.o取决于源文件my_strings.cpp和所有直接或间接包含在其中的#include -d 头文件 Your main program executable depends on all its object files and the libraries you are linking into it. 你的主要program执行依赖于它的所有目标文件和要链接到它的库。 Order of program arguments to g++ matters a lot. g++程序参数的顺序非常重要。

It uses it like a library, right? 它像图书馆一样使用它,对不对?

From what you are showing, you don't have any own libraries (but you probably use the standard C++ library, and perhaps some other system libraries). 根据显示的内容,您没有任何自己的 (但您可能使用标准的C ++库,也许还使用其他一些系统库)。 On Linux these are lib*.a files (static libraries) or lib*.so files (shared libraries). 在Linux上,这些文件是lib*.a文件(静态库)或lib*.so文件(共享库)。 A library is an organized agglomeration of object code -and sometimes other resources. 库是目标代码(有时是其他资源)的有组织的集合。

I'm a bit lost on dependencies and how linking works. 我对依赖项以及链接的工作方式有些迷失。

Understand the difference between source code files, object files (they contain relocation information) and executables (on Linux, object files and executable files and shared libraries are using the ELF format). 了解源代码文件, 目标文件 (它们包含重定位信息)和可执行文件 (在Linux上,目标文件和可执行文件以及共享库使用ELF格式)之间的区别。 Read also about the role of compilers , linkers (the g++ program can run both) & build automation (for which you are using make ). 另请阅读有关编译器链接器g++程序可以同时运行)和构建自动化 (要使用make的角色)的作用。

Read Program Library HowTo and much more about translation units and linkers (& name mangling ), notably Levine's book on Linkers & loaders . 阅读程序库HowTo以及有关翻译单元链接器 (及名称修改 )的更多信息,尤其是Levine的有关链接器和加载器的书。

See also this & that & this (examples about Makefile for C++ programs). 参见 (约实例Makefile为C ++程序)。

BTW, you should use g++ (not gcc ) when compiling C++ code. 顺便说一句,在编译C ++代码时,应该使用g++ (不是gcc )。 There are significant differences (even if gcc is sometimes able to compile C++ or Fortran code, you'll mostly use gcc to compile C code). 有很大的区别(即使gcc 有时能够编译C ++或Fortran代码,您也大多会使用gcc来编译C代码)。 And (assuming you use specifically GNU make) your Makefile should mention $(CXX) (not g++ ). 并且(假设您专门使用GNU make)您的Makefile应该提到$(CXX) (不是g++ )。 You need to understand the builtin rules of make (run once make -p to get them) and you'll better take advantage of them (eg use $(COMPILE.cc) or $(COMPILE.cpp) etc...). 您需要了解make的内置规则(运行一次make -p来获取它们),然后最好利用它们(例如,使用$(COMPILE.cc)$(COMPILE.cpp)等)。 You certainly should pass -Wall -Wextra (to get all warnings, and even more), and -g (to get debugging information) to g++ . 您当然应该将-Wall -Wextra (以获取所有警告,甚至更多)和-g (以获取调试信息)传递给g++ Practically speaking, you should set your CXXFLAGS variable in your Makefile . 实际上,您应该在Makefile设置CXXFLAGS变量。

Take time to carefully read GNU make documentation and Invoking GCC . 花时间仔细阅读GNU make文档Invoking GCC

Look into the Makefile -s of existing free software projects. 查看现有自由软件项目的Makefile -s。 For various reasons, some projects are generating their Makefile -s with tools like autoconf or cmake . 由于各种原因,一些项目正在使用诸如autoconfcmake类的工具生成Makefile -s。 But most simple projects don't need that generality, and you should be able to write your own Makefile for your C++ projects. 但是大多数简单的项目不需要这种通用性,因此您应该能够为C ++项目编写自己的Makefile Of course, take inspiration from existing code. 当然,可以从现有代码中汲取灵感。

If you have 如果你有

main.cpp         uses->     my_math.cpp and my_strings.cpp
my_math.cpp      uses->     my_math.h
my_strings.cpp   uses->     my_strings.h

The purpose of Make is to maintain dependency between modules in two different ways, by building .o files and by linking .o files. Make的目的是通过构建.o文件和链接.o文件,以两种不同方式维护模块之间的依赖性。

you can picture it as a dependency tree where main.o is the root 您可以将其描述为main.o是根的依赖关系树

                         main.o 
                       /       \
                   my_math.o   my_strings.o

for each .o there is also a dependency tree with regard to source files eg 对于每个.o,还有关于源文件的依赖树,例如

    main.o               my_math.o               my_strings.o
   /      \              /        \              /           \ 
main.cpp   main.h     my_math.cpp  my_math.h  my_strings.cpp my_strings.h

So when make builds, it sets up a dependency tree with main.o at its root and then tries to build all .o files needed for main. 因此,在进行make构建时,它将建立一个依赖树,其根目录以main.o为基础,然后尝试构建main所需的所有.o文件。 When all .o files have been built they are linked. 当所有.o文件构建完毕后,它们将被链接。

By following the dependency tree Make ensures that main will be linked/built when one of the dependent modules is changed. 通过遵循依赖关系树,Make可以确保在更改其中一个依赖模块时,将链接/构建main。

However if you have used something like say a constant from one of the included headers #define MAXSTRING 32 you are no longer merely dependent on the .o file, you are then dependent on the header content so you need to make sure that main.o is built if the header is changed since linking is then not enough so you add the .h in the dependency 但是,如果您从包含的头文件之一#define MAXSTRING 32使用了诸如说常量之类的内容,则您不再仅依赖于.o文件,而是依赖于头文件的内容,因此需要确保main.o如果因为链接不够而更改了标头,则会构建此链接,因此您需要在依赖项中添加.h

                               main.o 
                            /     |     \
                   my_math.o my_strings.o my_strings.h

Of course there are ways to make the header more robust to avoid that dependency but is another question. 当然,有一些方法可以使报头更健壮,从而避免这种依赖性,但这是另一个问题。

Your cpp files do not depend on other cpp files in terms of compilation. 您的cpp文件在编译方面不依赖于其他cpp文件。 Simple cpp file should only depend on h files. 简单的cpp文件应仅依赖于h文件。

In your question you say main.cpp depends on my_math.cpp and my_strings.cpp , but I think it is not true. 在您的问题中,您说main.cpp取决于my_math.cppmy_strings.cpp ,但我认为这是不正确的。 I can guess you have #include s there and these are your dependecies. 我猜你那里有#include ,这是你的依赖。

Generally speaking dependencies for cpp files are all #include d h files. 一般来说, cpp文件的依赖项都是#include d h文件。

Usually there are no dependencies between cpp files. 通常, cpp文件之间没有依赖关系。 You just generate o files by compiling them. 您只需通过编译即可生成o文件。 Then your final binary depends on all o files. 然后,最终的二进制文件取决于所有o文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM