目录
一、什么是Makefile?
在一个工程中的源文件不计其数,为了方便管理,我们将其按类型、功能、模块分别放在若干个目录中。Makefile 文件定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编 译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
Makefile 带来的好处就是“自动化编译” ,一旦写好,只需要一个 make 命令,整 个工程完全自动编译,极大的提高了软件开发的效率。
好处:自动化编译;使用:make命令;效果:自动化编程;作用:提高软件开发效率;简单来说:为了方便多文件管理,编写的一个拥有编译规则的文件。
二、如何编写Makefile文件
1、命名:
文件命名:Makefile或者makefile;
2、Makefile规则
一个Makefile文件中可以有一个或者多个规则
规则:
目标...:依赖...
命令(shell命令)
...
目标:最终要生成的文件(伪目标除外)
依赖:生成目标所需要的文件或是目标
命令:通过执行命令对依赖操作生成目标(命令前必须 Tab 缩进)
此外,Makefile中的其他规则一般都是为第一条规则服务的;
在lesson07中编写Makefile文件:
使用make进行编译,第一次使用需要安装make指令;
make进行编译:
运行结果:
三、工作原理
1、命令在执行之前,需要先检查规则中的依赖是否存在
Yes: 执行命令;
No:,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的, 如果找到了,则执行该规则中的命令(所以说:Makefile中的其他规则一般都是为第一条规则服务的;)
例如上面的Makefile文件中:第一个规则中的依赖都是.o文件,而.o文件根本不存在,在执行的时候,需要检查是否存在,这时不存在,就要检查底下的规则中是否能够产生依赖,如果能够产生,就可以执行。显然是可以产生的,底下的5个规则就产生了5个依赖。这也就显然,底下的规则是为了第一条规则服务的。
如果下面的规则与第一条规则无关,则不会执行,除非进行手动的调动,因为默认情况下,make执行Makefile中的第一条规则。
2、 检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
什么意思呢?我们知道在写代码的时候,代码需要不断的更新修改,这样产生的可执行程序也就需要不断的更新。那什么时候需要更新?什么时候不需要更新呢?
如果依赖的时间比目标的时间晚,需要重新生成目标。也就是在规则中,对依赖进行命令产生目标,只要依赖的生成时间比目标的生成时间晚,就证明了更新,就需要更新目标。
上述代码中,一旦.c文件发生更新,则.o文件就需要重新更新,因为依赖新产生。进一步.o作为app的依赖也会进行更新。
四、变量
变量是干什么呢?
先说出来变量的作用,在较为减到的Makefile文件中,变量的作用还不太明显,然而一旦Makefile中的内容过于复杂,则需要变量进行简化。如何简化呢?
首先是进行变量的规则介绍:
自定义变量:
变量名=变量值 例如:var=hello
预定义变量:
AR : 归档维护程序的名称,默认值为 ar
CC : C 编译器的名称,默认值为 cc,gcc作用
CXX : C++ 编译器的名称,默认值为 g++
$@ : 目标的完整名称
$< : 第一个依赖文件的名称
$^ : 所有的依赖文件
获取变量的值:
$(变量名)
举例:
相对来说是简化了一些,但是Makefile中的还有较多的内容没有简化,就比如说,底下的四条规则,结构具有什么相似的结构吗,,那么如何简化呢?就需要用到模式匹配;
五、模式匹配
add.o:add.c
gcc -c add.c
div.o:div.c
gcc -c div.c
sub.o:sub.c
gcc -c sub.c
mult.o:mult.c
gcc -c mult.c
main.o:main.c
gcc -c main.c
我们利用%进行匹配;%.o:%.c
%: 通配符,匹配一个字符串;
两个%匹配的是同一个字符串;进过匹配符的介入,上述规则就成了下面的指令:
%.o:%.c
$(CC) -c $< -o $@
运行结果:
六、函数
在经过模式匹配与变量的介入后,我们发现之前的Makefile文件已经简化了不少,但是我们发现,如果说一个文件中的.c文件或则说.o文件过多的时候,定义变量一个一个定义也是一个十分麻烦的事情,为了对其再次进行简化,在这里我们引入两个函数进行操作。
1、 $(wildcard PATTERN...)
功能:获取指定目录下指定类型的文件列表
参数:PATTERN 指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔
返回:得到的若干个文件的文件列表,文件名之间使用空格间隔
示例:
$(wildcard *.c ./sub/*.c)
返回值格式: a.c b.c c.c d.c e.c f.c
例如将上述的函数进行简化;
当然,上述代码是有问题的,因为我们在第一个规则中,所有的依赖是.o文件,就算获取了.c文件也没有用。
2、$(patsubst <pattern>,<repalcement>,<text>)
功能:查找text中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合 模式,如果匹配的话,则以替换。
pattern可以包括通配符`%`,表示任意长度的字串。如果 中也包含`%`,那么,repalcement中的这个`%`将是pattern中的那个% 所代表的字串。(可以用`\`来转义,以`\%`来表示真实含义的`%`字符)
返回:函数返回被替换过后的字符串
示例: $(patsubst %.c, %.o, x.c bar.c) 返回值格式: x.o bar.o
在第一个函数中,我们只是对文件中的.c依赖进行了利用函数的获取,但是我们知道,还有第一部分依赖是由底下的规则产生的,这时就需要再用一个函数。
运行结果:
最后再介绍一下清楚,我们在上述代码执行的时候,会在文件夹中产生.o文件,我们可以再Makefile文件中加入删除规则,然后单独调用;
必须直接调用,因为它对于第一条规则没有关系,默认条件使用make下不会被执行,只能专门调用才会被使用。
总结:本节我们学习了Linux中Makefile文件的相关基础知识以及相关操作的使用,大家学习完后一定要自己动手试试,操作操作!如有问题欢迎评论区交流。
创作不易,还请大家多多点赞支持!!!