0


【Linux系统】第六篇:Linux的自动化构建工具——make/makefile

文章目录

一、make和makefile的区分

make是一个命令,makefile是一个文件

二、依赖关系和依赖方法

依赖关系: 依赖关系指明了两个文件之间的依赖性。例如test.o文件的生成要依赖test.s文件

依赖方法: 依赖方法就是我依赖这个关系需要做什么。例如test.o形成需要test.s进行汇编,即gcc  -c  test.s  -o  test.o

三、make/Makefile的使用

#include<stdio.h>intmain(){printf("hello Makefile\n");return0;}

如上一串代码,如果我们需要在Linux中对其进行编写,生成可执行程序,以往我们需要敲一长串指令

gcc test.c -o test

,当我们学会makefile之后我们就不在需要敲这一长串指令了,只需要一个make指令即可。

1、makefile的编写

  1. 首先在源文件的目录下创建一个makefile或者Makefile文件(首字母可以大写,其他的不行)在这里插入图片描述
  2. 然后打开makefile文件,进行规则的编辑:在这里插入图片描述在这里插入图片描述 第一行中冒号左边的mycode是目标文件,该目标文件依赖于冒号右边的mycode.c而产生,所以第一行写的是依赖关系,第二行必须使用一个tab键之后写上两个文件的依赖方法。
  3. 接着然后直接使用make命令即可。如下:在这里插入图片描述 这样就形成了我们所需要的可执行程序文件。

2、临时文件的清理

完成上面的编写后我们就可以生成需要的可执行文件,但若我们需要清理生成的临时可执行程序文件,则可以进行如下编写:
在这里插入图片描述

.PHONY

表示被该关键字修饰的对象是一个伪目标。(该伪目标总是可被执行)

使用: 如下图:
在这里插入图片描述

疑问: 为什么编译的时候直接使用make就可以了,而进行清理需要加上clean呢?

其实make后面也可以接mycod,只不过make默认对makefile文件中的第一个目标文件可以省略名称

3、makefile的工作原理

  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 默认情况下Makefile的第一个目标为终极目标。   即默认情况下,makefile只形成一个可执行目标文件,形成之后,后续的依赖关系和依赖方法不再执行(默认从上到下扫描总是执行一个,默认不指明情况下,只形成第一个)
  3. all:Makefile文件默认只生成第一个目标文件即完成编译,但是我们可以通过all 指定所需要生成的目标文件。
  4. 若需要完成指定的功能,只需在make命令后加上自己写入makefile中的命令

4、文件的三个时间

上方我们提到,

.PHONY

是修饰伪目标的,该伪目标总是可被执行。什么意思呢?如图:
在这里插入图片描述
进行第一次make的时候,我们可以进行编译生成可执行程序文件,但当我们进行第二次make的时候就不可以了而且提示我们说mycode是最新的,而我们由

.PHONY

修饰的

clean

就可以总是被执行的。

那为什么gcc编译知道mycode是最新的呢?接下来我们认识一下文件的三个时间:

[wyt@VM-20-4-centos lesson3]$ stat mycode.c
  File: ‘mycode.c’
  Size:81            Blocks:8          IO Block:4096   regular file
Device: fd01h/64769d    Inode:794005      Links:1
Access:(0664/-rw-rw-r--)  Uid:(1001/     wyt)   Gid:(1001/     wyt)
Access:2023-02-1117:08:52.893235379+0800//文件最近访问时间
Modify:2023-02-0413:21:39.841893206+0800//内容被修改时间
Change:2023-02-0413:21:39.841893206+0800//属性被修改时间
 Birth:-

4.1、Access:最近一次访问文件的时间

读取文件内容,修改文件内容,Access都会发生变化.

修改文件内容,Access的时间会立即更新;但是读文件操作,不会立即更新。
在这里插入图片描述
在这里插入图片描述

我们读取文件或者查看文件,如cat、find等操作,这些都属于高频操作,如果我们频繁使用这些命令,可能会频繁更新Access时间,导致Linux的处理速度下降

在较新的Linux内核中,这个问题被优化了,对文件进行读操作以后,Access时间不会立即更新,经过一定的时间间隔,OS才会自动进行更新时间

4.2、Modify:最近一次修改文件内容的时间

只要是修改文件内容,Modify的时间都会被更新,这个被视为低频操作,所以一般修改文件内容以后,会立即刷新。

但是修改文件内容,有可能会顺带着修改文件属性,比如新增内容会改变文件大小(文件大小属于文件属性)
在这里插入图片描述

4.3、Change:最近一次修改文件属性的时间

修改文件属性也被视为低频操作,修改文件属性会立即更新Change的时间

只是单纯的修改文件属性,不会影响到Modify和Access的时间

在这里插入图片描述

4.4、‘xxx’ is up to date问题

所以我们在上面遇到的make问题就很好解答了。
在这里插入图片描述
第一次make后,生成一个可执行目标文件,再之后make时,需要比较可执行目标文件

mycode

和源文件

mycode.c

的Modify的时间

在这里插入图片描述

可执行目标文件

mycode

的modify的时间比源文件

mycode.c

的modify时间新,所以不可以再进行编译了。

当我们的源文件时间进行修改后,我们又可以再次进行make编译了
在这里插入图片描述

总结:

当源文件的Modify时间比目标文件的Modify时间新时,才可以再次利用make进行编译。

四、makefile的推导规则

makefile文件在扫描时,是从上往下进行扫描的,比如下图:
在这里插入图片描述

make会一层一层地去找文件的依赖关系,直到最后编译出第一个目标文件。

拿上图举例:
在这里插入图片描述
如上,最后找到mycode.i目标文件后,就会在一层一层的往上,最后形成一个可执行的目标文件。

上述的推导过程就如同一个栈结构,先进后出。

五、进度条小程序

1、行缓冲区问题

先看下面两串代码执行的现象:
代码1:
在这里插入图片描述
现象:
请添加图片描述

代码2:
在这里插入图片描述

现象:

请添加图片描述

两串代码的区别仅仅就是代码1有

\n

,而代码2没有那为什么会造成不同的现象呢?

首先我们要明确一点就是,代码是顺序结构的,所以他是从上往下执行,所以先执行printf在执行sleep。至于为什么会有不同的现象,如下:

,这里就有一个行缓冲区的概念在这里。对于C语言级别的缓冲区而言,任何字符串都会先保存在这个缓冲区里面,等待刷新在显示屏上。但是显示器刷新是属于行刷新,就是遇到‘\n’就进行刷新。所以现在我们就理解了,代码2中没有’\n’,要打印的字符串一直保存在了C语言级别的缓冲区,只有程序运行快结束是才会把这些字符串刷新在屏幕上。

那我们该如何将代码2的printf打印立马显示到显示器上呢?

#include<stdio.h>#include<unistd.h>intmain(){printf("hello LInux");fflush(stdout);//fflush会立即刷新缓冲区sleep(2);return0;}

2、回车换行(\r与\n)

理解:

  • \r:回车。回到当前行的最开始
  • \n:换行。换到下一行,但列不变

在语言层面:

\n

就是回车换行

3、倒计时功能

#include<stdio.h>#include<unistd.h>intmain(){int cnt=10;while(cnt){printf("%2d\r",cnt);//2d控制刷新两位,\r表示回车                                                                                   fflush(stdout);//手动刷新缓冲区   sleep(1);--cnt;}return0;}

3、进度条的实现

多文件形式:
在这里插入图片描述

头文件

process.h
#pragmaonce#include<stdio.h>#include<string.h>#include<unistd.h>#defineNUM101externvoidProncessOn();//函数的声明 

源文件

process.c
#include"process.h"voidProncessOn()//函数的定义{int cnt =0;char bar[NUM];memset(bar,'\0',sizeof(bar));constchar*lable ="|\\-/";while(cnt <=100){printf("[%-100s][%d%%][%c]\r", bar, cnt, lable[cnt%4]);fflush(stdout);//立即打印
        bar[cnt++]='#';//sleep(1);//单位是秒,太慢了usleep(50000);//微妙  5S/100 == 0.05S == 50000}printf("\n");}

效果如下:

请添加图片描述

标签: linux 自动化 运维

本文转载自: https://blog.csdn.net/m0_58124165/article/details/128880757
版权归原作者 Clumsy、笨拙 所有, 如有侵权,请联系我们删除。

“【Linux系统】第六篇:Linux的自动化构建工具——make/makefile”的评论:

还没有评论