【Linux探索学习】第九弹——Linux工具篇(四):项目自动化构建工具—make/Makefile

Linux笔记:https://blog.csdn.net/2301_80220607/category_12805278.html?spm=1001.2014.3001.5482

前言:

在前面我们学习了如何用编译并执行,在现代软件开发中,构建一个项目涉及多个步骤,从编译源代码到链接库文件,再到生成最终的可执行文件。为了简化这个过程,特别是在大型项目中,自动化构建工具显得尤为重要。本文将深入探讨Linux中的一个广泛使用的自动化构建工具——Make及其配置文件Makefile。

目录

一、什么是make/Makefile

make/Makefile的本质

二、如何使用make/Makefile

使用实例

思考

三、make如何实现高效编译

四、使用Make的优势

五、多文件编译(进度条)

六、总结


一、什么是make/Makefile

make/Makefile的本质

Make是一个自动化构建工具,它根据Makefile中的指令来自动化执行构建过程。Make的主要目的是简化复杂的构建过程,减少手动操作,从而提高开发效率。

Makefile是一个文本文件,其中包含了构建项目所需的规则和指令。一个典型的Makefile包含以下部分:

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

简单点来说make是一个命令,Makefile是当前目录下的一个文件

二、如何使用make/Makefile

使用实例

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

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

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

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

touch Makefile

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

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

#include<stdio.h>2 int main()3 {4     printf("Hello Linux\n");5     return 0;6 }     

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

在Makefile文件中写入以下内容:

mytest:test.c   gcc test.c -o mytest
clean:          rm -f mytest 

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

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

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

make clean

这样我们就能删除可执行程序


思考

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

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

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

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

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

 clean:           rm -f mytest                                                                                                                                                                                             mytest:test.c    gcc test.c -o mytest

此时我们再执行make命令的执行结果就是清除而不是编译

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

我们来看这样一个现象:

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

三、make如何实现高效编译

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

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

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

stat 文件名

stat可以查看到的信息如下:

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

Access:最近访问的时间

Modify:最近对文件内容做修改的时间

Change:最近对文件属性做修改的时间

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

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

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

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

#include<stdio.h>        int main()               {                        printf("Hello Linux\n");printf("更新内容\n");                                                                                                                                                                                    return 0;            }         

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

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

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

四、使用Make的优势

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

五、多文件编译(进度条)

这个是make/Makefile进行使用的一个实例——进度条的编写,我这里对这段代码不进行讲解,感兴趣的可以看一下,本篇的重点还是上面的内容

processBar.h

#include<unistd.h>
#define Num 102
#define TOP 100
#define BODY '='
#define RIGHT '>'void processbar(int rate);

processBar.c

const char* lable = "|/-\\";
char bar[Num];void processbar(int rate)
{if (rate < 0 || rate>100)return;int len = strlen(lable);printf("[%-100s][%d%%][%c]\r", bar, rate, lable[rate % len]);fflush(stdout);bar[rate++] = BODY;if (rate < 100)bar[rate] = RIGHT;
}

test.c

int main()
{int total = 1000;int curr = 0;while (curr <= total){processbar(curr * 100 / total);curr += 10;sleep(1);}printf("\n");return 0;
}

Makefile

processBar:processBar.c test.cgcc -o $@ $^ -g  .PHONY:clean         clean:               rm -f processBar 

运行结果:

六、总结

Make和Makefile是Linux环境中进行项目自动化构建的重要工具。通过定义清晰的规则和依赖关系,开发者可以大大简化构建过程,提高工作效率。无论是简单的项目还是复杂的多模块项目,掌握Make的使用都是软件开发者必备的技能之一。

感谢各位大佬观看,创作不易,还请各位大佬点赞支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/58479.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot+Vue+MySQL的房屋租赁系统

系统展示 系统背景 随着城市化进程的加速和人口流动性的增加&#xff0c;房屋租赁市场逐渐成为城市生活的重要组成部分。然而&#xff0c;传统的房屋租赁方式存在诸多问题&#xff0c;如信息不对称、交易成本高、租赁关系不稳定等&#xff0c;这些问题严重影响了租赁市场的健康…

View三大机制(一):触摸机制(事件分发)

传递过程遵循如下顺序&#xff1a;Activity->Window->PhoneWindow->DecorView->RootView->ViewGroup->View View事件方法执行顺序:onTouchListener > onTouchEvent > onLongClickListener > onClickListener 主要由三个重要的方法共同完成的,只有Vi…

【面试】rabbitmq的主要组件有哪些?

目录 1. Producer&#xff08;生产者&#xff09;2. Broker&#xff08;消息代理&#xff09;3. Exchange&#xff08;交换机&#xff09;4. Queue&#xff08;队列&#xff09;5. Consumer&#xff08;消费者&#xff09;6. Binding&#xff08;绑定&#xff09;7. Channel&am…

namespace 隔离实战

Docker简介 什么是虚拟化、容器化为什么要虚拟化、容器化?虚拟化实现 什么是虚拟化、容器化 物理机: 实际的服务器或者计算机。相对于虚拟机而言的对实体计算机的称呼。物理机提供给虚拟机以硬件环境&#xff0c;有时也称为“寄主”或“宿主”。 虚拟化: 是指通过虚拟化技术将…

Java AQS CountDownLatch 源码

前言 相关系列 《Java & AQS & 目录》《Java & AQS & CountDownLatch & 源码》《Java & AQS & CountDownLatch & 总结》《Java & AQS & CountDownLatch & 问题》 涉及内容 《Java & AQS & 总结》《Java & AQS &am…

Canvas 画布

文章目录 1. 初识1.1 认识画布1.2 兼容性1.3 上下文属性 2. 绘制2.1 绘制基本图形2.1.1 绘制矩形2.1.2 绘制圆形2.1.3 绘制直线2.1.4 绘制圆弧2.1.5 绘制贝塞尔二次曲线2.1.6 绘制贝塞尔三次曲线2.1.7 封装路径 2.2 颜色控制2.2.1 颜色设置2.2.2 线性渐变2.2.3 径向渐变2.2.4 圆…

使用 web (vue 和DRF))实现 模拟一个IDE 功能思路

采用文件系统和数据库相结合的方案&#xff0c;不仅可以实现基本的文件管理&#xff0c;还可以为未来的扩展提供灵活性。结合我们讨论的内容&#xff0c;以下是更完善的策略&#xff1a; 方案概述&#xff1a;文件系统与数据库结合 文件系统负责实际的文件存储和执行操作&…

javascript中的展开运算符是什么

展开运算符&#xff08;Spread Operator&#xff09;是 JavaScript 中一个非常有用的语法特性&#xff0c;它通过三个点 ...来展开可迭代对象&#xff08;如数组或对象&#xff09;&#xff0c;使其可以更方便地进行操作。 1. 数组中的使用 1.1 合并数组 展开运算符可以轻松地…

XML解析小坑记录[正则表达式解析]

一、问题描述 在做 SSO 单点登录时( 认证中为CAS服务对接 )。在完成对用户ticket票根校验后&#xff0c;返回了用户信息有关 XML 数据片段&#xff0c;例如下&#xff1a; <cas:serviceResponse xmlns:cas"http://www.xxx.xx/xx/cas"><cas:authentication…

ffmpeg视频滤镜:网格-drawgrid

滤镜介绍 drawgrid 官网链接 》 FFmpeg Filters Documentation drawgrid会在视频上画一个网格。 滤镜使用 参数 x <string> ..FV.....T. set horizontal offset (default "0")y <string> ..FV.....T. set…

(50)MATLAB最优延迟迫零均衡器仿真测试与评估

文章目录 前言一、最优延迟迫零均衡器评估模型二、最优延迟迫零均衡器仿真代码1.代码如下&#xff1a;2.迫零均衡器函数zf_equalizer()的MATLAB源码 三、仿真结果画图1.不同权系数长度和延迟的迫零均衡器性能2. 不同权系数长度的迫零均衡器的最佳延迟 前言 对于预设均衡器延时…

用AI绘画工具提升创作效率,这款神器你一定不能错过!

在如今的创作领域&#xff0c;无论是插画师、设计师&#xff0c;还是内容创作者&#xff0c;都在寻找能够提升效率的工具&#xff0c;而AI绘画工具的诞生无疑是一场创意革命。通过AI技术的支持&#xff0c;我们不再需要耗费大量时间在绘制基础草图或反复调整细节上&#xff0c;…

为什么要使用Golang以及如何入门

什么是golang&#xff1f; Go是一种开放源代码的编程语言&#xff0c;于2009年首次发布&#xff0c;由Google的Rob Pike&#xff0c;Robert Griesemer和Ken Thompson开发。基于C的语法&#xff0c;它进行了一些更改和改进&#xff0c;以安全地管理内存使用&#xff0c;管理对象…

Oracle故障诊断(一线DBA必备技能)之ADRCI(四)

1. 题记&#xff1a; 本篇博文继续详细介绍一线DBA必备技能—Oracle DB故障诊断工具ADRCI。 2. 使用 ADRCI 进行故障诊断的步骤 1. 查看警报日志 警报日志是故障诊断的重要信息源&#xff0c;它记录了数据库启动、关闭、错误消息等关键事件。 首先启动 ADRCI。在操作系统命…

基于SpringBoot的项目工时统计成本核算管理源码带教程

该系统是基于若依前后端分离的架构&#xff0c;前端使用vue2&#xff0c;后端使用SpringBoot2。 技术框架&#xff1a;SpringBoot2.0.0 Mybatis1.3.2 Shiro swagger-ui jpa lombok Vue2 Mysql5.7 运行环境&#xff1a;jdk8 IntelliJ IDEA maven 宝塔面板 系统与功…

嵌入式学习-网络-Day04

嵌入式学习-网络-Day04 1.IO多路复用 1.1poll poll同时检测键盘和鼠标事件 1.2epoll 2.服务器模型 2.1循环服务器模型 2.2并发服务器模型 多进程模型 多线程模型 IO多路复用模型 网络聊天室 项目要求 问题思考 程序流程图 1.IO多路复用 1.1poll int poll(struct pollfd *fds, n…

Java 面向对象基础

目录 1. 面向对象2. 类与对象3. 面向对象在内存中的执行原理4. 类和对象注意事项5. this 关键字6. 构造器6.1 什么是构造器?6.2 构造器作用6.3 构造器应用场景 7. 封装性7.1 什么是封装&#xff1f;7.2 封装的设计规范7.3 封装的书写 8. 实体JavaBean 正文开始 1. 面向对象 …

《华为云主机:1024的惊喜馈赠》

《华为云主机&#xff1a;1024的惊喜馈赠》 一、1024 华为送云主机之缘起&#xff08;一&#xff09;特殊日子的馈赠意义&#xff08;二&#xff09;华为云主机活动初衷 二、华为云主机领取攻略&#xff08;一&#xff09;领取条件全解析&#xff08;二&#xff09;具体领取步骤…

第10章 自定义控件

第 10 章 自定义控件 bilibili学习地址 github代码地址 本章介绍App开发中的一些自定义控件技术&#xff0c;主要包括&#xff1a;视图是如何从无到有构建出来的、如何改造已有的控件变出新控件、如何通过持续绘制实现简单动画。然后结合本章所学的知识&#xff0c;演示了一个…

开始使用HBuilderX开发网页

1 给我一个用hbuilderx的理由 首先看一个截图&#xff1a; 现在技术更新太快了&#xff0c;大家伙儿也都用windows10甚至了11了&#xff0c;而我们还在使用熟悉的windows7&#xff0c;这对于编程桌面端没问题的&#xff0c;但是网络编程真实够费劲的了&#xff0c;或者用pytho…