【Linux】第九站:make和makefile
文章目录
- 一、 Linux项目自动化构建工具make/Makefile
- 1.make/makefile工作现象
- 2.依赖关系与依赖方法
- 3.如何清理
- 4.为什么这里我们需要带上clean
- 5.连续的make
- 6.特殊符号
- 二、Linux下实现一个简单的进度条
- 1.回车换行
- 2.缓冲区
- 3.倒计时的实现
一、 Linux项目自动化构建工具make/Makefile
1.make/makefile工作现象
make/makefile
make是一条指令
makefile是一个当前目录下的文件
他们的用法如下
这样的话,当我们直接输入make的时候自动执行下面的这条语句


如果我们还想要清理的话,我们可以这样做

这样的话,就可以将我们从繁杂的命令中解脱了

在上面的makefile文件中,我们也可以是Makefile文件。
test.exe依赖于test.c
而下面的方法就是依赖方法
下面的clean不依赖于任何方法
2.依赖关系与依赖方法
什么是依赖关系和依赖方法呢?
在下面的例子中
test依赖于test.c生成,下面的一行就是依赖的方法,即生成的具体细节
我们可以将其具体的写的详细一些
如下所示

当我们make的时候

它的执行逻辑是这样的,先去执行第一个依赖关系,但是第一个依赖关系所需要的被依赖的文件不存在,我们继续去找看这个被依赖的文件能否被生成,如此递归下去。最终我们在被依赖的位test.c的时候刚好找到了,停了下来,然后开始不断的往回执行
所以就有了上面的效果
而且即便我们将Makefile里面的内容给乱序了,它依然按照它的标准去找
不影响最终结果


这个过程其实就是makefile的自动化推导
如果我们缺少了其中的一个依赖关系,那么则会直接报错


3.如何清理
上面的依赖关系可以使得我们减少繁琐的命令。仅需一个make即可
那么清理其实也是比较麻烦的一件事情,我们能否去完成呢?当然是可以的

如下就完成了清理工作

这个clean是不需要依赖关系,只需要一个方法即可
4.为什么这里我们需要带上clean
现在的问题是为什么我们执行清理的时候要带上clean呢?而前面那个不需要呢?
其实这个make是默认执行第一个依赖的。而前面连续调用多个依赖是因为要像栈一样的链式调用
我们也可以自己手动去调用它这个第一个依赖

如果我们将clean改为了第一个依赖,那么就会默认执行clean

不过我们还是建议将生成可执行程序的那个依赖放在第一个
5.连续的make
我们现在将我们的makefile文件变为下面的样子

然后当我们连续的make的时候,会显示如下

- 这是为什么呢?
这其实是因为我们的make编译完成之后,如果源代码没有被改变过,那么就不会再次编译了,因为根本没有必要
这里的目的就是为了提高编译效率
- 那么这里是怎么做到呢?
这里一定是源文件形成可执行,先有源文件,才有可执行,一般而言,源文件的最近修改时间比可执行文件要老的
而如果我们更改了源文件,历史上曾经还有可执行,那么源文件的最近修改时间,一定要比可执行程序要新
所以只需要比较,可执行程序的最近修改时间和源文件的最近修改时间,如果.exe新于.c源文件,不需要重新编译;.exe老于.c源文件,需要重新编译
一般而言,.exe == .c的时间是不可能的。
那么如何证明前面所说的
在linux中有一条命令stat
它可以访问文件的一些时间

这里有三个时间
Access : 最近访问时间
比如cat,vim都会去访问。这些都会更改这个时间
Modify : 最近的对文件内容修改的时间
文件 = 文件内容 + 文件属性
change : 最近修改文件属性时间
这三个时间我们也称为ACM时间
这三个时间很有可能是同时修改的
比如当对文件内容修改后,由于访问了,所以Access时间也被修改了,而内容修改必然伴随着文件大小的改变,所以最终文件属性也要被修改,所以最终三个时间都被修改了
比如下面,我们进去修改了一下,就会导致全部时间被修改了

如下是我们修改文件的属性

上面的一切都符合我们的预期
不过在有的linux系统上,我们的access时间不会被修改。
这是因为Access时间更新太频繁了。需要写到磁盘上,由于频繁的访问外设会使得效率大大降低。所以现在的一些linux系统会根据modify和change的修改次数去进行修改,以此减少开销。可以理解为里面有一个计数器的存在,变相的提高效率
如果我们就想要修改,那么我们可以使用touch,touch后面如果跟的是一个不存在的文件名,就会创建一个文件,如果是已经存在的,会将该文件的所有时间全部更新

我们也可以定向的只改变一部分的
这里因为时间也是文件的属性,所以Access会改变后,change也会改变


所以现在我们知道了如何访问时间
不过问题还是之前的要比较两个的时间,他们其实比较的就是Modify时间,即文件内容的最近修改时间
将这些时间转化为时间戳,然后比较时间戳的大小即可
我们可以看到,明显.c文件要老于.exe文件,所以无法再次编译

如果我们使用touch命令强行修改test.c的时间,那么就可以再次编译了

所以上面的过程已经足以证明
make会根据源文件和目标文件的新旧,判定是否需要重新执行依赖关系进行编译
所以make命令并不总是执行编译的!
但是如果我们非要它每次都想要执行,不要管什么时间了,我们可以在makefile文件加上这句话

代表对于test这个依赖也不要管什么时间的问题了,每次都要执行
这个.PHNOY就是伪目标修饰

不过我们这个一般不建议放在编译时候,而是在清理的时候去修饰

修饰以后,这个clean就变成了伪目标,代表每次都执行

6.特殊符号
在makefile中有两个特殊符号

$@指的是冒号左边的那部分
$^指的是冒号右边的那部分
所以我们的这个编译可以改为上面的写法了

不过我们也会发现我们上面的使用make的操作会使得这些命令回显出来,如果我们不想要回显出来,我们可以加上@


二、Linux下实现一个简单的进度条
1.回车换行
回车和换行其实是两个概念
比如说在我们写作文的时候
当我们将一行写完了,如果我们是从第二行的开头写起,这其实叫做回车换行。
如果我们是直接这一行的正下方写起来,这就是换行
所以回车换行是两个动作
即将光标挪到下方是换行,将光标挪到开头这是回车
只不过我们c语言的\n一个就直接代表了回车换行,如果我们拆开用的话,就有他们各自的含义了,这也解释了为什么我们显示器在打印的时候,命名是换行但是确实在新一行的最开头了
即如果我们只想回车的话,那就是\r,如果是回车换行就是\n
2.缓冲区
我们先看如下代码

注意,sleep这个函数的头文件是unistd.h,这个可以在man手册中查找到
这是我们的运行结果,具体的现象是这样的,先打印出hello world,然后停顿两秒钟,然后再显示我们下面的命令行

如果我们将这个代码改为这样子

那么会先执行1还是2呢?
首先肯定是先执行1,因为这是c语言的特性,顺序执行
但是下面是我们的现象,这个现象是先停顿两秒钟,然后hello world和命令行同时出现

那么这是为什么呢?
在我们sleep期间,“hello world”在哪里呢?它一定是被保存起来了
这里其实保存在了缓冲区
这个缓冲区就是由C语言维护的一段内存
这里其实就是因为没有刷因缓冲区才导致的
在C语言中会默认打开标准输入、标准输出(显示器、stdout)、标准错误,三个流
如果我们想要刷新缓冲区,那么就可以刷新输出流即可
下面这个函数可以刷新

所以我们可以将代码改成这样

这样的话,hello world就会立刻出来,然后个等待两秒后,显示命令行

3.倒计时的实现
如果我们的代码是这样的,那么最终的效果是,一次性将987654321全部输出,这是因为,没有刷新缓冲区


但是我们显然不可以直接加上\n,因为这样虽然会刷新缓冲区,但是也换行了。没有倒计时是会换行的
如果我们的代码是这样的

那么最终的效果是这样的,我们也知道这样也是不行的,因为倒计时应该是覆盖原来的位置的

所以我们应该将倒计时写成这样的
这个\r代表回车,即将光标移动到当前行的最开头。而我们加上%-2d的原因是因为10是一个两位数。如果不这样做就会出现10,90,80,70…这种数据,因为它只会覆盖一个数据,我们显示屏打印的只是一个字符一个字符的打印的。10是俩个字符,我们后面只能覆盖一个字符


所以最终,达到了我们的预期了
相关文章:
【Linux】第九站:make和makefile
文章目录 一、 Linux项目自动化构建工具make/Makefile1.make/makefile工作现象2.依赖关系与依赖方法3.如何清理4.为什么这里我们需要带上clean5.连续的make6.特殊符号 二、Linux下实现一个简单的进度条1.回车换行2.缓冲区3.倒计时的实现 一、 Linux项目自动化构建工具make/Make…...
一文了解什么是WebSocket
WebSocket 允许我们创建“实时”应用程序,与传统 API 协议相比,该应用程序速度更快且开销更少。 一、WebSocket 是如何工作的 按照传统的定义,WebSocket是一种双工协议,主要用于客户端-服务器通信通道。它本质上是双向的&…...
redis是什么
redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。和Memcached类似。redis支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。 一、 基本…...
基于深度学习的人脸专注度检测计算系统 - opencv python cnn 计算机竞赛
文章目录 1 前言2 相关技术2.1CNN简介2.2 人脸识别算法2.3专注检测原理2.4 OpenCV 3 功能介绍3.1人脸录入功能3.2 人脸识别3.3 人脸专注度检测3.4 识别记录 4 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于深度学习的人脸专注度…...
跨境电商的新引擎:崛起的网红经济
随着全球数字化时代的崛起,跨境电商成为了国际贸易的新引擎,而在这个巨大的变革浪潮中,网红经济正在崭露头角,成为这一引擎的有力推动者。在这篇文章中,我们将深入探讨网红经济如何催生跨境电商的新动力,以…...
P2006 赵神牛的游戏 python解法
赵神牛的游戏 题目描述 在 DNF 中,赵神牛有一个缔造者,他一共有 k k k 点法力值,一共有 m m m 个技能,每个技能耗费的法力值为 a i a_i ai,可以造成的伤害为 b i b_i bi,而 boss 的体力值为 n n…...
Unity的碰撞检测(六)
温馨提示:本文基于前一篇“Unity的碰撞检测(五)”继续探讨两个游戏对象具备刚体的BodyType均为Dynamic,但是Collision Detection属性不同的碰撞检测,阅读本文则默认已阅读前文。 (一)测试说明 在基于两个游戏对象都具…...
从前序与中序遍历序列构造二叉树
代码如下,开袋即食 class Solution {private Map<Integer,Integer> map;public TreeNode buildTree(int[] preorder, int[] inorder) {map new HashMap<>();for(int i 0;i<preorder.length;i){map.put(inorder[i],i);}return build(preorder,inord…...
antd5上传图片显示405解决
antd5上传图片,默认使用上传方式会调用本地的接口。 405 Method Not Allowed 状态码 405 Method Not Allowed 表明服务器禁止了使用当前 HTTP 方法的请求。 Upload {...props}beforeUpload{(file) > {//自定义上传图片的逻辑//最后返回falsereturn false }} &…...
生成瑞利信道(Python and Matlab)
channel h k h_k hk is modeled as independent Rayleigh fading with average power loss set as 10^−3 Python import numpy as np# Set the parameters average_power_loss 1e-3 # Average power loss (10^(-3)) num_samples 1000 # Number of fading samples to …...
数据结构Demo——简单计算器
简单计算器 一、项目介绍二、技术使用三、具体代码实现1.前端部分2.后端部分 一、项目介绍 本项目实现了一个通过网页访问的简单计算器,它可以对带括号的加减乘除表达式进行计算并将计算结果返回给用户,并且可以对用户输入的表达式进行合法性判断&#…...
java实现多文件打包压缩,导出zip文件
一.实现多文件打包压缩 Testpublic void testZipFile() throws IOException {String filePath "D:\\导出压缩文件.zip";OutputStream outputStream new FileOutputStream(filePath);try (ZipOutputStream zipOutputStream new ZipOutputStream(outputStream)) {//…...
java-枚举类的使用
public enum MyEnum {ONE("一"),TWO("二"),THREE("三");private final String myNum;MyEnum(String myNum) {this.myNum myNum;}public String getMyEnum() {return myNum;} }调用 MyEnum num MyEnum.ONE; System.err.println(num.getMyEnum…...
Vue插槽
插槽的作用就是在组件中的指定位置传入指定的内容 比如我们有两个相同样式的分类栏,但是里面的内容不同,一个是展示图片,一个是展示ul列表: 这样的情况我们就可以使用插槽来实现。 一、默认插槽 (一)指定…...
学习c++的第二天
目录 数据类型 基本数据类型 typedef 声明 枚举类型 类型转换 变量类型 变量定义 变量声明 左值(Lvalues)和右值(Rvalues) 变量作用域 数据类型 基本数据类型 C 为程序员提供了种类丰富的内置数据类型和用户自定义的数…...
Android NDK开发详解之调试和性能分析的系统跟踪概览
Android NDK开发详解之调试和性能分析的系统跟踪概览 系统跟踪指南 “系统跟踪”就是记录短时间内的设备活动。系统跟踪会生成跟踪文件,该文件可用于生成系统报告。此报告有助于您了解如何最有效地提升应用或游戏的性能。 有关进行跟踪和性能分析的全面介绍&#x…...
AD9371 官方例程HDL JESD204B相关IP端口信号
AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 : AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射: AD9371 官方例程之 tx_jesd 与 xcvr接口映射 AD9371 官方例程 时钟间的关系与生成 : AD9371 官方…...
蓝牙服务:优化体验,提高连接效率
文章目录 1. 对蓝牙连接进行优化2. 设备配对的缓存机制3. 优化蓝牙连接的稳定性 蓝牙技术已经成为我们生活中不可或缺的一部分,我们使用它进行音频传输、数据传输、设备连接等等。然而,有时蓝牙连接会让用户感到非常困扰,比如连接速度缓慢、连…...
SSM校园设备管信息管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目
选题理由 随着计算机网络及多媒体技术的广泛应用,互联网已成为高校办学的基础设施和必备条件,基于互联网的高校信息管理越来越综合化,越来越多的教学管理、行政管理工作将架构在互联网上,互联网正在变为学校实施教学、科研和管理…...
iOS的应用生命周期以及应用界面
在iOS的原生开发中,我们需要特别关注两个东西:AppDelegate和ViewController。我们主要的编码工作就是在AppDelegate和ViewControlle这两个类中进行的。它们的类图如下图所示: AppDelegate是应用程序委托对象,它继承了UIResponder类…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
RKNN开发环境搭建2-RKNN Model Zoo 环境搭建
目录 1.简介2.环境搭建2.1 启动 docker 环境2.2 安装依赖工具2.3 下载 RKNN Model Zoo2.4 RKNN模型转化2.5编译C++1.简介 RKNN Model Zoo基于 RKNPU SDK 工具链开发, 提供了目前主流算法的部署例程. 例程包含导出RKNN模型, 使用 Python API, CAPI 推理 RKNN 模型的流程. 本…...
深入理解 C++ 左值右值、std::move 与函数重载中的参数传递
在 C 编程中,左值和右值的概念以及std::move的使用,常常让开发者感到困惑。特别是在函数重载场景下,如何合理利用这些特性来优化代码性能、确保语义正确,更是一个值得深入探讨的话题。 在开始之前,先提出几个问题&…...
智能体革命:企业如何构建自主决策的AI代理?
OpenAI智能代理构建实用指南详解 随着大型语言模型(LLM)在推理、多模态理解和工具调用能力上的进步,智能代理(Agents)成为自动化领域的新突破。与传统软件仅帮助用户自动化流程不同,智能代理能够自主执行工…...
CentOS 7.9安装Nginx1.24.0时报 checking for LuaJIT 2.x ... not found
Nginx1.24编译时,报LuaJIT2.x错误, configuring additional modules adding module in /www/server/nginx/src/ngx_devel_kit ngx_devel_kit was configured adding module in /www/server/nginx/src/lua_nginx_module checking for LuaJIT 2.x ... not…...
c++算法学习3——深度优先搜索
一、深度优先搜索的核心概念 DFS算法是一种通过递归或栈实现的"一条路走到底"的搜索策略,其核心思想是: 深度优先:从起点出发,选择一个方向探索到底,直到无路可走 回溯机制:遇到死路时返回最近…...

