当前位置: 首页 > news >正文

【Linux】Linux项目自动化构建工具——make/Makefile

我举报,有人不学习!!!
在这里插入图片描述

文章目录

  • 一、makefile原理
  • 二、初步理解makefile的语法
    • 1.gcc如何得知,源文件不需要再编译了呢?
    • 2.为什么执行的指令是make和make clean呢?
  • 三、makefile的推导规则
  • 四、Linux小程序—进度条
    • 1.缓冲区概念
    • 2.回车换行
    • 3.倒计时小程序
    • 4.进度条



一、makefile原理

1.
makefile文件既可以写成makefile,也可以写成Makefile

2.
makefile文件中,要写的是依赖关系和依赖方法,例如生成的可执行程序mycode依赖的就是mycode.c源文件,没有这个源文件,就没有mycode这个可执行程序,生成可执行程序的过程中又依赖方法gcc mycode.c -o mycode也就是需要gcc来编译链接生成可执行程序。

vim makefile

// 下面是makefile文件的内容
mycode:mycode.c
       gcc mycode.c -o mycode  

二、初步理解makefile的语法

第一行是依赖关系,第二行必须以Tab键开头!!!,第二行写的是依赖方法
依赖关系可以为空

  1 mycode:mycode.c
  2     gcc mycode.c -o mycode
  3 
  4 .PHONY:clean
  5 clean:                                                                                                                                                                
  6      rm -f mycode

1.
被.PHONY:关键字修饰的对象是一个伪目标,该目标总是被执行的。
由于第一条依赖关系和依赖方法没有被.PHONY:修饰,所以如果命令执行过,且源文件没有被改动过的话,make是不允许连续多次执行的,但第二条依赖关系和依赖方法被.PHONY:修饰了,所以它是可以多次执行的

2.
换句话说,有了关键字.PHONY:修饰过后,就不要通过对比源文件和可执行程序Modify时间来判断是否能够执行指令了,不走这套规则,我让你执行,你就一直给我执行就OK了

在这里插入图片描述

1.gcc如何得知,源文件不需要再编译了呢?

Modify代表文件内容被修改的时间,Change代表文件属性被修改的时间,Access代表最后一次访问文件的时间,值得注意的是,文件大小也算文件的属性

1.
有时候访问文件的时间Access被更新的不是很灵敏,以前老的操作系统内核,对于这件事的原则就是,只要你访问了,就立马更新时间,但现在的操作系统内核,过一段时间之后才会更新我们的访问文件时间。
原因:文件操作的时候,改文件就一定会访问文件,但访问文件不一定该文件,所以访问文件的次数太多了,要进行更多次的IO,并且文件访问的时间基本没有人关心。

在这里插入图片描述
2.
一定先有源文件再有可执行程序,所以源文件的Modify时间一定要比可执行程序的Modify时间更早,所以gcc识别要不要重新编译,比较的就是源文件和可执行程序的文件内容修改时间。如果可执行程序更早,说明源文件被修改了,那就需要重新编译,如果源文件早,说明可执行程序被修改过,不需要重新编译。

当已经使用make指令过后,无法继续使用时,我们可以touch更新一下源文件的时间,这个时候就又可以用make指令了,这就证明了我们上面的结论。

touch mycode.c //touch后面跟上已存在的文件,可以更新此文件的三个时间。

2.为什么执行的指令是make和make clean呢?

make也可以跟上mycode使用,make默认从上到下扫描文本makefile的时候,第一个扫描到的目标文件可以省略名称使用,例如直接使用make,执行的就是makefile里面的第一个目标文件,并且默认情况下makefile只形成一个目标文件,也就是总目标文件只能有一个。

make mycode 
make
make clean

三、makefile的推导规则

在这里插入图片描述

  1 mycode:mycode.o
  2     gcc mycode.o -o mycode                                                                                                                                            
  3 mycode.o:mycode.s                  
  4     gcc -c mycode.s -o mycode.o       
  5 mycode.s:mycode.i                     
  6     gcc -S mycode.i -o mycode.s
  7 mycode.i:mycode.c              
  8     gcc -E mycode.c -o mycode.i
  9                  
 10 .PHONY:clean     
 11 clean:           
 12      rm -f mycode

1.
根据依赖关系列表,make先找mycode发现没有,那就去找mycode依赖的mycode.o,结果发现也没有,那就去找mycode.o依赖的mycode.s,结果发现还是没有,那就去找mycode.s依赖的mycode.i,结果没找到,那就去找mycode.i依赖的mycode.c结果找到了,那就执行他们之间的依赖方法,然后.i就有了,那就再一点一点向上执行每条依赖方法

2.
这就是整个make的依赖性,类似于堆栈结构,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。

四、Linux小程序—进度条

1.缓冲区概念

1.
如果加上\n那就会先显示you can see me然后停下来2秒钟,如果没有\n的话,那就会先停下来2秒,然后才显示出you can see me。

2.
第一种拥有\n可以立即输出的原因是因为,\n是行缓冲,只要遇到\n就会立马将这一行的内容输出到显示器上面

3.
针对第二种没有\n的情况,首先printf语句肯定是要先执行的,唯一的可能性就是,这个you can see me没有被立即显示出来,等到走完sleep语句,它才显示出来,在未显示的这段时间里面,you can see me一直被存储在行缓冲区里面

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main()
  5 {
  6     printf("you can see me ........\n");
  7     sleep(2);                                                                                                                                                         
  8     return 0;
  9 }
  
	// 可以利用fflush(stdout)语句来刷新缓冲区,这样数据就会立马显示出来
	

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main()
  5 {
  6     printf("you can see me ........");
  7     sleep(2);                                                                                                                                                         
  8     return 0;
  9 }

2.回车换行

理论上,回车和换行不是一个概念,换行是回到当前行的最开始,换行是将光标挪到下一行相同的光标位置,\r是回车\n是换行,\r\n合起来我们称之为回车换行。

语言层面上,\n就是回车换行,因为编译器在内部对于\n做了特殊处理,回车换行其实分成两步,先换行,再回车。

例如下面老式键盘的回车形状,是先向下再向左的。
在这里插入图片描述

3.倒计时小程序

1.
显示器能够显示各种符号,包括数字,汉字,字母等等,这些都被计算机看作符号,只不过人把它分为数字还是汉字,字母等,能够显示这么多符号是因为显示器面板上有各种像素点,点亮对应显示器上的像素点,就可以给人类显示出来各种各样的符号了,并且凡是能够显示到显示器上的,其实都是字符

在这里插入图片描述

2.
如果我们重新在第一个像素点输入8,那么这个像素点就会重新显示8,将9覆盖掉,基于这样的原理,我们就可以写一个倒计时小程序了。

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 int main()
  4 {
  5     int cnt=10;
  6     while(cnt)
  7     {
  8         printf("剩余时间:%2d\r",cnt);
 			// 利用\r回车来实现同一个像素点,显示多个数字,这样看起来就像倒计时                                                                                                                          
  9         fflush(stdout);
  			// 每次刷新一下缓冲区,立马显示数据
 10         cnt--;
 11         sleep(1);
 12     }
 13     return 0;
 14 }

4.进度条

gcc的-D选项可以帮助我们在命令行中完成某些变量的定义,例如下面定义了进度条的样式为N=1时的样式。

ProcessOn文件依赖main.c和process.c源文件,所以依赖关系和依赖方法如下:

Makefile文件内容

  1 ProcessOn:main.c process.c
  2     gcc main.c process.c -o ProcessOn -D N=1                                                                                                                          
  3 
  4 .PHONY:clean
  5 clean:
  6     rm -f ProcessOn

main.c文件内容

  1 #include "process.h"                                                                                                                                                  
  2 
  3 int main()
  4 {
  5     ProncessOn();
  6     return 0;
  7 }

process.h文件内容

  1 #pragma once 
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 
  6 #define NUM 101
  7 #define S_NUM 5                                                                                                                                                       
  8 
  9 extern void ProncessOn();

\033[42;34m 输出的内容 \033[0m这是内容的颜色控制
usleep代表的是微秒
%%在printf中可以输出显示为一个%号
-100可以控制进度条宽度为100位宽并且每次左对齐输出字符数组bar

C语言printf输出颜色控制

process.c文件内容

    2 #include "process.h"
    3 
    4 char style[S_NUM]={'*','#','-','.','+'};
    5 五种风格,可以在makefile文件中修改N,以控制风格样式
    
    6 void ProncessOn()
    7 {
    8     int cnt=0;
    9     //循环101次
   10     char bar[NUM];
   11     memset(bar,'\0',sizeof(bar));
   12 
   13     const char*lable="|\\-/";
   14 
   15     while(cnt<=100)
   16     {
   17         //printf("[%-100s][%-3d%%][%c]\r",bar,cnt,lable[cnt%4]);
   18         printf("\033[42;34m[%-100s][%-3d%%][%c]\033[0m\r",bar,cnt,lable[cnt%4]);                                                                                    
   19         fflush(stdout);
E> 20         bar[cnt++]=style[N];
   21         usleep(60000);
   22     }
   23 
   24     printf("\n");
   25 }

相关文章:

  • <Linux线程同步>——《Linux》
  • 【Array数组】面试前基础知识点深度记忆总结
  • 20221226编译Toybrick的TB-RK3588X开发板的Android12系统1-编译环境配置
  • 大话JMeter2|正确get参数传递和HTTP如何正确使用
  • 在Makefile中使用空格缩进的方法
  • 详解vue中vuex的用法
  • 利用Bat打开exe程序并传入值
  • 【iMessage苹果推群发】苹果相册推它由pushchatkey.pem和pushchatcert.pem作为单独的文件使用
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • 基于Xlinx的时序分析与约束(5)----衍生时钟约束
  • Python常见问题整理
  • Docker安装Zookeeper教程(超详细)
  • 【学习笔记12.25】动态规划入门
  • C语言用好写好头文件
  • 程序员过圣诞 | 用HTML写出绽放的烟花
  • 收藏网友的 源程序下载网
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【笔记】你不知道的JS读书笔记——Promise
  • Facebook AccountKit 接入的坑点
  • FastReport在线报表设计器工作原理
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • SpiderData 2019年2月16日 DApp数据排行榜
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 手写一个CommonJS打包工具(一)
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 携程小程序初体验
  • 一文看透浏览器架构
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • Nginx实现动静分离
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)jQuery 基础
  • (转)socket Aio demo
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • .NET 使用 XPath 来读写 XML 文件
  • .NET/C# 使用反射注册事件
  • .NET业务框架的构建
  • /etc/shadow字段详解
  • :not(:first-child)和:not(:last-child)的用法
  • @select 怎么写存储过程_你知道select语句和update语句分别是怎么执行的吗?
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [ vulhub漏洞复现篇 ] Hadoop-yarn-RPC 未授权访问漏洞复现
  • [ web基础篇 ] Burp Suite 爆破 Basic 认证密码
  • [@Controller]4 详解@ModelAttribute
  • [<MySQL优化总结>]
  • [4.9福建四校联考]