10.Makefile构建奥秘:从基础到高效编译

make和makefile

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

由tab开头

cmake 复制代码
target: dependencies
    command
 

依赖关系和依赖方法

Make 和 Makefile 是管理项目构建的强大工具。通过定义目标、依赖关系和命令,可以自动化编译过程,提高开发效率。从简单项目到复杂系统,Makefile 都能提供灵活的支持。

但是为什么make多次不行呢

2..PHONY 伪目标

.PHONY 后面的clean叫做伪目标,绿色的clean:也是依赖关系只不过它什么都不依赖没有依赖目标。

make指令去makefile时会默认与从上往下的第一条匹配形成目标文件,所有make就对应gcc编译的指令,要执行清理指令需自己手动写出来。(如果gcc编译的指令和clean换个位置那么make就这些clean的指令了,make myproc才会执行gcc编译的指令)。

.PHONY的作用是什么,为什么要加它,不加它还能执行吗?

PHONY 是 Makefile 中的一个特殊目标,用于声明伪目标(phony target)。伪目标不代表实际的文件名,而是作为一个标签或命令集合的别名。

  • 伪目标的命令每次都会执行,无论依赖项是否更新。

所以在源代码没有更新时不用重新编译,在工程上如果文件很多但只修改了几个文件,重新编译的时候就不会去编译没有修改过的,只会再编译修改过的,能够提高效率。但伪目标就不一样了,每次编译的时候都会重新编译执行一次命令,不管有没有更新,所以对清理文件这种要求上就很适合,这样可以保证每次有清理要求时都能编译并清理干净文件。

make怎么知道.bin和.c的新旧,从而决定要不要重新编译呢?

通过stat我们能看到目标文件的access,modify和change时间

文件=文件内容+文件属性

modify就对应内容,change就对应属性

再打开myproc.c并修改内容后发现modify时间确实变了,但问题时为什么change也变了呢?这个问题很简单,因为你改了内容后文件的大小属性不也就改变了吗,或者modify的时间变了那这也是文件的modify时间属性呀,所以change的时间肯定会发生改变。(%99情况下modify变了change也一定会变)

在单独个文件的拥有者加上x权限后发现只是change变了modify没有变

对与access时间比较复杂,因为在工程上cat查看文件的比重肯定大于修改或者编辑的比重,所以如果每一次查看就会有很多io操作导致性能下降,所以通常是cat几次才会更新一次access时间。具体多少次与Linux版本有关

myproc.c和myproc不会同时产生,时间上不重叠

touch 已有文件 ->更新时间

make不行touch一下再make就ok

因为.PHONY总是被运行,相当于告诉gcc编译指令忽略对比时间和新旧问题,直接编译,所以默认不给编译加.PHONY

makefile版本1:

分开为每一个过程理解

依次保持依赖关系,形成推导链

好比入栈和出栈过程

.o依赖.s .s依赖.i .i依赖.c

所以依次向下找直到找到存在的.c,再返回去执行什么的指令

makefile推导规则:从上往下寻找,根据依赖关系链推导,不存在就入栈,一直到出口找到存在就执行,再依次出栈执行

makefile 版本2:

定义变量

就好比\*解引用拿到值 ,@指向BIN即依赖关系前一个 $^指向SRC依赖关系后一个

@echo ... 有了@就不会显示出echo只会显示后面的内容

make已经和gcc编译匹配,clean和test要显示写出来

通过定义变量的方式方便在文件名改变时,能快速更改,不用一个一个去找文件名修改

版本2plus:

依赖关系只一行,依赖方法可以有多行

makefile版本3:

通常我们先把所有文件编译成.o最后再把所有的.o文件和库的.o文件链接编译成.exe可执行文件

eg:gcc -c code.c先编译成同名.o文件

%:表示把所有.o .c依次展开

$<:表示把源文件.c依次编译

版本3plus:

针对许多文件通过定义一个一个列出文件的名字再去编译显然是不合理的

shell ls *.c拿到在shell执行ls命令后的结果,这里只要.c文件。或者用wildcard

SRC:.c=.o把SRC的.c变为.o

把code.c和myproc.c先分别形成.o文件,再最后链接到一起

回车换行

  • 回车(CR):将光标移动到当前行的行首。
  • 换行(LF):将光标移动到下一行的同一列位置。
  • \n:换行(LF)。
  • \r:回车(CR)。
  • \r\n:Windows风格的换行

缓冲区问题:

有\n就可以立刻看到hellobit,为什么去掉后要等3秒才能看到

当程序走到sleep(3)时一定执行了printf函数,显示器没有显示那么休眠的3

秒内hellobit在哪里?

现在可以简单理解缓冲区就是一段内存块,休眠3秒内hellobit就在缓冲区里面,没有刷新所以就没有打印出来,而\n会进行行刷新所以会立刻打印出来,没有\n就只能等到程序结束后自动刷新缓冲区最后再打印出来

这样手动刷新显示器就可以,或者直接用fprintf向显示器文件打印

进度条:

首先实现10倒数到1的基础指令

直接展示

相关推荐
空中海1 小时前
Nginx 知识体系 · 上篇:基础与核心
运维·nginx
说再见再也见不到1 小时前
华为交换机端口隔离(port-isolate)
linux·服务器·网络·华为·交换机·端口隔离·port-isolate
承渊政道1 小时前
群晖配Plex搭建私人影音中心,用起来到底怎么样?
服务器·windows·网络协议·https·ip·视频·持续部署
daemon.qiang2 小时前
Ubuntu 20.04+安装JFrog CLI超详细指南
linux·运维·ubuntu
湖城彭于晏2 小时前
VMware Ubuntu 固定IP + 上网 + 远程访问 完整教程
linux·ubuntu·vmware
小夏子_riotous2 小时前
Docker学习路径——6、简单微服务
linux·运维·服务器·docker·微服务·容器·云计算
剪刀石头布Cheers2 小时前
Ubuntu Hermes安装关键步骤
linux·运维·ubuntu·ai·agent·hermes
汽车仪器仪表相关领域2 小时前
Kvaser Leaf Light HS v2 CB:裸卡式CAN接口新标杆,赋能车载与工业集成测试高效升级
服务器·网络·数据库·人工智能·单元测试·自动化·汽车
l1t2 小时前
试用支持postgresql wire协议的duckdb服务器duckgres
服务器·数据库·postgresql