繁体   English   中英

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

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

我有一个关于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

如果我有一个makefile,则一般费用如下:

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

我不知道每个依赖项应该包含什么内容。 就像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

我对依赖项以及链接的工作方式有些迷失。

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

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

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

(实际上,您通常不会在Makefile编写对编译器本身的某些显式依赖关系;但是,在升级编译器时,请不要忘记make clean

除非您的main.cpp包含my_strings.cpp (这不是常规的并且味道很差),否则您的make规则将不会从my_strings.cppmain.o进行依赖。 但是您的main.cpp可能是#include -ing(直接或间接) my_strings.h因此main.o应依赖于main.cpp还应依赖于my_strings.h

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

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

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

我对依赖项以及链接的工作方式有些迷失。

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

阅读程序库HowTo以及有关翻译单元链接器 (及名称修改 )的更多信息,尤其是Levine的有关链接器和加载器的书。

参见 (约实例Makefile为C ++程序)。

顺便说一句,在编译C ++代码时,应该使用g++ (不是gcc )。 有很大的区别(即使gcc 有时能够编译C ++或Fortran代码,您也大多会使用gcc来编译C代码)。 并且(假设您专门使用GNU make)您的Makefile应该提到$(CXX) (不是g++ )。 您需要了解make的内置规则(运行一次make -p来获取它们),然后最好利用它们(例如,使用$(COMPILE.cc)$(COMPILE.cpp)等)。 您当然应该将-Wall -Wextra (以获取所有警告,甚至更多)和-g (以获取调试信息)传递给g++ 实际上,您应该在Makefile设置CXXFLAGS变量。

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

查看现有自由软件项目的Makefile -s。 由于各种原因,一些项目正在使用诸如autoconfcmake类的工具生成Makefile -s。 但是大多数简单的项目不需要这种通用性,因此您应该能够为C ++项目编写自己的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

Make的目的是通过构建.o文件和链接.o文件,以两种不同方式维护模块之间的依赖性。

您可以将其描述为main.o是根的依赖关系树

                         main.o 
                       /       \
                   my_math.o   my_strings.o

对于每个.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

因此,在进行make构建时,它将建立一个依赖树,其根目录以main.o为基础,然后尝试构建main所需的所有.o文件。 当所有.o文件构建完毕后,它们将被链接。

通过遵循依赖关系树,Make可以确保在更改其中一个依赖模块时,将链接/构建main。

但是,如果您从包含的头文件之一#define MAXSTRING 32使用了诸如说常量之类的内容,则您不再仅依赖于.o文件,而是依赖于头文件的内容,因此需要确保main.o如果因为链接不够而更改了标头,则会构建此链接,因此您需要在依赖项中添加.h

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

当然,有一些方法可以使报头更健壮,从而避免这种依赖性,但这是另一个问题。

您的cpp文件在编译方面不依赖于其他cpp文件。 简单的cpp文件应仅依赖于h文件。

在您的问题中,您说main.cpp取决于my_math.cppmy_strings.cpp ,但我认为这是不正确的。 我猜你那里有#include ,这是你的依赖。

一般来说, cpp文件的依赖项都是#include d h文件。

通常, cpp文件之间没有依赖关系。 您只需通过编译即可生成o文件。 然后,最终的二进制文件取决于所有o文件。

暂无
暂无

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

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