【Linux】项目自动化构建工具make / Makefile 及进度条小程序

news2025/1/21 4:54:49

​🌠 作者:@阿亮joy.
🎆专栏:《学会Linux》
🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根
在这里插入图片描述

目录

    • 👉make项目管理器的基础👈
    • 👉makefile的基本结构👈
    • 👉小程序进度条👈
      • 缓冲区问题
      • 回车和换行
    • 👉总结👈

👉make项目管理器的基础👈

在实际应用中,一个 C 语言的工程项目常常由多个文件组成,此时为了对多个文件进行管理和处理,可以使用 make 项目管理器。

使用项目管理器的主要目的是用于管理较多的文件。在上一篇博客介绍过 C 语言代码的编译过程分为预处理、编译、汇编和链接,其中编译阶段仅检查语法错误以及函数与变量是否被正确地声明了,在链接阶段则主要完成函数链接和全局变量的链接。因此,那些没有改动的源代码根本不需要重新编译,只要把它们重新链接进去就可以了。这是, make 项目管理器就应运而生了。

实际上,make 项目管理器也就是个“自动编译管理器”。这里的“自动”是指它能够根据文件的时间戳自动发现更新过的文件而减少编译的工作量,同时其通过读入 makefile 文件的内容来执行大量的编译工作。用户只需编写一次简单的编译语句就可以了,所以大大提高了实际项目的工作效率。

注:make 是一个命令,而 makefile 是一个文件。

👉makefile的基本结构👈

makefile 是 make 项目管理器中使用的配置文件,其通常有一下几个部分组成。

  • 目标体:make 项目管理器生成的目标文件或者可执行文件。
  • 依赖文件:make 项目管理器创建目标体所需要的文件,通常是 C 语言的源文件和头文件等。
  • 相关操作命令:make 项目管理器使用依赖文件来创建目标体所需要的命令,这些操作命令必须以制表符(Tab)开头。
  • makefile 存在的意义就是为了构建项目。
  • 注:Makefile 也是可以的。

Makefile 文件样例

在这里插入图片描述
在这里插入图片描述
make clean 清理文件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上图告诉我们,可执行程序 mycode 已经是最新了。为什么会这样呢?系统是如何得知的呢?为了解决这个问题,我们先来想一个问题:如果一份源代码没有任何的修改,该代码是否还需要再编译一次呢?答案是,肯定不需要。

虽然 make 指令连续使用,系统会提示你。但是 make clean 指令连续使用,系统并不会提示任何的信息。

在这里插入图片描述
其实这就是.PHONY的作用所在。被.PHONY关键字修饰的对象是伪目标,伪目标总是会被执行相关操作命令的。其实我们所要生成的目标体,也可以用.PHONY关键字修饰,那么 make 指令就可以被连续执行了。但是通常来说,我们所要生成的目标体是不需要被.PHONY关键字修饰的。

在这里插入图片描述
在这里插入图片描述
那么,我们现在来回答上面的问题:gcc 是如何得知我们的源代码不需要再编译了呢?这就需要涉及文件的三个时间了。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上图所示,我们多次访问 mycode.c 文件,但该文件的访问时间 Access 却没有变化,这是为什么呢?在之前,只要你访问了文件,那么文件访问时间 Access 就会改变。但是现在不会。因为在操作文件的时候,访问文件的操作比较多;如果每访问文件一次,就修改文件的访问时间 Access,那么 Access 时间将会被频繁地修改,这就需要进行更多次的 IO。而且文件的访问时间 Access 也不是特别的重要。所以新的 Linux 系统要求一段时间后访问文件,才会修改文件的访问时间。

知道了文件的三个时间,我们就能回到上面的问题了。第一次编译时,源代码的修改时间肯定是早于可执行程序的修改时间的。如果源代码的修改时间晚于可执行程序的修改时间,那么就需要重新编译源代码,否则不需要编译源代码。

在这里插入图片描述

touch 已经存在的文件 #将文件的时间更新为现在的时间

在这里插入图片描述
那么,.PHONY关键字就是不管源文件和可执行程序的修改时间的新旧,你只要帮我重新编译就行了。

注:makefile 中的第一个目标体,使用 make 命令时可以省略目标体名称。make 命令默认从上到下执行,执行形成一个目标体,形成一个目标体后,后面的相关操作命令便不会执行了。

在这里插入图片描述

makefile 的依赖关系

在这里插入图片描述
注:不建议这么来写 makefile 文件。

👉小程序进度条👈

缓冲区问题

sleep 函数原型
在这里插入图片描述

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

现象:先打印字符串"you can see me...",然后睡了两秒。

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

现象:先睡两秒,再打印字符串"you can see me..."

关于第二个列子的现象,首先执行的一定是 printf 函数,因为我们的代码是顺序结构。先执行 printf 函数不代表数据先显示。所以该现象的解释就是已经执行 printf 函数,只不过该数据没有被立即显示出来。睡完两秒后,数据才被刷新出来。那休眠的期间,printf 函数一定执行完成打印了,那么对应输出的数据在哪里呢?答案是在缓冲区里面!

那如果我们想要 print 函数打印的内容立即显示出来,怎么才能做到呢?答:调用 fflush 函数刷新缓冲区。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
那想问大家一个问题:为什么第一个例子中加了个'\n'就能够马上打印内容呢?其实'\n'是行缓冲,有'\n'的话,就会把一行内容刷新出来,没有就不刷新。

现象:先打印字符串"you can see me...",然后睡了两秒。

回车和换行

  • 回车\r是回到当前行的最开始
  • 换行\n是换到下一行
  • 一般而言,\r\n是回车换行。但在语言层面上,\n就是回车换行

补充知识:显示器为什么能显示各种符号?显示器面板上有各种像素点,那么点亮显示器上对应的像素点就能显示各种符号了。凡是显示到显示器上的东西,都是字符。

倒计时程序

#include <stdio.h>
#include <unistd.h>

int main()
{
    int cnt = 10;
    while(cnt)
    {
        printf("剩余时间:%2d\r",cnt--);	// %2d一次刷新两个字符
        fflush(stdout);	// 刷新缓冲区
        sleep(1);	// 休眠一秒钟
    }
    return 0;
}

进度条程序

在这里插入图片描述

注:头文件不用在 makefile 里写,编译器能够在当前目录下找到。

// makefile文件里的内容,注:-D N=1为命令行参数
ProcessOn:process.c main.c
	gcc process.c main.c -o ProcessOn -D N=1
.PHONY:clean
clean:
	rm -f ProcessOn

// process.h
#pragma once

#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define NUM 101
#define S_NUM 5

extern void  ProncessOn(); //函数的声明

// process.c
#include "process.h"

void ProncessOn() //函数定义
{
    int count = 0;
    char bar[NUM];
    memset(bar, '\0', sizeof(bar));

    //reserve
    const char* lable = "|/-\\";

    // 进度条样式
    char style[S_NUM] = {'+', '#', '>', '-', '.'};
    while(count <= 100)
    {
        printf("\033[42;34m[%-100s][%d%%][%c]\033[0m\r", bar, count, lable[count%4]);  //%-s向左对齐
        fflush(stdout);
        bar[count++] = style[N];
        //sleep(1); //sleep参数的单位为秒,休眠时间太长
        usleep(50000);    //usleep参数的单位为微妙
    }
    printf("\n");
}

// main.c
#include "process.h"

int main()
{
    ProncessOn(); //函数调用
    return 0;
}

颜色控制格式

在这里插入图片描述

在这里插入图片描述

👉总结👈

本篇博客主要讲解 make、makefile 以及 Linux 下的第一个小程序进度条。那么以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以点个三连支持一下!谢谢大家!💖💝❣️

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

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

相关文章

关于对死锁的理解

文章目录什么是死锁&#xff1f;举例理解死锁如何解决死锁锁池与等待池的理解什么是锁池与等待池锁池与等待池的区别两个线程交替执行什么是死锁&#xff1f; 所谓死锁&#xff0c;是指互斥锁标记使用不当造成多个线程&#xff0c;相互持有对方想要申请的资源&#xff0c;不释…

HummerRisk V0.7.0:支持京东云、webhook、PDF下载等

HummerRisk V0.7.0发布&#xff1a;新增京东云支持&#xff0c;系统增加webhook支持&#xff0c;灵活扩展&#xff0c;新增多种页面的PDF下载&#xff0c;新增主机的批量导入和Windows类型主机的检测支持。 感谢社区中小伙伴们的反馈&#xff0c;你们的认可是我们前进的动力。…

四旋翼无人机学习第16节--labview开发allegro的PAD与封装查询工具

文章目录1 前言2 使用展示(有labview软件)2.1 使用界面展示2.2 配置文件展示2.3 封装检索2.4 pad检索2.5 软件退出3 使用展示(无labview软件)4 源文件下载方式1 前言 在学习allegro过程中&#xff0c;设计封装需要先设计组成封装的PAD&#xff0c;也就是使用Padstack Editor工…

Linux学习-93-SELinux安全上下文操作

18.6 SELinux安全上下文查看方法 SELinux 管理过程中&#xff0c;进程是否可以正确地访问文件资源&#xff0c;取决于它们的安全上下文。进程和文件都有自己的安全上下文&#xff0c;SELinux 会为进程和文件添加安全信息标签&#xff0c;比如 SELinux 用户、角色、类型、类别等…

Android设计模式详解之原型模式

前言 原型模式是一个创建型设计模式。 定义&#xff1a;用原型实例指定创建对象的种类&#xff0c;并通过复制这些原型创建新的对象。 使用场景&#xff1a; 类初始化需要消耗非常多的资源&#xff0c;这个资源包括数据、硬件资源&#xff0c;通过原型复制避免这些消耗&…

音质更出色的骨传导耳机,设计也很时尚,南卡Runner CC3上手

这两年我几乎每天都会用耳机&#xff0c;现在耳机的种类也不少&#xff0c;如果是户外健身的话&#xff0c;我觉得骨传导耳机比挂脖式的耳机更好用&#xff0c;这种耳机因为不入耳的使用方式&#xff0c;在我们听音乐的同时&#xff0c;还可以更清晰地感知周围的情况&#xff0…

【Django项目开发】自动生成接口文档(二)

文章目录一、安装第三方库drf-yasg2二、注册到子应用INSTALLED_APPS三、配置路由1、注意四、接口文档中展示详细的文档说明视图类中接口的标准注释五、视图类中自己定义的方法实现接口文档注释1、注意一、安装第三方库drf-yasg2 pip install drf-yasg2二、注册到子应用INSTALL…

新技术不断发展,一个全新的互联网行业的新风口已然来临

拥抱实体经济&#xff0c;绝对是当下互联网玩家们的首要选择。无论是头部的互联网企业来讲&#xff0c;还是新生的互联网玩家而言&#xff0c;它们都不约而同地将关注的焦点聚焦在了这样一个方向上。   透过这一点&#xff0c;我们可以非常明显地感受到&#xff0c;一个全新的…

网络技术展开型介绍(超详细)二

♥️作者&#xff1a;小刘在这里 ♥️每天分享云计算网络运维课堂笔记&#xff0c;疫情之下&#xff0c;你我素未谋面&#xff0c;但你一定要平平安安&#xff0c;一 起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的&#xff0c;绽放&#xff0c;…

MyBatis—MyBatis参数详解

文章目录MyBatis参数详解1、 parameterType2、resultType3、 resultMap结果类型MyBatis获取参数值的两种方式1.配置sql输出日志2.看#{}和${}的输出现象3.#{}的预编译4.sql注入5.什么时候使用${}6.如何选择使用 #{} 和 ${}7.为什么#{}可以预防sql注入—————————————…

Shuffle的作用以及MapReduce的Shuffle过程

Shuffle的设计 为什么需要Shuffle&#xff1f; Shuffle的本质是基于磁盘划分来解决分布式大数据量的全局分组、全局排序、重新分区【增大】 等问题 因为单台机器的资源处理不了分布式大数据量全局分区/排序/分组 所以需要通过Shuffle对每一台机器的数据构建一个Task来做分区的…

通关剑指 Offer——剑指 Offer II 055. 二叉搜索树迭代器

1.题目描述 剑指 Offer II 055. 二叉搜索树迭代器 实现一个二叉搜索树迭代器类BSTIterator &#xff0c;表示一个按中序遍历二叉搜索树&#xff08;BST&#xff09;的迭代器&#xff1a; BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会…

20221221英语学习

今日新词 define v.下定义&#xff1b;确切说明&#xff08;或解释&#xff09;&#xff1b;树立&#xff0c;表明 chemistry n.化学, 物质的化学组成&#xff08;或性质&#xff09; fly v.飞, 飞翔, 航行, &#xff08;乘航空器或航天器&#xff09;航行 forfeit v.&…

港华燃气上线WeOps推动运维效能提升,托举业务智慧运行!

“嘉为蓝鲸WeOps一体化运维平台有效提升了运维工作效率&#xff0c;满足系统安全要求&#xff0c;尤其是补丁安装、巡检自动化、监控告警等功能&#xff0c;为我们节省了运维人力成本和时间成本。” ——来自港华燃气 港华集团介绍&#xff1a; 港华集团为香港中华煤气在内地…

m在LTE-A系统载波聚合下的资源分配算法的matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 载波聚合即CA&#xff0c;是LTE-A中的关键技术。是为满足用户峰值速率和系统容量提升的要求&#xff0c;增加系统传输带宽的技术&#xff0c;通过CA技术&#xff0c;用户最高上网速率可提升到300…

IPv4 和 IPv6 报文格式详解

文章目录1 概述2 报文格式2.1 IPv42.2 IPv62.3 两者区别3 网工软考真题1 概述 2 报文格式 2.1 IPv4 中文名英文名长度 bit&#xff08;位&#xff09;解释版本Version4IP协议版本号&#xff0c;固定为 4首部长度Header Length4数据报首部的总长度。 以 4 Byte&#xff08;字节…

【Java基础知识复盘】Java概述篇

本人知识复盘系列的博客并非全部原创&#xff0c;大部分摘自网络&#xff0c;只是为了记录在自己的博客方便查阅&#xff0c;往后也会陆续在本篇博客更新本人查阅到的新的知识点&#xff0c;望悉知&#xff01; Java概述 何为编程 编程就是让计算机为解决某个问题而使用某种程…

100多条2023年元宇宙统计数据!Hubbleverse替你整理好了!

欢迎来到Hubbleverse &#x1f30d; 关注我们 关注宇宙新鲜事 &#x1f4cc; 预计阅读时长&#xff1a;9分钟 本文仅代表作者个人观点&#xff0c;不代表平台意见&#xff0c;不构成投资建议。 元宇宙最近被评为最热门的新兴技术趋势之一。在过去的几年里&#xff0c;元宇宙…

SpringBoot整合Mybatis之Mapper接口和映射文件

一、什么是MyBatis MyBatis中文网https://mybatis.net.cn/ MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型…

消息中间件执行原理

1 关于消息中间件 1.1 什么是消息中间件&#xff1f; 消息中间件是指在分布式系统中完成消息的发送和接收的基础软件。 消息中间件也可以称消息队列&#xff08;Message Queue / MQ&#xff09;&#xff0c;用高效可靠的消息传递机制进行与平台无关的数据交流&#xff0c;并基…