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

【Linux】自动化构建-make/Makefile

目录

一、简介

背景

什么是make/makefile

二、make/makefile的使用

三、推导过程

扩展语法


合集传送门:Linux_uyeonashi的博客-CSDN博客

一、简介

背景

• 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
• 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
• makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

什么是make/makefile

• make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
• make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

二、make/makefile的使用

示例代码:

#include <stdio.h>
int main()
{
 printf("hello Makefile!\n");
 return 0;
}

Makefile:

myproc:myproc.c
 gcc -o myproc myproc.c
 
.PHONY:clean
clean:
 rm -f myproc

依赖关系:上⾯的⽂件myproc,它依赖myproc.c

依赖方法:gcc -o myproc myproc.c ,就是与之对应的依赖关系

.PHONY:clean

• 工程是需要被清理的
• 像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
• 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。

什么叫做总是被执行?

$ stat XXX
File: ‘XXX’
Size: 987 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1321125 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ whb) Gid: ( 1000/ whb)
Access: 2024-10-25 17:05:30.430619002 +0800
Modify: 2024-10-25 17:05:25.940595116 +0800
Change: 2024-10-25 17:05:25.940595116 +0800

文件 = 内容 + 属性
Modify: 内容变更,时间更新
Change:属性变更,时间更新
Access:常指的是文件最近一次被访问的时间。在Linux的早期版本中,每当文件被访问时,其atime
都会更新。但这种机制会导致大量的IO操作。具体更新原则,不做过多解释。

查看状态, 我们可以看到以下三个时间。
文件 = 内容 + 属性
以下简称acm时间, a表示最近一次访问的时间, M表示内容最近被修改的时间, C表示最近一个属性被修改的时间。
例如 :
cat proc.c就是访问文件(但是访问频繁影响效率, 现在的操作系统已经这一块已经发生了变化。)
chmod o-r proc.c 就是改变属性
vim proc.c 就是修改内容

但是内容被修改可能发生属性的联动, 因为文件的大小变了。

不管是源文件, 还是可执行程序, 都是文件, 程序可不可总是被执行就是看mtime的时间, 如果没有修改proc.c的m时间,只修改了proc.exe的时间, 那么表示exe比.c更新,编译器就认为没有必要再重新编译了, 相反如果.c的mtime时间更新,那么就可以重新编译生成新的可执行程序

三、推导过程

myproc:myproc.o 
 gcc myproc.o -o myproc
myproc.o:myproc.s 
 gcc -c myproc.s -o myproc.o
myproc.s:myproc.i 
 gcc -S myproc.i -o myproc.s
myproc.i:myproc.c
 gcc -E myproc.c -o myproc.i
 
.PHONY:clean 
clean: 
 rm -f *.i *.s *.o myproc

编译

$ make
gcc -E myproc.c -o myproc.i
gcc -S myproc.i -o myproc.s
gcc -c myproc.s -o myproc.o
gcc myproc.o -o myproc

 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 的终极任务,也就是执行文件hello 了。
6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

扩展语法

% 是makefile中的通配符
例如: %.c: 当前目录下所有.c文件, 展开到依赖项中。
依赖关系:右侧的依赖文件, 一个一个的交给gcc -c选项, 形成同名的.o文件。

$@表示目标文件, $^表示所有依赖文件的文件列表

默认情况下, makefile执行到了一个目标文件之后就会停下来, 比如下图, 只会生成一个proc文件

如果想进行多个文件同时编译,则可以添加目标all,但是不给执行方法, 为了形成目标all,makefile就会像下面搜索依赖项,形成proc和code。

BIN=proc.exe # 定义变量  
CC=gcc 
#SRC=$(shell ls *.c) # 采⽤shell命令⾏⽅式,获取当前所有.c⽂件名 
SRC=$(wildcard *.c) # 或者使⽤ wildcard 函数,获取当前所有.c⽂件名 
OBJ=$(SRC:.c=.o) # 将SRC的所有同名.c 替换 成为.o 形成⽬标⽂件列表 
LFLAGS=-o # 链接选项 
FLAGS=-c # 编译选项 
RM=rm -f # 引⼊命令 
$(BIN):$(OBJ) 
 @$(CC) $(LFLAGS) $@ $^ # $@:代表⽬标⽂件名。 $^: 代表依赖⽂件列表 
 @echo "linking ... $^ to $@" 
%.o:%.c # %.c 展开当前⽬录下所有的.c。 %.o: 同时展开同
名.o
 @$(CC) $(FLAGS) $< # %<: 对展开的依赖.c⽂件,⼀个⼀个的交给gcc。 
 @echo "compling ... $< to $@" # @:不回显命令 
.PHONY:clean 
clean:
 $(RM) $(OBJ) $(BIN) # $(RM): 替换,⽤变量内容替换它 
 
.PHONY:test 
test: 
 @echo $(SRC) 
 @echo $(OBJ)

本篇完,下篇见!


http://www.kler.cn/a/520811.html

相关文章:

  • 八股——Java基础(四)
  • 算法-加油站问题
  • PyTorch中的movedim、transpose与permute
  • 深入剖析 Adam 优化器:原理、优势与应用
  • .NET9增强OpenAPI规范,不再内置swagger
  • PyCharm接入DeepSeek实现AI编程
  • linux naive代理设置
  • 解决.NET程序通过网盘传到Linux和macOS不能运行的问题
  • GIS与相关专业软件汇总
  • “腾讯、钉钉、飞书” 会议开源平替,免费功能强大
  • 一文读懂 HTTP:Web 数据交换的基石
  • Solon Cloud Gateway 开发:熟悉 ExContext 及相关接口
  • Doris Schema Change 常见问题分析
  • AF3 FourierEmbedding类源码解读
  • Windows 靶机常见服务、端口及枚举工具与方法全解析:SMB、LDAP、NFS、RDP、WinRM、DNS
  • ListOJ13:环形链表(判断是否为环形链表)
  • 在亚马逊云科技上使用Luma AI Ray2视频模型生成炫酷视频 (下)
  • yolov11 解读简记
  • 指针的介绍1后
  • 《 C++ 点滴漫谈: 二十四 》深入 C++ 变量与类型的世界:高性能编程的根基
  • python实现答题游戏
  • 【橘子Kibana】Kibana的分析能力Analytics之Canvas画布
  • 网站上的图片无法使用右键“图片另存为”
  • 步入响应式编程篇(三)之spring webFlux与R2DBC
  • 力扣算法题——611.有效三角形的个数
  • Java 大视界 -- Java 大数据在元宇宙中的关键技术与应用场景(65)