【Linux】make命令 | makefile文件详解
目录
前言:
一、预览功能
二、依赖关系和依赖方法
三、清理项目
四、makefile中写入其他Linux命令
五、PHONY关键字
1.文件时间信息(stat命令)
六、makefile执行命令顺序
七、makefile使用技巧
八、生成多个可执行文件
总结:
前言:
我们是否可以在Linux上面不安装编译器,也可以使每次写的代码编译运行?也就是不用每次都是用gcc编译出一个可执行文件,之后修改了源文件之后又删除生成的可执行文件再gcc生成可执行文件。
接下来我们就来详细讲解两个相关的知识:make命令和makefile。他们可以快速的提升编程效率。
一、预览功能
我们先来预览一下他们的整体功能。此时我们写一个proc.c文件,并在里面写入一些内容:
此时我们新建一个Makefile/makefile文件,这两个名字都可以。并向Makefile中写入以下内容:
此时我们直接在命令行中输入make,就会发现生成了一个proc可执行文件。
此时你可能会说,这看起来步骤反而变多了,没错,到这步确实是变多了,但是我们接下来要深入学习你就会发现,这个文件真的用起来很爽。
二、依赖关系和依赖方法
我们来看一下makefile文件中的语句分解:
什么是依赖关系?什么是依赖方法?
打个比方:你和你爹,这个就是依赖关系;此时你问你爹要钱,这个就是依赖方法。
所以必须现有依赖关系,之后才有依赖方法(大家不要想的很复杂) 。
此时就好解释了:形成proc可执行程序依赖proc.c,所以互不可缺;但是只有依赖关系不行,我们还要有依赖方法,要表明如何形成可执行程序。
makefile本质就是依赖方法的集合。
三、清理项目
如何清理项目?此时我们在Makefile中再加入如下几条语句:
.PHONY:clear
clear:
rm -f proc
之后执行如下命令(make clear):
这里大家肯定都一头雾水,这是为啥?(插一句:phony假的)
注意这里的命名可以更改,比如:
你可以发现clear目标文件右边没有依赖文件。
此时你会好奇,难道第一次直接make就可以生成可执行文件吗?可不可以make proc?其实也可以:
这是因为makefile文件是从上到下扫描的,第一行的依赖关系make proc中的proc可以省略掉。
所以我们也可以把clear放在首行,比如我们作出以下修改:
但是我们一般建议把清理命令(清理的依赖关系)放在最后。
小总结:makefile文件,会被make从上到下开始扫描,第一个目标名,是可以直接用make省略目标名形成的;如果我们要执行其他组的依赖关系和依赖方法:make name.
四、makefile中写入其他Linux命令
此时你会想:rm 了、gcc 了这些命令归根结底还是Linux中的命令行,那么是不是我们在依赖方法中写入也可以执行呢?
此时我们先补充一下:#在makefile文件中可以注释。
此时我们将Makefile的内容做以下修改:
但是还是很烦,因为每次把命令行也显示出来了,此时我们要将命令行隐藏。隐藏命令行要使用@符号(@是关闭命令回显)。
唉!此时是不是可以增加一些提示信息呢?比如:
此时我们故意项文件中加入报错信息,看看运行结果:
此时我们修正代码:
五、PHONY关键字
此时我们一直执行make命令看看是什么效果:
再一直执行make clear命令:
此时把PHONY语句给注释了并再次一直执行make clear命令:
我们可以发现,好像有PHONY和没有它都一样,这里我们把PHONY放到第一行并观察执行结果。
此时我们发现,用PHONY修饰第一行依赖关系的目标文件,每次都可以执行。所以.PHONY让目标文件对应的方法,总是被执行。此时我们再来看一个现象:
有时候需要重新编译,有时候不需要,这是为什么?
1.文件时间信息(stat命令)
对于源文件和可执行文件,都是文件。
文件 = 内容 + 属性
我们用stat命令来查看一个文件或文件系统的状态信息:
至于Access对应的时间是文件被访问的时间,因为这个频率太高了,频繁修改影响效率,所以它的修改时间我们不做讨论。
此时我们先修改proc.c权限,之后修改proc.c内容:
此时我们来对比proc和proc.c文件的时间区别:
这里再回到之前的问题,此时我们再Makefile中将PHONY放在第一行,并把PHONY修饰的clear给删除:
PHONY让依赖方法忽略掉时间对比,但是为什么make clear却一直执行呢?因为clear中的依赖方法rm -f file本身就不关心时间。所以可以一直执行make clear。
六、makefile执行命令顺序
我们之前在gcc章节讲到过(vim编辑器和gcc编译器-CSDN博客),生成一个可执行文件是经过预编译、编译、汇编、链接的步骤的。我们可以在makefile中把详细的执行步骤写入:
Makefile执行顺序为从上到下执行,此时文件中它先找有没有proc.o依赖文件,没有将的话会将依赖方法放入栈中……如下图:
make解释makefile的时候,是会自动推导的,一直推导,此时不会执行依赖方法(将依赖方法放入栈中),直到推导到有依赖文件的存在,然后逆向执行所有依赖方法。
这里插一句,我们如果没有目标文件直接-c会直接生成同名汇编的.o文件:
但是我们一般不会这么写,太冗长了,我们一般这样写:
这是因为你在Windows中,一般生成可执行文件时,是会生成一个同名的.obj文件的,所以我们一般会这样写makefile。
七、makefile使用技巧
当我们写一个项目时,可能不止一个.c文件,此时如果我们想像C语言一样,可以使用宏替换,如果要修改文件,只需要把宏给替换即可,不需要一个一个替换变量,makefile可以吗?当然可以,因为makefile支持通配符,所以可以这样使用:
makefile也可以定义变量,可以不用带类型。此时我们再修改一下makefile文件:
因为未来我们不可能只有一个.c文件,所以利用此方法有点像C语言中的宏定义。
而且我们还可以这样修改:
所以最终的makefile版本应该这么写。
八、生成多个可执行文件
此时我们再写一个code.c文件,并修改makefile文件:
此时可以发现只形成了一个proc可执行文件,因为我们在Windows中也是默认形成一个,但是Linux中可以一次形成多个,此时就需要使用其他技巧了:
生成all就要生成proc和code,此时没有源文件,之后继续向下执行依赖方法(依赖方法入栈),最终会生成proc和code可执行文件,并生成all目标文件。
总结:
此时我们已经理解了大部分的makefile的原理,当前知识已经完全够我们使用,接下来我们先利用这些已学过的知识来完成一个进度条小项目(下一篇敬请期待)。