首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >编译的乐章:项目自动化构建工具—Make/Makefile,在代码的世界中编织自动化的魔法

编译的乐章:项目自动化构建工具—Make/Makefile,在代码的世界中编织自动化的魔法

作者头像
用户11379153
发布2025-11-05 16:18:22
发布2025-11-05 16:18:22
1120
举报
在这里插入图片描述
在这里插入图片描述

前言

在软件开发的浩瀚宇宙中,构建与编译的过程常常是开发者日常工作中不可忽视的一部分。每当项目中加入新的代码或修改现有的代码时,我们不得不再次构建整个程序,确保修改的部分与整个项目的其余部分无缝衔接。这个过程,看似单调、枯燥,却也至关重要。正是这些小小的构建过程,确保了一个庞大软件系统的正常运作。

然而,在每次修改后手动执行一系列繁琐的构建命令,难免让人感到疲惫与困扰。这时,Make 和 Makefile 便应运而生,化繁为简,赋予了开发者极高的效率。

在这篇报告中,我们将深入探讨 Make 和 Makefile,如何在自动化构建的舞台上,成为程序员手中不可或缺的利器。

一、Make工具的起源与发展

Make 工具的历史可以追溯到上世纪70年代,源自 Unix 系统中的自动化构建需求。最初,Make 被设计为一个简单的自动化构建工具,用于编译大型项目。随着时间的推移,Make成为了软件开发中自动化构建的标准工具,它能自动分析源文件的依赖关系,决定哪些文件需要重新编译,并自动执行相应的构建命令。

*早期的 Make 仅仅支持简单的命令和文件依赖关系,但随着其不断发展,现代的 Make 版本(尤其是 GNU Make)已经具备了强大的功能,支持变量、条件判断、循环等高级特性,能够满足更加复杂的构建需求。

make/Makefile的本质

  • Make是一个自动化构建工具,它根据Makefile中的指令来自动化执行构建过程。Make的主要目的是简化复杂的构建过程,减少手动操作,从而提高开发效率。
  • Makefile是一个文本文件,其中包含了构建项目所需的规则和指令。

一个典型的Makefile包含以下部分:

  • 变量定义:用于定义编译器、编译选项等。
  • 目标:需要生成的文件,如可执行文件或对象文件。
  • 依赖关系:指定构建目标所依赖的源文件。
  • 命令:用于生成目标的具体命令。

make是⼀条命令,makefile是⼀个⽂件,两个搭配使⽤,完成项⽬⾃动化构建。

二、如何使用make/Makefile

使用实例

为了方便我们下面的讲解,我们这里先带大家看一下如何使用make/Makefile来实现自动化构建的功能

首先,我们要先明白为什么要有这个自动化构建工具,在我们之前的学习中,我们在编写代码的时候会经常用到gcc和删除相关的指令,每次都需要我们重新创建并删除可执行文件,这个操作比较冗余,且当工程比较大时,这种操作就会显得非常麻烦,所以就有了自动化构建工具

下面我们来看一下如何简单的使用make/Makefile

首先,我们要先在当前目录下创建一个Makefile文件

代码语言:javascript
复制
touch Makefile
在这里插入图片描述
在这里插入图片描述

然后进入这个文件中,将我们的源文件和目标文件建立依赖关系,和相关的清除语句

先来看一下我们的源文件test.c中的内容

代码语言:javascript
复制
#include<stdio.h>
  2 int main()
  3 {
  4     printf("Hello Linux\n");
  5     return 0;
  6 }     

在之前我们只能通过gcc来编译得到可执行文件,运行可执行文件才能得到结果,如果test.c中的内容进行了改动,就需要重新执行上面的步骤,比较繁琐.

但现在我们可以通过以下操作,在Makefile文件中写入以下内容:

代码语言:javascript
复制
mytest:test.c   
    gcc test.c -o mytest
clean:          
    rm -f mytest 
在这里插入图片描述
在这里插入图片描述

写入后保存并退出,然后执行make命令

在这里插入图片描述
在这里插入图片描述

执行后我们就可以发现我们执行了Makefile文件中的编译命令,生成了可执行文件,运行可执行文件后就可以得到我们想要的结果

当我们要删除我们得到的这个可执行文件时,需要下面的指令即可:

代码语言:javascript
复制
make clean
在这里插入图片描述
在这里插入图片描述

沉思

上面有几个小的知识点值得思考:

1、如果有多层依赖关系怎样处理?

这里的多层依赖关系指的是互相依赖,就比如在上篇我们已经讲过了可执行文件是由.o文件得来,而.o文件又依赖于.s文件,.s文件依赖于.i文件,.i文件依赖于.c文件,就这样层层依赖,才得到了最终的可执行文件,如果将这几个依赖关系都写入Makefile文件中去,其实我们可以发现它会自己处理这种多层依赖关系,即使我们的顺序写的不对

2、为什么make命令的执行结果是gcc编译?

这个取决于makefile的内容,make命令的功能是执行Makefile中的第一条命令,因为我们将编译的指令放在最上面,所以执行结果就是gcc编译,如果我们以下面的这种顺序写入Makefile文件:

3.当源文件不变时,只能编译一次:

在这里插入图片描述
在这里插入图片描述

当我们的源文件没有改动时,我们只能make编译一次,之后就无法再编译了,这样的原因其实是为了提高编译效率,那么make指令具体是怎么做的呢?这就牵扯到文件时间戳的问题了,下面我们详细讲解一下

三、make如何实现高效编译

make实现高效编译的原理其实就是通过比较源文件和可执行文件的修改时间,来判断是否可以再次执行,从而避免无效的执行

具体点来说就是源文件的修改时间新于可执行文件的修改时间时,就能够再次执行make命令,生成新的可执行文件

我们可以用stat指令来查看文件的时间的相关的信息

代码语言:javascript
复制
stat 文件名
在这里插入图片描述
在这里插入图片描述

在本篇我们需要关注到的就是这三个与时间相关的信息:

  • Access:最近访问的时间
  • Modify:最近对文件内容做修改的时间
  • Change:最近对文件属性做修改的时间

其中我们判断是否可以再次执行比较的是源文件与可执行文件的Modify时间

就比如我们上面的test.c和可执行文件mytest

在这里插入图片描述
在这里插入图片描述

我们可以发现可执行文件mytest的Modify时间新于源文件test.c的Modify时间,所以无法执行make命令

此时我们更新一下test.c文件中的内容

代码语言:javascript
复制
#include<stdio.h>        
 int main()               
 {                        
     printf("Hello Linux\n");
     printf("更新内容\n");                                                                                                                                                                                    
     return 0;            
 }         

更新之后再来查看一下test.c和mytest的时间:

在这里插入图片描述
在这里插入图片描述

此时源文件的最新修改时间就晚于可执行文件的最新修改时间,所以make就可以执行

以上就是make实现高效编译的方式

伪目标

代码语言:javascript
复制
myproc:myproc.o
gcc myproc.o -o myproc
myproc.o:myproc.s
gcc -c myproc.s -o myproc.o
myproc.s:myproc.i
gcc -S myproc.i -o myproc.s
myproc.i:myproc.c

gcc -E myproc.c -o myproc.i
.PHONY:clean
clean:
rm -f *.i *.s *.o myproc

⼀般我们这种clean的⽬标⽂件,我们将它设置为伪⽬标,⽤.PHONY修饰, 伪⽬标的特性是,总是被执⾏的。 因此可得出该结论: .PHONY:让make忽略源⽂件和可执⾏⽬标⽂件的M时间对⽐

四、使用Make的优势

  • 简化构建过程:通过定义规则,开发者可以简化构建过程,只需执行make命令。
  • 处理依赖关系:Make会自动处理文件之间的依赖关系,只有被修改的文件会被重新编译。
  • 跨平台性:Makefile可以在多种Unix/Linux系统间共享,简化了跨平台开发。

结语:Makefile的深远意义

在计算机世界的广袤天地里,Makefile或许只是众多工具中的一员。然而,它所代表的自动化构建理念,却深刻地影响了整个软件开发的进程。从初学者到资深开发者,每一位接触Makefile的人,都在这个过程中找到了高效与优雅的平衡。正如那位隐形的指挥家,Makefile将开发者的工作引领至一个个完美的高峰。

编写Makefile,也许只是一项技术任务,但它却以其简洁、高效与诗意的魅力,永远镶嵌在开发者心中,成为一段难忘的记忆。

本篇关于Make和Makefile的介绍就暂告段落啦,希望能对大家的学习产生帮助,欢迎各位佬前来支持斧正!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、Make工具的起源与发展
    • make/Makefile的本质
  • 二、如何使用make/Makefile
    • 使用实例
    • 沉思
  • 三、make如何实现高效编译
    • 伪目标
  • 四、使用Make的优势
  • 结语:Makefile的深远意义
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档