浅讲make/makefile【linux】
- 一. 什么是make/makefile?
- 二. makefile
- 2.1 依赖关系与依赖方法
- 2.2 浅用make
- 2.2.1 make test
- 2.2.2 clean
- 2.2 make一次执行多步
- 2.3 部分修饰符号
- 2.3.1 .PHONY(伪目标)
- 2.3.2 @
- 2.3.3 $@ $^
一. 什么是make/makefile?
make/makefile这两个可以说是搭档,缺一不可
make和makefile可以说是做大型项目不可缺少的功能
就本质来讲
make是系统自带的一条指令
makefile则是一个文件
使用make后:
编译器会自己去寻找目录下的makefile文件并执行
可以说make的指令作用:就是执行本目录下的makefile文件
当目录下没有makefile文件的时候就会报错
所以我们在学习make/makefile的功能,主要专注在makefile内部
二. makefile
想用make/makefile功能,直接自己在本目录下创建个makefile文件即可
touch makefile
用vim编辑器进行修改。
发现文件内是全空的,所以我们想要写出能用的makefile文件,需要先了解依赖关系与依赖方法
2.1 依赖关系与依赖方法
这里一条最普通的编译test的makefile指令
让我们看看这两行分别是什么
这里我们能看到一个指令的组成有两个部分:
1.依赖关系
2.依赖方法
接下来我们分别来看一下这两个部分:
依赖关系:
左边可以说是指令名。
使用的时候就是
make test
来执行
test.cpp是test指令依赖的文件。
依赖方法
依赖方法可以说是
编程语言中函数体内的函数内容。
就是执行的指令
2.2 浅用make
了解了具体了以后我们就可以试着来编写两个makefile的文件了
2.2.1 make test
这个就是我们上面的例子,接下来我们来使用一下。
这里随便写了一个test.cpp的文件
这里输入
make test
可以发现这里已经执行了。
发现已经多了个可执行程序,makefile指令已经执行完毕了
2.2.2 clean
相同的,我们也可以写个像C++中的析构函数那样的清理可执行程序的clean指令
clean:
rm -rf test
依赖关系冒号后面没有跟文件,代表这个指令没有依赖文件
这里来执行一下
make clean
发现test可执行程序被删除了
2.2 make一次执行多步
讲这个内容时会涉及到语言的执行过程,如果看不太懂,可以去翻我以前的博客
C语言程序的编译过程
这里的test.i ,test.s,test.o
都是之前程序编译和汇编以及链接的生成文件。
这里如果直接用make test.i会怎么样?
这不是很简单嘛
直接执行
g++ test.cpp -o test.i -E
就结束了。
但是如果我们执行 make test会怎么样?
我们会发现一下执行了全部的指令。
这里让我们来刨析一下过程。
第一步执行test时,发现依赖关系时test.o文件,但是系统查找不到
这是时候就会去寻找具有test.o的命令
这个时候找到 test.o指令,但是发现执行需要test.s,这个时候又会去寻找test.s文件
就这样不停寻找,找到了test.i能进行创建了
这个时候在返回到上一条需要test.i的指令,并执行
就这样一条一条执行并返回,就类似于递归一样的思路
那我们如果随便换个顺序也是结果会怎么样
发现结果不会变,因为顺序不会影响执行
系统是会寻找可以执行的指令,自动去执行,如果没有就报错
就C语言中的函数一样,引用函数不需要注重顺序,只要能被系统找到就可以了
2.3 部分修饰符号
接下来是几个比较基础的修饰符号
2.3.1 .PHONY(伪目标)
在执行makefile时,如果可执行文件已经产生,为了防止重复无意义的执行生成可执行文件指令
会自动判断可执行文件的源文件是否发生变动,从而判断是否要执行编译
例:
这里进行了第一次编译。
第二次执行的时候就会发现,系统会阻止你重复make
那这么高大上的功能是怎么实现的呢?
其实就是通过对比时间而已
我们可以通过
stat 【文件名】
查看文件属性
access:访问时间
对文件内容进行修改:modify
对文件属性进行改变:change
这里要注意:对文件属性进行修改,文件内容的时间一般也会修改
因为文件内容有一个size的属性
按道理来说,对文件执行指令,access时间都要进行改变
但是因为access变化实在是太过于频繁,文件处于磁盘中,多个用户访问文件都要改变access,导致服务器十分卡顿
所以较新版中,只有对文件进行一定量的操作后才能会进行改变access时间
所以make文件对源文件进行依赖关系的操作的时候
会将可执行程序的时间转化为时间戳,将.cpp文件的修改时间转化为时间戳
进行比较,判断是否要执行指令
这里如果想要取消时间戳对比
就可以添加.PHONY修饰(伪目标)
但是不推荐将生成可执行文件用伪目标进行修饰
这里就可以随便进行执行了,不用进行时间戳的对比。
2.3.2 @
我们在输入了make后
make会自动弹出makefile中执行指令的依赖方法
加了@后,就可以防止弹出依赖方法
2.3.3 $@ $^
这两个修饰符主要用在依赖关系上
这两个分别代表了依赖关系的两边
那具体有什么用呢?
写依赖方法的时候就可以用符号代替文件名了
这里能发现文件正常执行了。