本期博客我们的任务就是搞懂自动化构建工具——make/Makefile
一、什么是make/Makefile
📌make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
📌makefile是一个文件,和make指令搭配使用,可以完成项目自动化构建。
会会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
二、make/Makefile的使用
我们要想使用好这个自动化构建工具首先得要有一个文件名为Makefile(makefile)的文件,有了这个Makefile文件后,我们可以在Makefile文件中编写其中的依赖关系和依赖方法,最后在我们使用make指令时,系统会自动查看Makefile文件中的内容进行自动化操作。
下面是使用make/Makefile的实际举例:
第一步:touch一个Makefile
📋这里不必多说,直接touch:
第二步:编写Makefile
make指令所要进行的操作都是从Makefile文件中读取的,编写好Makefile文件是重中之重
Makefile文件的内容主要包含两个部分:依赖关系和依赖方法
依赖关系
依赖关系,是指一个文件和另一个文件的关系,用:来表示,冒号两边由两个文件名构成,意思是前一个文件来源于后一个文件(当然当前一个文件没有来源文件时冒号后面也可以不写)
📌具体操作为:目标文件名 : 来源文件名
📋我们来举个栗子:
我们来看到这四个依赖关系,由上至下分别表示的是:text.exe文件源于text.o文件、text.o文件源于text.s文件、text.s文件源于text.i文件、text.i文件是最终依赖没有来源文件。
依赖方法
有依赖关系我们可以知道两个文件是有关联的,那它们具体是怎么依赖的呢?
在这里依赖方法就起了重要作用:由一段指令来解释两个文件之间是怎么依赖的
📌依赖方法具体写法为:在相对应的依赖关系下,空一段tap的距离,然后用指令来表示两个文件的形成关系
📋例如:
上面的每个依赖关系下面都标明了依赖方法,从上到下意思依次为:text.exe文件源于text.o文件具体指令为:gcc -o test.exe test.o;text.o文件源于text.s文件具体指令为:gcc -c -o test.o test.s;text.s文件源于text.i文件具体指令为:gcc -S -o test.s test.i;text.i文件具体指令为:gcc -E -o test.i test.c
第三步:make一下
最后我们只需要输入make指令,系统会自动查看Makefile文件中的内容进行自动化操作
📋例如我们上面编写的Makefile文件,make指令会先找到第一个依赖关系,第一个依赖关系依赖第二个依赖关系,所以找到第二个依赖关系,而第二个依赖关系依赖第三个依赖关系,所以找到第三个依赖关系,而第三个依赖关系依赖第四个依赖关系,所以找到第四个依赖关系,最后第四个依赖关系没有依赖文件,所以开始依次执行第四个依赖方法、第三个依赖方法、第三个依赖方法········ 一直到第一个依赖关系的依赖方法执行完毕。这可以看到make指令读Makefile文件时用到了栈的原理,先进后出:
三、多个依赖关系下make指令执行原理
上述例子虽然有多个依赖关系,但是每个依赖关系都与下一个依赖关系有联系,所以执行时可以将其看成一个整体(相当于一条依赖关系)
📋现在我们再加一条与上面没有任何联系的依赖关系(clean):
💡那我们该怎么单独执行clean依赖关系的指令呢?
将make指令后加上想要执行的依赖关系即可:
💡那我们在上一个例子make后面没有加上任何依赖关系为什么还可以执行呢?
这是因为make指令在后面没有任何依赖关系时默认执行第一条依赖关系!
四、 .PHONY
📋在我们make之后,继续执行make指令可以发现系统提示已经是最新的了,不会再去执行一遍:
但是.PHONY可以让指定的依赖关系总是被执行
📋在.PHONY后面加上指定的依赖关系:
我们多次使用make指令:
我们发现我们每输入一遍不管之前是否被执行过都会再执行一遍。
💡这里有个小问题:make是怎么知道我们所编译代码形成的可执行程序是否是最新的呢?
这是根据源代码文件的最新修改时间和可执行程序最近被编译的时间来决定的:如果可执行程序在源代码文件的最新修改时间只后形成,说明已经是最新的可执行程序了;反之make就认为可执行程序旧于源文件,将会重新生成一份新的可执行文件。
五、$@和$^
我们在编写Makefile时,可以使用$@代表依赖关系中的目标文件,用$^代表依赖关系中的来源文件
📋例如:
在上面这个Makefile中$@代表Mytest这个目标文件,而$^代码test.c这个来源文件。
写完运行一下该指令:
完全没问题~
本期博客到这里就结束了
我们下一期见~