自学内容网 自学内容网

Linux初识:【make/Makefile】【进度条】

目录

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

1.1背景

1.2有什么用?

 1.3Makefile基本概念

1.3.1make命令从上到下扫描

 1.3.2伪目标

1.3.3又有一个问题:make是怎么识别出我们代码的老和旧的?

 1.3.4Makefile推导规则

 1.3.5Makefile扩展语法

 二.Linux第⼀个系统程序−进度条

2.1缓冲区问题

 2.2测试代码

2.3进度条的代码

第一版

第二版


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

1.1背景

会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的 规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂 的功能操作

makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编 译,极大的提高了软件开发的效率。

make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一 种在工程方面的编译方法。

make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

1.2有什么用?

先在一个新建目录下创建两个文件,其中一个一定要是makefile或者Makefile:

code.c可以写我们想写的代码,Makefile这样写

 

code依赖code.c保存退出后,直接用make就可以执行命令:

 

 1.3Makefile基本概念

 

 

保存退出后,就可以直接使用make来执行代码:

 

 上面是先使用make来编译成可执行程序,后面的make clean自动调用删除可执行程序

 


1.3.1make命令从上到下扫描

为什么使用make会执行code,而删除要写成make clean?

调换一下位置:

此时再去make执行的就是clean了: 

 

make命令扫描Makefile文件时,从上到下扫描,默认形成第一个目标文件

 1.3.2伪目标

浅谈一个问题,如果我们多次make:

 这里就只有一个make会被执行

伪目标的作用:对应的目标总是被执行(对应的依赖方法和依赖关系) 

在我们的code也加上伪目标: 

 

此后我们再去一直运行就会一直执行了: 

 

对于我们没有改过的文件,我们没必要这样一直编译,所以这里没必要用伪目标,这里主要是为了好理解。 


1.3.3又有一个问题:make是怎么识别出我们代码的老和旧的?

 stat +文件名:

 这里有三个时间:

我们知道文件=内容+属性,所以如果我们文件的内容被修改则Modify的时间更新,文件属性被修改则Change更新,Access时间是用来记录文件或目录最近一次被访问的时间

 看Modify:

结论: .PHONY:让make忽略源文件和可执行目标文件的M时间对比  

 1.3.4Makefile推导规则

从上到下扫描,刚开始是没有.o文件的,理解为先把这段指令入栈,往下执行,也没有.s文件,也入栈,以此类推一直到.i所依赖的.c文件,执行这段代码,生成.i文件,一直往上走。

 


make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么: 

1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。 

2. 如果找到,它会找文件中的第⼀个目标文件(target),在上面的例子中,他会找到 myproc 这 个文件,并把这个文件作为最终的目标文件。

3. 如果 myproc 文件不存在,或是 myproc 所依赖的后面的 myproc.o 文件的文件修改时间要比 myproc 这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成 myproc 这个文件。

4. 如果 myproc 所依赖的 myproc.o 文件不存在,那么 make 会在当前文件中找目标为 myproc.o 文件的依赖性,如果找到则再根据那一个规则生成 myproc.o 文件。(这有点像一个堆栈的过程)

5. 当然,你的C文件和H文件是存在的,于是 make 会生成 myproc.o 文件,然后再用 myproc.o 文件声明 make 的终极任务,也就是执行文件。

6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个 目标文件。

7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并 报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。

8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对 不起,我就不工作。 

 1.3.5Makefile扩展语法

BIN变量的内容是code,后面的test有依赖方法,用echo打印,$是引用这个变量,括号理解为解引用

但是这里打印会给我们回显命令(加个@不会回显了):

 

 


 

 有了上面的结论,我们就可以做到在依赖方法中不出现一个名称(理解为宏):


 

还可以写成: 

 

其中的$@始终代表依赖关系的目标文件,$^始终代表依赖关系的依赖文件。 

 

 依赖方法可以写多个方法


如果是多个文件(版本一):

 


如果是多个文件(版本二):

或者: 

 

 

 

可以帮我们自动拿到当前目录下所有的.c文件 

 

这个可以帮我们把SRC的后缀.c全部换成.o 

 

最终的Makefile: 

 

 二.Linux第⼀个系统程序−进度条

2.1缓冲区问题

先来看两段代码:

先打印再休眠 

和 

 

先休眠再打印 

第二段,在运行代码的时候是先执行sleep还是printf ?虽然在执行代码时我们看到的现象是:沉睡三秒,再打印出来。实际上先执行的还是printf 

我们的代码运行到sleep时,printf一定执行完毕了,显示器没有显示出来,那在sleep休眠的3秒期间,hello Linux在哪里?hello Linux在缓冲区里。 

往显示器打印是行刷新,程序退出自动刷新缓冲区。 

 

 2.2测试代码

在main函数里写这样的一个函数:

其中\r是回车,表示我们输出的数字都只会在第一个位置出现,因为不是\n所以不会自动刷新缓冲区,我们手动刷新一下,就能显示数字了。但是这里有一个问题,就是我们把i的数字变为10或者更大的数字,这里就不会是倒计时了(只会改变第一个位置),理解显示:

我们在显示器打印出来数字的时候,实际上还是字符,因为显示器只认识字符:

2.3进度条的代码

第一版

 最终样式:

所有目录文件:

 

Makefile:

 

process.c:

 

process.h:

 

main.c:

 

 无法使用这个代码

第二版

 main.c:

回调函数:

process.c: 

 


原文地址:https://blog.csdn.net/2301_81699364/article/details/145238944

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!