make和gcc有什么区别?

44
在该文章的最后一个句子引起了我的注意。
引用:
“对于C/C++开发人员和学生,他们有兴趣学习如何使用C/C++编程而不是Linux用户。这是因为在GNU/Linux中通过使用'make'命令使源代码的编译变得简单。”
我一直使用gcc来编译我的C/C++程序,而javac来编译我的Java程序。我只使用make命令通过configure / make / make install安装程序到计算机上。
看起来你可以用make命令来编译所有程序。
“make”和“gcc”有什么区别?

需要注意的是,javac 包含一些基本的依赖关系解析功能,即它也是一个简单的 make 工具。它会递归查找其他类使用的(源代码)类,并在需要时编译它们,即使它们没有被作为参数提及。C 编译器或链接器不会这样做,部分原因是对象文件或库与源代码之间的联系不能像 Java 中那样推断出来,因为物理文件名和路径对应于逻辑类名和包名。 - Peter - Reinstate Monica
12个回答

76

嗯……gcc是一个编译器,make是一个帮助构建程序的工具。它们之间的区别非常大。您无法仅使用make构建程序,因为它不是编译器。make所做的是引入一个单独的“规则”文件,描述如何从源代码生成完成的程序。然后它解释这个文件,找出需要编译的内容,并为您调用gcc。对于具有数百或数千个源代码文件以及跟踪编译器选项、包含路径等内容的大型项目来说,这非常有用。


1
现在,对于简单的单文件应用程序,Makefile不再是必需的。如果你有一个名为application.cpp的文件,那么执行make application就可以构建它了。 - Martin York
@LokiAstari,那么对于单个文件使用make或gcc没有区别吗?当我使用gcc时,会得到一个.out文件,但是make会给出一个相同名称且没有扩展名的文件。有什么区别吗? - Manoj
1
@Manoj:从来没有说过没有区别。当你运行make plop.cpp时,它会准确地打印出它正在做什么:g++ plop.cpp -o plop(实际操作将根据您的环境而异,因为make还会从其中提取设置(因此它永远不会与直接调用g++相同))。对于简单情况,您只需要使用make就可以完成正确的事情,因此您不需要一个makefile。但总体而言,我认为正在发生的事情是相当直观的。 - Martin York

20

gcc 是一个编译器,可以编译和/或链接单个文件。它支持多种语言,但不知道如何将几个源文件组合成一个复杂的可运行程序 - 即使是最简单的程序,通常也需要至少两次调用 gcc(编译和链接)。

维基百科关于 GCC 的页面将其描述为“编译器系统”:

GNU 编译器集合(通常缩写为 GCC)是由 GNU 项目生产的支持各种编程语言的编译器系统。

make 是一个“构建工具”,按特定顺序调用编译器(可以是 gcc)编译多个源文件并将它们链接在一起。它还跟踪各个源文件和目标文件之间的依赖关系,这些目标文件是从源文件编译而来的,并且仅对自上次构建以来更改的部分进行操作。

GNUmake 是 make 的一个流行实现。GNUmake 的描述如下:

Make 是一种工具,控制从程序的源文件生成可执行文件和其他非源文件。

Make 通过一个叫做 makefile 的文件获取关于如何构建程序的信息,该文件列出了每个非源文件以及如何从其他文件计算它。


16

gcc是一种C编译器:它接受C源文件并创建机器代码,可以是未链接的目标文件形式或实际可执行程序形式,已链接到所有对象模块和库。

make对于控制项目的构建过程非常有用。一个典型的C程序由多个模块(.c)和头文件(.h)组成。如果每次更改后都要编译所有内容,那将会很耗时,因此make旨在仅编译需要重新编译的部分。

它通过遵循程序员创建的规则来实现这一点。例如:

foo.o: foo.c foo.h
    cc -c foo.c

这条规则告诉make文件foo.o依赖于foo.c和foo.h文件,如果它们中的任何一个发生变化,就可以通过运行第二行上的命令构建它。(以上不是实际语法:make希望通过TAB字符缩进命令,但我无法在此编辑模式下执行。请想象它在那里。)

make从一个通常称为Makefile的文件中读取其规则。由于这些文件(传统上)是手动编写的,因此make具有许多神奇的功能,让您可以缩短规则。例如,它知道可以从foo.c构建foo.o,并且它知道要执行的命令是什么。因此,上述规则可以简化为:

foo.o: foo.h

一个由三个模块组成的小程序可能有以下这样的Makefile:
mycmd: main.o foo.o bar.o
    $(CC) $(LDFLAGS) -o mycmd main.o foo.o bar.o
foo.o: foo.h bar.h
bar.o: bar.h

make 不仅可以编译程序,还可以做更多的事情。一个典型的 Makefile 会有一个规则来清除不需要的文件:

clean:
    rm -f *.o core myapp

另一个规则可能运行测试:

check: myapp
    ./myapp < test.input > test.output
    diff -u test.correct test.output

一个Makefile可能会“构建”文档:运行工具将文档从某种标记语言转换为HTML和PDF,例如。
一个Makefile可能有一个安装规则,将它构建的二进制程序复制到用户或系统管理员想要安装的任何位置。
等等。由于make是通用且强大的,因此通常用于自动化整个过程,从解压源tarball到软件准备好供用户使用的点。
如果您想完全学习它,那么有很多关于make的知识需要学习。 GNU版本的make有特别好的文档:http://www.gnu.org/software/make/manual/以各种形式提供。

1
我会将“make”和“gcc”与网络技术中的“git”和“ftp传输”进行比较:git就像make(仅在需要时更新更改的文件,这是常见用例),而gcc则像ftp(更改所有内容)。 - Timo

5

Make通常使用gcc来编译大量的C或C++文件。


4

Make是一种工具,用于构建任何复杂系统,其中各个系统组件之间存在依赖关系,并且只需进行必要的最小化工作。

如果您想了解make可以用于哪些事情,GNU make手册是非常好的参考。


4
make 使用当前目录下的 Makefile 文件来应用一组规则到其输入参数上。即使在当前目录下没有找到 Makefile(或类似文件),make 也知道一些默认规则,所以它仍然可以执行。对于 cpp 文件,许多系统中的规则会调用 gcc 来执行。

请注意,您不是使用 输入 文件名来调用 make,而是使用反映 输出规则名称。因此,调用 make xyz 将努力执行规则 xyz,该规则默认构建一个名为 xyz 的文件(例如基于源代码文件 xyz.cpp)。


4

gcc是像javac一样的编译器。你给它源文件,它会给你一个可执行程序。

make是一个构建工具。它接收一个描述如何基于文件之间的依赖关系构建项目文件的文件,因此当您更改一个源文件时,您不必重新构建所有内容(就像使用构建脚本一样)。make通常使用gcc来实际编译源文件。


正如我在对OP问题的评论中所说:javac不仅仅是一个编译器,它还根据内置规则执行依赖性检查(这些规则由于Java的路径/名称与包/类对应关系而变得简单)。 - Peter - Reinstate Monica

4

make本质上是一个构建代码的专家系统。您可以设置构建规则以及它们之间的依赖关系。Make会查看所有文件的时间戳,并在任何时候确定需要重新构建的内容。

gcc是“GNU编译器集合”。它支持许多语言(如C、C++、Ada等,取决于您的设置),但它仍然只是make用来构建系统的众多工具之一。


3

您可以使用 make 命令在 makefile 中调用 gcc 或 g++ 来编译 C 和 C++ 程序,执行所有编译和链接步骤,只需一个简单的命令即可完成。但它不是编译器的替代品。


3
'gcc' 是编译器,它将源代码转换成可执行文件的程序。你需要告诉它源代码在哪里,输出什么,以及各种库和选项等其他内容。
'make' 更像是编译程序的脚本语言。它可以隐藏编译源代码时的所有细节(例如必须传递给编译器的所有参数)。你只需在 Makefile 中编写上述所有细节一次,就不必为每个文件输入这些信息。它还可以做一些很棒的事情,比如只重新编译已更新的源文件,并处理依赖关系(如果我重新编译这个文件,那么我将需要重新编译那个文件)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接