个人主页:Weraphael
✍作者简介:目前正在学习c++
和Linux
还有算法
✈️专栏:Linux
希望大家多多支持,咱一起进步!
如果文章有啥瑕疵,希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论 点赞 收藏 加关注
先来想象一个案例,假设一个执行文件里面包含了5
个源代码文件,分别是main.c
、add.c
、sub.c
、div.c
、mul.c
,这5
个文件的目的是:
main.c
:让用户输入两个操作数和一个操作符,再调用其他4
个子程序。Add.c
:计算两数之和。Sub.c
:计算两数之差。Div.c
:计算两数之商。Mul.c
:计算两数之积。接下来让以上使用gcc
编译代码,让程序运行起来
我们发现一个特点:当gcc
同时编译多个源文件的时候写的很长。
而且如果某个模块修改了,还得要重新编译,光是找出这个命令就够烦人的了。
如果可以的话,能不能有一个步骤完成上面的所有操作?
那就利用 make
指令和makefile
文件。
首先先带大家见见猪跑,后面再教大家怎么写。
通过以上样例,我们发现仅仅通过make
指令就生成了可执行文件,真的非常方便。
另外,如果我们修改某些源代码文件,则make
也可以更新该执行文件test.exe
,如此一来,节省了很多编译的时间。
要知道,某些程序在进行编译的操作时,会消耗很多CPU
资源。所以说make
有以下这些好处:
简化编译时所需要执行的命令
如果修改了某个源文件,则make
仅会针对被修改的文件进行重新编译来更新执行文件。
而make
里面最需要注意的大概就是文件makefile
,所以接下来我们就针对makefile
的语法来加以介绍。
makefile
文件中主要编写任务,而任务由 依赖关系
+ 依赖方法
构成。注意:Makefile
文件开头也可以大写。
因此,基本的makefiile
语法是这样的:
执行文件 : 源文件1 源文件2 ... # 依赖关系
<tab> gcc 源文件1 源文件2 ... -o 执行文件 # 依赖方法
# 在makefile中,#代表注释
# 依赖方法必须以<tab>键为开头
# 执行文件与依赖文件(源文件)之间需要以[:]隔开
接下来我用gcc
编译代码的过程再写一套:
以上是Makefile
文件和源文件的内容,接下来执行make
指令
接下来分析这些依赖关系
大家有没有发现,make
一下发现文件变多了,那能不能也通过执行一个命令就直接删除所有的目标文件和执行文件呢?答案是当然可以!
clean : # 不需要依赖任何文件
rm -rf [要删除的文件]
单纯输入make
指令时,默认执行makefile
中的第一个任务,当任务成功执行后,不再继续执行后续任务。
当然我们可以指定执行任务make filename
。就像上面的clean
一样。
我们在开始就发现,当我们连续的make
的时候,会提示我们文件已经是最新的
这其实是因为make
编译完成之后,如果源代码没有被改变过,那么就不会再次编译了,因为根本没有必要。其目的就是为了提高编译效率。
首先大家得明白一个概念,可执行文件的时间不可能会等于源文件的时间。因为必须要先有源文件才能够有可执行文件。因此,源文件的创建时间要早于可执行文件的创建时间。
那么,其实系统只需要对比源文件最近修改时间和可执行文件的时间,就可以判定是否重新编译。
如果源文件的时间晚于可执行文件的时间。说明源文件被修改过了,因此就需要重新编译
如果源文件的时间早于可执行文件的时间。说明源文件没被修改过了,因此就不需要重新编译
因此,这里有一条指令能帮助我们查看文件的时间
stat [filename]
那么有没有什么办法可以重复执行呢?答案当然是有的!
.PHONY
是 makefile
文件中的一个关键字,意为对某某对象生成伪目标,这样就能在不对源文件进行修改的情况下,重复执行任务了。
# 在makefile开头写上
.PHONY : [你需要重复执行的任务]
然后我们再重复执行make
指令看看效果
但是需要注意的是:以上对源文件的做法是没有意义的。一直重复执行没有修改的源文件不是白费力气吗?
.PHONY
这个关键字,一般是用来修饰 clean
任务,即清理解决方案
在makefile
中有两个特殊符号
$@ - 冒号左边的文件
$^ - 冒号右边的文件
再来看看效果
不过我们也会发现我们上面的使用make
的操作会使得这些命令回显出来,如果我们不想要回显出来,可以在依赖方法前加上@
再来看看效果