当前位置: 首页 > news >正文

【Linux】自动化构建工具 —— make/makefileLinux第一个小程序 - 进度条

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:Linux
🎯长路漫漫浩浩,万事皆有期待

上一篇博客:Linux编译器 gcc/g++的使用&&初识动静态链接库

文章目录

  • 一、前言
  • 二、概念
  • 三、代码实现
  • 四、实现原理
    • 1、依赖关系和依赖方法
    • 2、清理
      • ① .PHONY 伪目标
      • ② .PHONY 的取舍
    • 3、make 确定是否编译的方法
    • 4、完整代码
  • Linux第一个小程序 - 进度条
    • 行缓冲区的概念
    • \r和\n
    • 进度条代码及效果展示
  • 总结:

一、前言

上篇博客,我们学习了 gcc 编译器。学会了如何在 Linux 上编译C语言代码。如果有上百个源文件,难道一个个都用 gcc 编译为 .o 文件,最后将它们一起链接起来?

有没有一种方法,使编译更加快捷,一定程度实现自动化编译?
可以使用 make/makefile 构建一个简单的自动化工具。

二、概念

makefile :

makefile 是一个文件。它是一个工程文件的编译规则,描述了整个工程的编译链接等规则。
写好的 makefile 文件可以使用一行命令来完成 “自动化编译” ,从而完成对工程的编译,极大提高效率。

make :

make 是一个命令工具,用来一个解释 makefile 中文件中的指令。
当已经编写好 makefile 文件后,只需要使用 make ,就可以执行 makefile 中的内容。

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。所以使用好 make/makefile ,可以使得开发更加得心应手。

总结make 是一条指令makefile 是一个文件,两个搭配使用,完成项目自动化构建。

三、代码实现

在讲解 make/makefile 之前,我们先写一个小 demo ,以这个 demo 为基准,对其进行讲解。

makefile 文件需要创建在当前工程的目录下,makefile 文件的名称可以为 makefile 或 Makefile

假设当前工程下已经有了一个 test.c ,我们直接开始 demo 的编写:
在这里插入图片描述

这样 makefile 就编写好了,就两句话,这时编写的 makefile 可以完成对程序的编译。

我们返回终端,使用 make 就可以对 test.c 进行编译:

在这里插入图片描述

使用 make 指令后,makefile 的第二行内容被打印在终端,并且生成了可执行程序 test ,test 程序也是可以执行的。

四、实现原理

1、依赖关系和依赖方法

在 Makefile 文件中,有这样一句话:

test:test.c

刚刚测试过我们知道 test 是目标文件,而 test.c 则是原始文件。

而 test.c 经过 gcc test.c -o test 生成 test 文件。

它们的关系 :

  • test 依赖 test.c 生成,所以 test.c 是 test 的依赖文件 。它们之间的关系被称为 依赖关系 。
  • test.c 生成 test 需要通过 gcc test.c -o test 指令,这条指令就是 依赖方法 。

依赖关系 和 依赖方法 如何理解呢?

我们通过一个 makefile 理解一下:

在这里插入图片描述

在 makefile 文件中,共有四组依赖关系和依赖方法 ,当使用 make 调用 makefile 文件中内容时,便开始执行 makefile 中的内容:

test 依赖于 test.o ,但是 test.o 并不存在,跳转到下一组依赖关系
test.o 依赖于 test.s ,但是 test.s 并不存在,跳转到下一组依赖关系
test.s 依赖于 test.i ,但是 test.i 不存在,跳转到下一组依赖关系
test.i 依赖于 test.c ,test.c 存在,这时开始执行依赖方法

由此开始,逐渐执行上面的依赖方法,一层层回退,逐渐生成 test.i 、test.s 、test.o ,最后生成可执行程序,make 执行完毕。我们发现,这一过程就像 数据结构的栈 。

当目标文件所依赖的文件不存在时,就会将依赖方法入栈,知道依赖关系匹配了,再执行相应的依赖方法,在按照栈的规则,逐渐将栈中的元素出栈,规则满足后进先出。

为了验证这些步骤是否都被执行,我们 make 一下看看:
在这里插入图片描述

依赖方法对应的文件都产生了,所以依赖关系和依赖方法必须同时具备并正确,缺一不可 。

2、清理

平时写代码时,经常需要反复编译,执行代码。

而在下一次重新编译之前,需要清理一下上次生成的可执行程序。但是清理的时候可能清理错误,不小心把源文件删了,这时又造成了问题。

而上面的步骤,我们也生成了很多附加文件(如 test.i 等)。

所以我们基于 demo 增加一个清理功能:
在这里插入图片描述

使用 make 测试一下:

在这里插入图片描述

文件也都删除了。

这是为什么,新增语句是什么意思?

① .PHONY 伪目标

.PHONY 修饰的对象是伪目标,伪目标的特性是:总是被执行的。

.PHONY 修饰的一定能被反复执行,但是能被反复执行的不一定被 .PHONY 修饰。

多次执行 make 和 make clean 试试:
在这里插入图片描述

:makefile 默认从上到下扫描只会执行第一组的依赖关系和依赖方法,所以默认执行第一组,这时使用 make 就可以;而 clean 为第二组,所以需要 make clean ,加上对应的关系。同理,对于第一组,使用 make test 也能执行。

第一组关系没有被 .PHONY 修饰,而不能重复执行。但是第二组 clean 可以重复执行 。
但是怎么证明 .PHONY 修饰对象之后,对象能被反复执行?我们再验证一下,给 test 加上修饰:
在这里插入图片描述

加上 .PHONY 修饰后,make 可以执行多次了,证明了 .PHONY 的作用。
在这里插入图片描述

但是能被反复执行的不一定被 .PHONY 修饰,就比如 clean :

在这里插入图片描述

当 clean 去掉修饰之后,依然能被反复执行。
在这里插入图片描述

② .PHONY 的取舍

一般对于编译来说,是不加 .PHONY 修饰的。

因为编译是十分耗时间,特别是当工程量很大的时候,编译一两小时都不为过。所以防止对未修改的程序反复编译 ,一般编译时不加修饰。

但是 清理clean 是可以多次执行的,因为删除不太浪费时间,且可以反复清理,确认是否清理完毕。并且为了肯定清理可以被多次执行,所以通常用 .PHONY 修饰。

3、make 确定是否编译的方法

上面我们测试 make 时,发现当编译过一次后,继续使用 make 就无法继续编译了。但是 clean 是可以不加修饰反复执行的。 make 是如何确定是否要编译?

对于程序来说,时间有两条线。第一条是源代码时间的一条线,第二条是形成的可执行程序的时间的一条线 。而它们之间的次序,是先有源代码,再有可执行程序。

所以只要可执行程序的最近修改时间比源文件的修改时间晚,就认为当前可执行程序是最新的,为了减少时间和其他开销,于是不执行编译;反之执行编译 。

我们再重新生成可执行程序,并重复 make ,观察它们的时间:
这里就要用到 stat 指令,它的 modify 就是最近修改时间 ,如果对 stat 指令不了解的可以看这一篇:【Linux】基本指令(一) (在 ls 指令部分)
在这里插入图片描述

可执行程序 test 的时间明显比 源代码 test.c 晚,所以 make 并不能起作用。

那么基于对这个概念的理解,我们能否用其他方法再次执行 make ?

touch 指令为创建一个文件。若文件不存在则会创建一个文件;若文件存在则会把文件时间更新到最新。

使用 touch 更新一下 test.c 的时间,用 stat 观察时间,并反复 make 试试:
在这里插入图片描述

在这里插入图片描述

由此,我们发现可以使用 touch 来 “欺骗” make 来反复编译。这也侧面证明了: make 对于是否编译的决策是基于修改时间,而并不是基于文件内容是否修改 。

4、完整代码

test:test.cgcc test.c -o test 
.PHONY:clean                                                      
clean:rm -f test.i test.s test.o test

对于依赖关系而言,: 左边为目标文件,: 右边为依赖文件
依赖方法前需要有一个 tab ,为固定格式
: 右边可以有多个依赖文件 ,: 右边通常被称为依赖文件列表
对于 : 右边,目标文件对应的依赖文件列表可以为空 (例如 clean)
makefile 默认执行第一组的依赖关系和依赖方法,对于第一组可以直接使用 make 执行,后面则需要 make + 目标文件
.PHONY 修饰的 伪目标可反复执行 ,但反复执行的不一定是伪目标

Linux第一个小程序 - 进度条

行缓冲区的概念

首先,我们来感受一下行缓冲区的存在,在Linux当中以下代码的运行结果是什么样的?
在这里插入图片描述

对于此代码,当然是先输出字符串hello world然后休眠3秒之后结束运行。那么对于以下代码呢?
在这里插入图片描述

可以看到代码中仅仅删除了字符串后面的’\n’,那么代码的运行结果还与之前相同吗?
答案是不相同,该代码的运行结果是:先休眠3秒,然后打印字符串hello world之后结束运行。该现象就证明了行缓冲区的存在。

显示器对应的是行刷新,即当缓冲区当中遇到’\n’或是缓冲区被写满才会被打印出来,而在第二份代码当中并没有’\n’,所以字符串hello world先被写到缓冲区当中去了,然后休眠3秒后,直到程序运行结束时才将hello world打印到显示器当中。

\r和\n

\r: 回车,使光标回到本行行首。
\n: 换行,使光标下移一格。

在这里插入图片描述

而我们键盘上的Enter键实际上就等价于\n+\r。

既然是\r是使光标回到本行行首,那么如果我们向显示器上写了一个数之后再让光标回到本行行首,然后再写一个数,不就相当于将前面一个数字覆盖了吗?但不使用’\n’进行换行怎么将缓冲区当中数据打印出来?

这里我们可以使用fflush函数,该函数可以刷新缓冲区,即将缓冲区当中的数据刷新到显示器中。
对此我们可以编写一个倒计时的程序。
在这里插入图片描述

在输出下一个数之前都让光标先回到本行行首,就得到了倒计时的效果。

请添加图片描述

进度条代码及效果展示

知道了\r这个概念我们就可以实现一个简单的进度条了。
在这里插入图片描述
效果展示:

在这里插入图片描述

总结:

今天我们学习了自动化构建工具 —— make/makefile ,重点了解了 make/makefile 的规则上。实际开发中,好的 make/makefile 可以让项目开发事半功倍。接下来,我们将继续学习其他Linux环境基础工具的基本使用及配置。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

相关文章:

【Linux】自动化构建工具 —— make/makefileLinux第一个小程序 - 进度条

​ ​📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:Linux 🎯长路漫漫浩浩,万事皆有期待 上一篇博客:Linux编译…...

tensorflow的unet模型

import tensorflow as tf from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Dropout, UpSampling2D, concatenate# 定义 U-Net 模型 def unet(input_size(256, 256, 3)):inputs Input(input_size)# 编码器部分conv1 Conv2D(64, 3, activationrelu, padding…...

(2023 最新版)IntelliJ IDEA 下载安装及配置教程

IntelliJ IDEA下载安装教程(图解) IntelliJ IDEA 简称 IDEA,由 JetBrains 公司开发,是 Java 编程语言开发的集成环境,具有美观,高效等众多特点。在智能代码助手、代码自动提示、重构、J2EE 支持、各类版本…...

react 实现拖动元素

demo使用create-react-app脚手架创建 删除一些文件,创建一些文件后 结构目录如下截图com/index import Movable from ./move import { useMove } from ./move.hook import * as Operations from ./move.opMovable.useMove useMove Movable.Operations Operationse…...

【EI会议】第二届声学,流体力学与工程国际学术会议(AFME 2023)

第二届声学,流体力学与工程国际学术会议 2023 2nd International Conference on Acoustics, Fluid Mechanics and Engineering(AFME 2023) 声学、流体力学两个古老的学科发展至今,无时无刻都在影响着我们的生活。小到日常使用的耳…...

Android StringFog 字符串自动加密

一、StringFog 作用 一款自动对dex/aar/jar文件中的字符串进行加密Android插件工具,正如名字所言,给字符串加上一层雾霭,使人难以窥视其真面目。可以用于增加反编译难度,防止字符串代码重复。 支持java/kotlin。支持app打包生成…...

上四休三,未来的期许

近日“少上一天班,究竟香不香”引发关注,英国媒体2月21日报道,一项全世界目前为止参加人数最多的“四天工作制”试验,不久前在英国取得了成功。很多人表示上过四天班之后,给多少钱也回不去五天班的时代了。 来百度APP畅…...

怎么防止360安全卫士修改默认浏览器?

默认的浏览器 原先选项是360极速浏览器(如果有安装的话),我这里改成了Chrome。 先解锁 才能修改。...

调整参数提高mysql读写速度

要提升MySQL的写入速度,您可以采取一些参数调整和优化措施,这些措施可以根据您的具体应用和环境进行调整。以下是一些常见的参数和优化建议: InnoDB存储引擎: 如果您使用的是InnoDB存储引擎,确保以下参数被设置得合理: innodb_buffer_pool_size:增加内存池大小,以便更多…...

第一届电子纸产业创新应用论坛-邀请函

...

Go expvar包

介绍与使用 expvar 是 exposed variable的简写 expvar包[1]是 Golang 官方为暴露Go应用内部指标数据所提供的标准对外接口,可以辅助获取和调试全局变量。 其通过init函数将内置的expvarHandler(一个标准http HandlerFunc)注册到http包ListenAndServe创建的默认Serve…...

Yolo v8代码逐行解读

train.py文件 1.FILE Path(__file__).resolve() __file__代表的是train.py文件,Path(__file__).resolve()结果是train.py文件的绝对路径。 2.ROOT FILE.parents[0] 获得train.py父目录的绝对路径 3.sys.path 是一个列表list,里面包含了已经添加到系…...

9.18号作业

完善登录框 点击登录按钮后,判断账号(admin)和密码(123456)是否一致,如果匹配失败,则弹出错误对话框,文本内容“账号密码不匹配,是否重新登录”,给定两个按钮…...

Spring源码阅读(spring-framework-5.2.24)

spring-aop spring-aspects spring-beans spring-context 等等 第一步: Tags spring-projects/spring-framework GitHub 找到相应的release版本 第二步: 下载相应版本的gardle,如何看版本 spring-framework/gradle/wrapper /gradl…...

【SpringMVC】文件上传与下载、JREBEL使用

目录 一、引言 二、文件的上传 1、单文件上传 1.1、数据表准备 1.2、添加依赖 1.3、配置文件 1.4、编写表单 1.5、编写controller层 2、多文件上传 2.1、编写form表单 2.2、编写controller层 2.3、测试 三、文件下载 四、JREBEL使用 1、下载注册 2、离线设置 一…...

数据结构 第二章作业 线性表 西安石油大学

在顺序表中插入和删除一个结点需平均移动多少个结点?具体的移动次数取决于 哪两个因素? 在顺序表中插入和删除一个结点时,平均移动的结点数量取决于两个因素:插入/删除位置和当前顺序表的长度。 插入/删除位置:如果要…...

vue.mixin全局混合选项

在Vue.js中,Vue.mixin 是一个用来全局混合(mixin)选项的方法。它允许你在多个组件中共享相同的选项,例如数据、方法、生命周期钩子等。这可以用来在组件之间重复使用一些逻辑或共享一些通用的功能 Vue.mixin({// 在这里定义混合的选项data() {return {s…...

VMware Fusion 13+Ubuntu ARM Server 22.04.3在M2芯片的Mac上共享文件夹

因为Server版没有桌面,VMware Tools不能直接装,导致没办法共享文件。 Ubuntu中的包如果需要更新,先执行下面的步骤 sudo apt update 再执行 sudo apt upgrade 不需要更新的话,直接执行下面的步骤 先把open-vm-tools卸载了 …...

PostgreSQL serial类型

serial类型和序列 postgresql序列号(SERIAL)类型包括 smallserial(smallint,short),serial(int)bigserial(bigint,long long int) 不管是smallserial,serial还是bigserial,其范围都是(1,9223372036854775807)&#…...

[创业之路-76] - 创业公司如何在长期坚持中顺势而为?诚迈科技参观交流有感

目录 一、创业环境 1.1. VUCA乌卡时代:易变、复杂、不确定性、模糊的时代 1.2. 中国用了四十年的时间完成了三次工业革命:机械化、电气化、数字化 1.3. 中国正在经历着第四次工业革命:智能化、生态化、拟人化 1.4 国产替代:国…...

人脸修复祛马赛克算法CodeFormer——C++与Python模型部署

一、人脸修复算法 1.算法简介 CodeFormer是一种基于AI技术深度学习的人脸复原模型,由南洋理工大学和商汤科技联合研究中心联合开发,它能够接收模糊或马赛克图像作为输入,并生成更清晰的原始图像。算法源码地址:https://github.c…...

linux入门到精通-第三章-vi(vim)编辑器

目录 文本编辑器gedit介绍vi(vim)命令模式命令模式编辑模式末行模式 帮助教程保存文件切换到编辑模式光标移动(命令模式下)复制粘贴删除撤销恢复保存退出查找替换可视模式替换模式分屏其他用法配置文件 文本编辑器 gedit介绍 gedit是一个GNOME桌面环境下兼容UTF-8的文本编辑器…...

Mybatis面试题(三)

文章目录 前言一、Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签?二、当实体类中的属性名和表中的字段名不一样,如果将查询的结果封装到指定 pojo?三、模糊查询 like 语句该怎么写四、…...

Qt扩展-KDDockWidgets 简介及配置

Qt扩展-KDDockWidgets 简介及配置] 一、概述二、编译 KDDockWidgets 库1. Cmake Gui 中选择源文件和编译后的路径2. 点击Config,配置好编译器3. 点击Generate4. 在存放编译的文件夹输入如下命令开始编译 三、qmake 配置 一、概述 kdockwidgets是一个由KDAB组织编写…...

Vue3搭配Element Plus 实现候选搜索框效果

直接上代码 <el-col :span"14" class"ipt-col"><el-input v-model"projectName" class"w-50 m-2" input"inputChange" focus"inputFocusFn" blur"inputBlurFn" placeholder"请输入项目名…...

进程间的通信方式

文章目录 1.简单介绍2.管道2.1管道的基础概念**管道读写规则**:**管道特点** 2.2匿名管道匿名管道父子进程间通信的经典案例&#xff1a; 2.3命名管道基本概念:命名管道的创建&#xff1a;命名管道的打开规则&#xff1a;匿名管道与普通管道的区别**例子&#xff1a;用命名管道…...

分类预测 | Matlab实现基于MIC-BP-Adaboost最大互信息系数数据特征选择算法结合Adaboost-BP神经网络的数据分类预测

分类预测 | Matlab实现基于MIC-BP-Adaboost最大互信息系数数据特征选择算法结合Adaboost-BP神经网络的数据分类预测 目录 分类预测 | Matlab实现基于MIC-BP-Adaboost最大互信息系数数据特征选择算法结合Adaboost-BP神经网络的数据分类预测效果一览基本介绍研究内容程序设计参考…...

phpcms v9对联广告关闭左侧广告

修改目录“\caches\poster_js”下的文件“53.js”&#xff0c;修改函数“showADContent()” 将代码&#xff1a; str "<div idPCMSAD_"this.PosID"_"i" style"align_b":"x"px;top:"y"px;width:"this.Width&…...

7.2.4 【MySQL】匹配范围值

回头看我们 idx_name_birthday_phone_number 索引的 B 树示意图&#xff0c;所有记录都是按照索引列的值从小到大的顺序排好序的&#xff0c;所以这极大的方便我们查找索引列的值在某个范围内的记录。比方说下边这个查询语句&#xff1a; SELECT * FROM person_info WHERE nam…...

1400*C. No Prime Differences(找规律数学)

解析&#xff1a; 由于 1 不是质数&#xff0c;所以我们令每一行的数都相差 1 对于行间&#xff0c;分为 n、m之中有存在偶数和都为奇数两种情况。 如果n、m存在偶数&#xff0c;假设m为偶数。 如果都为奇数&#xff0c;则&#xff1a; #include<bits/stdc.h> using name…...

做电子商务系统网站/晋城今日头条新闻

这个问题严格来说是肯定有的&#xff0c;kafka只能保证分区内的有序性。 下面是kafka作者Jay Kreps的blog中介绍kafka设计思想的一段话。 Each partition is a totally ordered log, but there is no global ordering between partitions (other than perhaps some wall-clock…...

用ps可以做网站吗/游戏推广员如何推广引流

1.联合结果集 (1) 简单的结果集联合 select FNumber,FName,Fage from T_Employee\ union select FidCardNumber,FName,Fage from T_Employee (2) 查询的基本原则是&#xff1a;每个结果集必须有相同的列数&#xff0c;没个结果集的列必须类型相同。 select FNumber,FName,Fage,…...

页面设计网站素材/网站关键词搜索排名

这里介绍的是mt2523平台FAQ解决方案资料&#xff0c;需要mt2523相关技术资料或方案开发&#xff0c;可到一牛网论坛 mt2523 [GPS] 如何在MT2523上测试cold/warm/hot start TTFF&#xff1f; 1. 编译GNSS_get_location project&#xff0c;并且烧录image到设备 2. 将设备UART…...

北京市住房和城乡建设委网站/他达拉非什么是

发工资咯&#xff1a; Time Limit: 2000/1000ms (Java/Others) Problem Description: 作为广财大的老师&#xff0c;最盼望的日子就是每月的8号了&#xff0c;因为这一天是发工资的日子&#xff0c;养家糊口就靠它了&#xff0c;呵呵 但是对于学校财务处的工作人员来说&#xf…...

建设wap手机网站制作/北京seo优化方案

使用SMB登入扫描器对大量主机的用户名和口令进行猜解&#xff0c;不过扫描动静很大&#xff0c;容易被察觉&#xff0c;而且每一次登入尝试都会被扫描的主机系统日志记录下来&#xff0c;留下痕迹不建议使用。 实例 第一步&#xff1a; msf > use auxiliary/scanner/smb/smb…...

邢台市政/外贸seo推广

开头 大家好&#xff0c;我是G哥&#xff0c;目前人在荆州办事&#xff0c;但是干货还是要安排上&#xff01; 国外有一个爆火的开发人员学习路线&#xff0c;目前已经在 Github收获了 131 k star&#xff0c;Star 数量在 Github 所有仓库中排名第 9 。这个仓库有多火就不用说…...