Linux之make和makefile及其拓展

make和makefile

基础知识

在一个大型工程项目中,通常存在多个源文件,那么这些文件哪些是要被先编译,哪些后编译,或者说某些文可能会重复编译。makefile制定了一系列的规则来指定。

makefile带来的好处就是自动化编译,一旦写好这个文件,只需要一条make命令,整个工程就能自动完成编译,极大的提高了效率。

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

make/makefile的使用

系统本身并没有makefile,需要我们自己创建makefile文件(也可以叫Makefile)。该文件中主要写依赖关系和依赖方法:

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

注意:在这里插入图片描述

有了makefile文件,make命令才能派上用场,保存退出makefile文件后在终端输入make命令就能完成自动编译

在这里插入图片描述

这个时候你可能有一个疑问:为什么只执行了第一条指令没有执行clean的指令?

makefile默认只执行第一个依赖方法,如果你要执行clean可以使用make+依赖关系

在这里插入图片描述

那么为什么要有依赖关系和依赖方法?

我们来感性认识一下:设定一个这样的情景,现在是月底了,你兜里没钱了,所以你决定打电话给你爸要钱

如果你给你爸打电话只说:我是你儿子(表明依赖关系),你爸很难清楚你要干啥

你要想完成目标,你应该说:我是你儿子(依赖关系),我没钱了,打钱(依赖方法)

同理,对于makefile来说,基于mytest.c生成mytest文件(依赖关系),需要执行gcc mytest.c -o mytest命令(依赖方法)

伪目标

在这里插入图片描述

为什么多次make会失败,但是多次make clean却能一直成功?

观察makefile文件发现:clean用.PHONY修饰了,而mytest没有

在这里插入图片描述

.PHONY所修饰的就是伪目标,而伪目标可以不遵守规则,因此可以多次反复执行。

三个时间

不加伪目标make无法多次执行的原因在于目标文件没有更新,不用重新编译(在一些大型工程项目中,仅是编译的过程就可能要耗费数十分钟甚至几小时)

在这里插入图片描述

那么它怎么知道我没有更新目标文件呢?这里就依赖于文件属性中的时间了

在这里插入图片描述

对于mytest来说,一定是先有的mytest.c才有的mytest,所以如果mytest的时间modify时间比mytest.c的modify时间要早说明近期对mytest.c文件进行过修改,也就需要重新编译,此时就可以再次执行make

在这里插入图片描述

拓展

Access是访问时间,Modify是文件内容更改时间,Change是文件属性更改时间。

但是modify时间更新change时间也会更新,因为内容变了文件大小就会变,文件大小也是一种属性。
在这里插入图片描述

但是此时有一个奇怪的问题产生了,我刚刚修改文件内容时用vim打开了mytest.c文件,明明访问了mytest.c文件啊,为什么Access时间没有更新?

首先要清楚,我们访问一个文件不一定修改这个文件,但是我们修改这个文件一定要访问这个文件。

意思是访问文件的频率可能会很高,如果每访问一次就修改一次访问时间,就会进行大量多余的IO

所以设计者决定采用,多长时间后访问或者连续访问多少次以后再更新访问时间

推导规则

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

调用make指令后makefile文件内依赖方法的执行顺序和我的写法正好相反,这是为什么?
在这里插入图片描述

在make推导的时候会根据依赖关系而推导,从上到下,当依赖文件列表不存在会继续根据依赖文件列表所对应的项而继续。但这样是将简单的过程复杂化了,平时没必要这样写,这里也只是做讲解用。

小程序进度条

缓冲区问题

在这里插入图片描述

首先明确一件事,是printf语句先执行还是sleep先执行?

很明显,该代码中没有任何循环或者选择结构,也就是说代码是从上往下执行的,先执行printf再执行sleep

在这里插入图片描述

不对啊,结果显示是先休眠再打印。

printf打印的结果没有显示在屏幕上也没有丢失,是因为暂存在了缓冲区。

缓冲区默认是行刷新,也就是说如果printf语句中有\n就会马上刷新

\r称为回车,即回到该行行首,如果行首本来有字符,再写入就会覆盖。

\n称为换行,也就是从本行的所在位置到下一行是此位置。

所以\r\n就是回车换行,但是在语言层面,\n就是回车换行

此外,还可以使用fflush(stdout)手动刷新

倒计时程序

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

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

在这里插入图片描述

进度条

采用分文件的方式来写:

在这里插入图片描述

不用在makefile文件中放process.h文件,因为编译器会自动到当前目录去查找

最后一起来看看程序的运行结果:

在这里插入图片描述


最近的文章都写的比较短,因为我感觉写太长了没什么人看,虽然我的文章本来也没人看。不知道各位大佬对我的文章有没有什么好的建议。

猜你喜欢

转载自blog.csdn.net/m0_62633482/article/details/129496002