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

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

👉make项目管理器的基础👈


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


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


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


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


👉makefile的基本结构👈


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

目标体:make 项目管理器生成的目标文件或者可执行文件。

依赖文件:make 项目管理器创建目标体所需要的文件,通常是 C 语言的源文件和头文件等。

相关操作命令:make 项目管理器使用依赖文件来创建目标体所需要的命令,这些操作命令必须以制表符(Tab)开头。

makefile 存在的意义就是为了构建项目。

注:Makefile 也是可以的。


Makefile 文件样例


616edd32729e45a992f82119ff0691a6.png

0ef7660adc434cc1ae56ff2461e1a18b.png

make clean 清理文件

67baa4ad904d49cbbf4026bf5e03e248.png


7ada998ceb3a4142875af02aba0683b0.png


02d1cb4972a240f0804920d735bc7969.png


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


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


1e9cc7fc9e9447ffb77ad87b06414448.png


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

bcd771712bfe49fab0132b773d1918af.png4dd958c9f5024aa3b053784439041f7d.png


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

e243f1247774424caccee8df7baa6ab7.png

4c3d710db84949bb8b212464d95c9d5d.png

ac05fdadbe0f4d03b0099dfe0f9bdbf7.png


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


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

d1cd4a2c96954dbea4078ab95649a2ff.png

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


1f7f099df6fd4132827c9a2103f3c8f9.png


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


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


cf842cdb328e429aa01fd0e7011d75f7.png

makefile 的依赖关系


6d71b6e9b4624755b30d578ee8e45ef9.png


:不建议这么来写 makefile 文件。


👉小程序进度条👈


缓冲区问题


sleep 函数原型


9b6cd007c79d4370adc279cbd2fddb01.png


1de309d88e5b423387aeed670f702b44.png

dd9038654c97486bad563548d6bb9bfe.png


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

e92792616cc849bd811932a516a805cb.png


d486e2e79fad4bbc9ddc0caeb5ee8001.png

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


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


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


3f7bee8790874581a021f158f2e90ce0.png


11e1b58f6f19498c9a5912903c6a6dcd.png


cc976a08d3544ae9a3bd5977cf1abc0a.png


那想问大家一个问题:为什么第一个例子中加了个'\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;
}


进度条程序


dc76a777f5e54c32b6c891cff1399989.png


注:头文件不用在 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;
}


颜色控制格式


1c054662eb6f4579a1d95f65f325ab1e.png

dc3bef81490a4a00be8dab70c8aa74c9.png



👉总结👈


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


















相关文章
|
Web App开发 编解码 Linux
使用Selenium自动化测试解决报告生成失败问题及Linux部署指南
这篇文章介绍了使用Selenium自动化测试解决报告生成失败问题的方法,包括Linux环境下的部署指南和代码实现。
233 1
使用Selenium自动化测试解决报告生成失败问题及Linux部署指南
|
存储 监控 Linux
|
小程序
【亲测有效】支持横竖屏 微信小程序video禁止进度条拖动,微信小程序遮罩进度条,
【亲测有效】支持横竖屏 微信小程序video禁止进度条拖动,微信小程序遮罩进度条,
488 1
【亲测有效】支持横竖屏 微信小程序video禁止进度条拖动,微信小程序遮罩进度条,
|
存储 运维 监控
|
Shell Linux
Linux Shell 脚本入门教程:开启你的自动化之旅
Shell是一种计算机程序,它充当了用户与操作系统之间的接口。在Linux系统中,Shell允许用户通过命令行界面(CLI)来控制计算机。Shell脚本则是一种使用Shell语言编写的脚本,它可以自动执行一系列的命令,帮助用户实现任务自动化,提高工作效率。
290 2
|
关系型数据库 MySQL Shell
【权限提升】Linux系统&环境变量&定时任务&权限配置不当&MDUT自动化
【权限提升】Linux系统&环境变量&定时任务&权限配置不当&MDUT自动化
323 4
|
小程序 Linux C语言
Linux小程序 —— 进度条
Linux小程序 —— 进度条
197 6
|
NoSQL 编译器 Linux
【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用
【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用
344 0
|
1月前
|
数据采集 运维 监控
爬虫与自动化技术深度解析:从数据采集到智能运维的完整实战指南
本文系统解析爬虫与自动化核心技术,涵盖HTTP请求、数据解析、分布式架构及反爬策略,结合Scrapy、Selenium等框架实战,助力构建高效、稳定、合规的数据采集系统。
爬虫与自动化技术深度解析:从数据采集到智能运维的完整实战指南