makefile
有什么用?本篇文章小编将详细介绍
会不会写makefile
,从侧面说明一个人具不具备完成大型工程的能力
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
makefile
带来的好处就是——“自动化编译”,一旦写好,只需要一个make
命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make
是一个命令工具,是一个解释makefile
中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make
。可见,makefile
都成为了一种在工程方面的编译方法。
make
是一条命令,makefile
是一个文件,两个搭配使用,完成项目自动化构建。
实例代码:
首先创建一个code.c
文件,在该文件中写一个测试代码
#include<stdio.h>
int main()
{
printf("hello gwj!\n");
return 0;
}
创建一个makefile
文件:
使用vim
指令,进入makefile
:
使用如下代码:
mytest:code.c
gcc -o mytest code.c
保存并退出
使用make
指令,可直接生成mytest
运行文件
清除操作:
进入makefile
文件,使用如下指令:
.PHONY:clear
clear:
rm -f mytest
保存并退出后,使用make clear
指令可删除mytest
运行文件
以上代码实例快速感受一下make
指令
make
是一条命令,makefile
是一个文件,两个搭配使用,完成项目自动化构建。
mytest:code.c
称之为依赖关系
mytest
是目标文件,使用make
命令后,生成的运行文件叫mytest
code.c
是依赖文件列表,如果有多个时使用空格符隔开,例如:code.c code1.c code2.c code3.c
gcc -o mytest code.c
称之为依赖关系,前面必须是Tab
键开头,不能是四个空格
此时,makefile
写好之后,运行make
,会在当前目录里找makefile
,读取makefile
里的内容,根据依赖关系去形成目标文件。如何去形成呢?根据gcc
这样的一个依赖方法形成。
换句话来说就是,make
会读取makefile
里面的内容
- 什么是依赖关系?? 在大学,到了月底,身为尾款人的你打电话给你爹要点生活费:“爹,我是你儿子!” 这句话中,“我是你儿子”表明了两人的关系,表明你需要依赖于你爹,这就是一个依赖关系。
- 什么是依赖方法?? 此时呢,你爹就把电话挂了,心想:是我儿子就是我儿子呗,有病吧。现实生活中,光有依赖关系没有用,需要表明你想做什么,此时你又把电话打回去:“我没有生活费啦,给我打钱!” 这里的要钱就是表明了依赖方法
clear
是一个种特殊的依赖关系,clear
也是目标文件,只不过后面什么都不跟
rm -f mytest
是依赖方法,是删除文件
.PHONY:
在读取makefile
文件内容时,是从上往下读取,默认认形成第一个目标文件
习惯上把形成可执行程序放在上面,make
就可以直接形成
在编译时,默认情况下,如果可执行程序是最新的了,make
就不会再去编译,如果就想让编译这个操作总是可以被执行,使用.PHONY:XXX
,这里的XXX
对应的方法总是可以被执行的。
一般清理项目会总是执行,因此习惯上会有:.PHONY:clear
如果项目种存在很多个源文件,如果在这些源文件中只进行了很小的改变,如果去把所有的源文件重新编译一遍,会带来很大的效率延缓,效率很低。更重要的是,如果每次都重新编译,源代码可能都没有改,重新去编译效率会很低。
这要做的主要目的是提高编译效率。
Modify
是修改时间,可执行文件和源代码文件最近修改时间不可能一样
因为永远是先写源代码,即使修改代码,也是先修改,再形成可执行程序。
因此,makefile
只需对比可执行文件最近修改时间和源文件最近修改时间,如果可执行文件最近修改时间新,就不需要重新编译;如果源文件最近修改时间新,就需要重新编译。
如果被.PHONY:
修饰,就忽略了时间,于是可以总是被执行
code.exe:code.c
gcc -o $@ $^
可以理解为取内容,@表示目标文件,^表示依赖文件 @表示取code.exe文件,
make
时会自动替换成gcc -o code.exe code.c
make
会根据文件的依赖关系,进行自动推导,帮助我们执行所有相关依赖方法。当前的依赖关系如果不存在,就将当前依赖关系入栈,如果下一个依赖关系存在导致当前依赖关系存在,则当前依赖关系出栈,这里就相当于一个递归。
最终需要的目标文件一定要在第一个,后面的可以乱
我们自己在使用makefile
时没必要像上述代码那样写,没必要纠结那么多选项,直接可以这样写:
code.exe:code.c
gcc -o $@ $^
使用变量替换:
1 bin=code.exe
2 src=code.c
3
4 $(bin):$(src)
5 gcc -o $@ $^
6 .PHONY:
7 clean:
8 rm -f $(bin)
此时照样可以编译,在makefile
中是可以定义变量的