• Linux项目自动化构建工具-make/Makefile


    大家好!这篇文章主要讲Linux的最后一个工具,并说一个进度条小程序。
    在这里插入图片描述

    1. Linux项目自动化构建工具-make/Makefile

    1.1 背景知识

    以前在vs下,我们创建一个项目,我们编辑,运行就行了。我们不需要考虑项目结构,比如:多文件时,.h,.c,.cpp,我们先编译哪一个文件呢?链接需要哪些库?库和头文件等在哪里去找?等等一些问题我们都不需要考虑。那么在Linux下,有没有什么方式帮助我们解决这些问题呢?
    而makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

    1.2 什么是make/Makefile

    makefile是一个文件,make是一个命令工具,是一个解释makefile中指令的命令工具

    1.3 如何使用make/Makefile

    首先我们创建一个文件,在里面编写一些代码:
    在这里插入图片描述
    然后我们需要在当前项目目录下,创建一个Makefile/makefile文件(大小写都行)。
    在这里插入图片描述
    现在我们就需要在这个Makefile里写一些依赖关系和依赖方法
    为什么要写依赖关系和依赖方法呢?因为我们的目的是:形成可执行程序。而形成可执行程序它的依赖关系是:它的源文件。它的依赖方法是:gcc

    1.3.1 代码演示

    第一步:可执行程序名:源文件。表明它的依赖关系。
    在这里插入图片描述
    前面是编译后的名字,后面是需要的源文件。
    第二步:按一下Tab键。然后写出gcc的编译方式
    在这里插入图片描述
    在这里,依赖方法在依赖关系的后面,并且必须以Tab开头
    写完后保存退出。此时我们在使用make命令:
    在这里插入图片描述
    我们可以看到它生成一个test可执行程序,并且可以正常运行。
    这个过程在vs上叫做生成解决方案,那么清理解决方案怎么写呢?有的人会说用rm,这是不行的。因为用rm,可能会把源文件删除。所以,我们应该这样做:
    在这里插入图片描述
    .PHONY的意思:是Makefile中的一个关键字,后面跟着的叫做伪目标
    伪目标也是目标,它也有目标关系和目标方法

    写好之后,我们保存一下。然后用命令——“make clean”,以此来清除所有的目标文件,以便重新编译
    在这里插入图片描述
    这里我们还需要解释一下.PHONY关键字。clean被.PHONY修饰时,表明总是被执行的
    这是什么意思呢?我用代码演示一下什么是不是总被执行的
    在这里插入图片描述
    从这里我们可以看到make执行test的依赖方法时,只能执行一次。下次再使用make,就不会再形成新的test了。这个就叫做不是总被执行的。不被执行的原因是:认为test已经是最新的文件,不需要再次执行,浪费资源。

    那么现在我们再把test目标被.PHONY修饰,看有什么变化。
    在这里插入图片描述
    在这里插入图片描述
    可以看到,它现在是可以被重复执行的。所以总是被执行的意思是:无论目标文件是否新旧,照样可以直接执行

    那么makefile是如何识别我的exe/bin是新的还是旧的呢?
    在Linux下有一个命令可以查看文件的时间。
    在这里插入图片描述
    在Linux下有三种时间,acm时间。
    Access的意思是:进入,访问文件的时间。
    Modify的意思是:修改文件内容的时间。
    Change的意思是:修改文件属性的时间。

    在这里插入图片描述
    从上图我们可以看到,文件的属性更改。它的change时间也发生变化,其它的没有发生变化。

    我们再举一个例子:
    在这里插入图片描述
    我们进去修改了文件的内容,所以它的Access的时间和Modify发生了变化。为什么它的Change的时间也发生了变化呢?原因是:修改了文件内容,它的大小也可能发生变化,所以它的属性发生了变化

    所以现在我们就可以讲解一下makefile是如何识别我的exe/bin是新的还是旧的。
    原因如下
    我们知道源文件的Modify时间一定是比可执行程序的Modify时间早,如果我们对源文件进行修改,它的Modify时间会修改,就会在可执行程序的Modify时间后面。所以,根据对比源文件和可执行程序的最近修改时间,评估要不要重新生成

    那么还有一个问题:为什么make会自动执行test的依赖方法,而不自动执行clean的依赖方法呢?
    原因是:makefile默认只会形成第一个目标文件,执行该依赖关系的依赖方法。
    我们给它们掉换一下位置:
    在这里插入图片描述
    在这里插入图片描述
    可以发现make执行的就是clean的依赖方法。

    1.3.2 多文件的Makefile演示

    这个我们现阶段只需要了解一下,见一下就行了。
    在这里插入图片描述
    首先,我们创建两个源文件和一个头文件。
    在这里插入图片描述
    打开头文件,写一个test函数声明。
    在这里插入图片描述
    然后打开test.c完成函数的实现。
    在这里插入图片描述
    在main.c文件中调用这个函数。
    写好之后。如果我们想用这两个源文件(.c)去生成两个目标文件(.o),然后去链接库形成可执行程序该怎么写呢?
    在这里插入图片描述
    我们创建一个makefile,然后vim。
    在这里插入图片描述
    这里我们是没有main.o和test.o的,但是makefile会自动向下寻找执行依赖关系和依赖方法。
    在这里插入图片描述
    在这里我们要注意一点:第二种依赖方法我们没有写-o。在makefile中,我们不写,它会默认生成同名.o文件。这两种写法都可。

    然后,我们把makefile文件写完:
    在这里插入图片描述
    这里的意思是:* 号是通配符,它会清理所有的.o文件和可执行程序test。注意:*号和.o之间没有空格,一定要记住!!!
    在这里插入图片描述
    在这里插入图片描述

    2. Linux第一个小程序-进度条

    2.1 缓冲区

    在写这个小程序之前,我们需要一些准备知识。
    在这里插入图片描述
    在Linux下有一个sleep函数,是让程序休眠的。它的单位是秒,对应的头文件是< unistd >。在Windows下有一个Sleep函数,它的单位是毫秒。

    那么现在有一个问题:这个程序是先执行第一步还是第二步呢?
    在这里插入图片描述
    从运行结果我们可以看到,它是先执行了第一步然后才执行第二步。
    在这里插入图片描述
    那么我们把\n去掉是什么情况呢?
    在这里插入图片描述
    在这里插入图片描述
    从这个运行情况来看。可能有的同学会认为是先执行了第二步,再执行的第一步。其实并不是这样的,学过C语言的我们知道程序是从上往下编译的。所以还是先执行的第一步,然后执行的第二步。

    那么为什么这里的hello world数据没有在睡眠前打印出来,也没在睡眠后打印出来,而是在程序结束时才打印出来呢原因是:数据在缓冲区里
    那么这里是缓冲区指的是哪里的缓冲区呢?
    这个问题,我们暂时是回答不出来的。以后再说。不过缓冲区其实就是一段内存空间。所以hello world数据就在这个内存空间里。而这个内存空间有一个刷新策略:立马将内存中的空间显示出来。而刷新策略中有一个叫做行刷新

    现在有一个问题:不想用\n,如何把数据立马刷新出来?
    我们可以用一个函数来强制刷新:
    在这里插入图片描述
    在C语言的文件操作那篇文章其实有提到过。大家可以去看一下那篇文章。
    快速通道:C语言文件操作
    大家再去实验一下就可以看出结果了。

    2.2 回车和换行

    用严格定义来说:
    回车:将光标回到当前行的最开始。
    换行:新起一行,但和上行的列不变。

    而我们平时口头说的"回车",“换行”。其实是二者的结合。
    在Linux下\n就是二者的结合,而单单的回车是\r

    现在我们就写一个倒计时打印的程序:
    在这里插入图片描述
    在这里我们写的是回车,记住一定要刷新缓冲区不然不会立即显示。
    演示这里不好演示,大家可以自己试一下。

    2.3 代码演示

    首先,我们创建一个目录,然后创建一些文件:
    在这里插入图片描述
    划黄线的大家可能有些疑惑,这个我们前面的说过。
    > 是定向输出到文件,如果文件不存在,就创建文件。如果文件存在,就将其清空
    在这里插入图片描述
    然后,我们进入Makefile先把基本的指令写好。
    在这里插入图片描述
    然后开始写实现进度条的函数。我们知道一般的进度条它是从0到100,所以会循环101次。然后我们可以定义一个字符数组,按字符串来打印。第一次打印0个字符,第二次打印1个字符… …
    在这里插入图片描述
    这里的usleep也是一个睡眠函数。单位是微秒
    在这里插入图片描述
    但是我们打印出来是这样的一个结果。
    在这里插入图片描述
    因为我们是\r,光标还是在最左侧,所以当我们打印完了之后,命令行提示符会把前面的字符给覆盖了。所以这里我们需要在循环结束后再加一个\n。
    在这里插入图片描述
    结果就是这个样子了:
    在这里插入图片描述
    如果我们想加一个%多少的数字呢?我们可以这样:%%就是一个%
    在这里插入图片描述
    运行情况如下:
    在这里插入图片描述
    如果大家演示的话,你能发现后面的]号是跟着#号一起动的,如果我们想预留空间的话。在C语言有专门的方式。
    在这里插入图片描述
    运行情况如下:
    在这里插入图片描述
    在这里,我们还可以增加一个动态的效果。就是类似一个旋转符合,第一次打印|,第二次打印/,第三次打印-,第四次打印\。
    在这里插入图片描述
    运行情况如下:
    在这里插入图片描述
    在C语言中,我们还能输出时带有颜色:
    在这里插入图片描述
    举个例子:
    在这里插入图片描述
    在这里插入图片描述
    剩下的大家可以自己发挥,写出优美的进度条吧!
    在这里插入图片描述

  • 相关阅读:
    Slf4j打印异常的堆栈信息
    java基于ssm+vue二手手机销售平台
    Git-03-分支操作
    eval()方法字符串转对象; 分别取对象属性名和属性的方法
    【云原生K8S】Kubernetes资源管理
    RISC-V (五)上下文切换和协作式多任务
    从此 Typora 代码块有了颜色
    微服务项目:尚融宝(38)(核心业务流程:申请借款额度(1))
    总结:大数据服务
    @keyframes css3动画技巧与代码实例
  • 原文地址:https://blog.csdn.net/qq_52154068/article/details/126066869