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

Linux环境基础开发工具->make/Makefile

引入:make/Makefile是什么?

前面我们知道了vim负责编辑代码,gcc负责编译代码,而make/Makefile则负责的是自动化编译!

Makefile是一个文件,make是一条指令

我们在Makefile文件中进行编辑,让哪些文件需要先编译,哪些文件需要后编译

然后简单的make指令即可让整个工程完全自动编译,极大的提高了软件开发的效率

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

一:需要makefile的场景

现在我想自己实现一个打印功能的函数,所以我有以下三个文件

1:print.h 

#pragma once
#include<stdio.h>void print(const char* str);

2:print.c

#include"print.h"
void print(const char* s)
{printf("%s", s);}

3:main.c

#include"print.h"
int main()
{print("hello!");return 0;
}

三个文件: 

 

此时我想形成一个可执行文件,每次执行该文件的时候,就显示出"hello!"

所以现在我们让print.c和main.c通过gcc形成了.o文件

然后再gcc main.o print.o 生成可执行程序a.out

 

但是太麻烦了,我们这还仅仅只有两个.c文件的合并,以后一个项目都是几十个,难道我们要进行几十次的gcc -c吗??所以我们只需将这些写进makefile这个文件即可

 

二:makefile的使用演示

1: 在源文件所在目录下创建一个名为Makefile/makefile的文件

 

2:编写Makefile文件

3:运行make指令

此时发现其自动创建了我们想要的两个.o文件,并且对两个进行链接生成了a.out:

运行a/out 

 

makefile的出现,让我们不在需要手动的每次都gcc ,我们写在makefile中,想用直接make即可!

三:makefile的格式

Makefile文件最简单的编写格式是:

先写出文件的依赖关系,然后写出这些文件之间的依赖方法,依次写下去:

目标: 依赖文件1 依赖文件2 ...Tab键开头的依赖方法

 

注意:依赖方法最前面必须是tab键,不能连续的空格!

Q:为什么写了makefile,我们进行make就能执行这一系列的指令?

A:make的原理如下:

①:make会在当前目录下找名字为“Makefile”或“makefile”的文件。

②:如果找到,它会找文件当中的第一个目标文件,在上面的例子中,它会找到mytest这个文件,并把这个文件作为最终的目标文件。

③:如果mytest文件不存在,或是mytest所依赖的后面的test.o文件和main.o文件的文件修改时间比mytest文件新,那么它就会执行后面的依赖方法来生成mytest文件。

④:如果mytest所依赖的test.o文件不存在,那么make会在Makefile文件中寻找目标为test.o文件的依赖关系,如果找到则再根据其依赖方法生成test.o文件(类似于堆栈的过程)。

⑤:当然,你的test.c文件和main.c文件是存在的,于是make会生成test.o文件和main.o文件,然后再用test.o文件和main.o文件生成最终的mytest文件。

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

⑦:在寻找的过程中,如果出现错误,例如最后被依赖的文件找不到,那么make就会直接退出,并报错。

四:项目清理->clean

在我们每次重新生成可执行程序前,都应该将上一次生成可执行程序时生成的一系列文件进行清理,但是如果我们每次都手动执行一系列指令进行清理工作的话,未免有些麻烦,因为每次清理时执行的都是相同的清理指令,所以makefile也提供了clean板块来进行文件的清理

写法如下:

make clean指令即可清理指定文件:

解释:执行make clean指令之后,按照makefile文件中的指令把两个.o和a.out都删除了!

注意:clean: 是一个依赖关系,只不过clean:不依赖于任何的文件,所以:后面什么都没有

五:ACM

Q1:我重复的进行make会怎么样?

A1:

解释:第一次make生效了,但是第二次打印:`a.out' is up to date. (译为a.out已经是最新的了!)

Q2:系统怎么知道a.out是最新的了?

A2:因为文件的最近修改时间没有变,所以系统对之后的make不作处理!

任何一个文件都有三个时间,简称ACM!

A:最近访问时间
C:最近的属性修改时间
M:最近的内容修改时间

系统在执行make指令的时候,会去比对所涉及的文件的ACM是否发生变化,变化了,此时的make指令才有意义,系统才会进行一些列的gcc指令!

在我们连续的make期间,既没有影响到任何一个文件的最近访问时间,最近属性修改时间,最近内容修改时间,所以最后发现没有任何的变化,所以对第二次及后面的make不做处理!

六:.PHONY

.PHONY 的作用

  1. 将目标(如 clean)标记为 伪目标,表明它不生成同名文件。

  2. 当调用伪目标时,Make 跳过对该目标文件存在性的检查,直接执行其命令。

所以我们的clean常常用.PHONY修饰

格式如下:

现在 我们连续的make clean,系统也不会去比对文件的ACM了!

七:makefile的简写方式

Makefile文件的简写方式:

自动变量:

        $@:目标文件(如 a.out 或 print.o)。

        $^:所有依赖文件(如 print.o main.o)。

        $<:第一个依赖文件(如 print.c)。

模式规则:

        %.o: %.c:匹配所有 .c 文件生成对应的 .o 文件,避免为每个 .o 文件写重复规则。

通配符清理:

        rm -f *.o:删除所有 .o 文件,无需手动列出。

所以可以 简写成如下:

八:一些细节

1:makefile的执行顺序

当你把clean板块放在makefile文件的上面是,此时直接运行 make 时会执行 clean!此时只能进行make a.out,才能执行 a.out 的构建规则

 

2:ACM这三个时间可以通过stat指令来查看

需要注意的是,尽管能影响的A的是访问,也就是cat或者touch,但是由于优化,只有第一次的cat能够影响A,后面连续的cat不会改变A!

但是touch指令就算什么都不做,也能够一次性影响ACM三个时间,且能够连续的影响,如图:

 

3: 为什么要给clean加上.PHONY

  • 无 .PHONY 时
    Make 会检查 clean 的依赖文件和它本身的时间戳,但这种检查对伪目标毫无意义(例如 clean 本就不该对应任何文件)。

  • 有 .PHONY 时
    Make 会跳过文件检查,直接执行命令,减少不必要的计算。

总结:提高性能

4:makefile和Makefile都一样,看个人喜好

5:makefile中也能进行宏替换

CC := gcc        # 定义编译器
CFLAGS := -Wall  # 定义编译选项
TARGET := a.out  # 定义目标文件名

好处:修改编译器或选项时只需修改变量值。

http://www.xdnf.cn/news/761473.html

相关文章:

  • VScode编译调试debug,gpu的cuda程序,Nsight
  • Java 老矣,尚能饭否?
  • 车辆检测算法在爆炸事故应急响应中的优化路径
  • Vue项目中安装插件的命令及区别
  • 22. Generate Parentheses
  • 盲盒经济2.0:数字藏品开箱是否适用赌博法规
  • 3C All-in-One Toolbox:安卓手机的全能维护专家
  • BLIP-2
  • 【C++】vector的模拟实现
  • 牛客2025年儿童节比赛
  • OpenLayers 地图标注之图文标注
  • 【第四十七周】HippoRAG 2 复现与分析(一):环境部署与代码分析
  • linux文件管理(补充)
  • 纯汇编自制操作系统(四、应用程序等的实现)
  • [Python] Python自动化:PyAutoGUI的基本操作
  • ArkTS基础
  • [PCIe]Gen6 PAM4的功耗相比Gen5 NRZ增加了多少?
  • C++测开,自动化测试,业务(第一段实习)
  • 微软常用运行库合集(VisualC++)2025.04.22
  • 阴盘奇门 api数据接口
  • Redis:安装与常用命令
  • Mybatis-Plus 学习
  • RTMP播放器谁更强?深入解析SmartPlayer与VLC、PotPlayer等方案的技术差异
  • 落石石头检测数据集VOC+YOLO格式1185张1类别
  • WEBSTORM前端 —— 第3章:移动 Web —— 第5节:响应式网页
  • 字节golang后端二面
  • 位运算 #常见位运算总结 #题解
  • 优化06-物理读和IO
  • Markdown笔记
  • 81、使用DTU控制水下灯光控制