由于才刚接触Makefile不久,这里只能做出一些简单的介绍。
通常,我们建立一个工程,里面存放许多源文件,这时候,就有一些问题产生了。到底哪些文件先编译,哪些需要重编译,哪些根本就不需要编译(假设存在不需要编译的文件,当然,通常在一个工程中是不会出现这种状况的),甚至一些更加复杂的操作,而我们的Makefile就规定了一系列的规则来使这些操作准确无误地进行。其实我们也可以把Makefile看做是一个Shell脚本,虽然它们还是有所区别的。
我们可以来看一下Shell脚本和Makefile的区别。
1)Makefile。
一个makefile由依赖关系和规则两部分内容组成。
A.依赖关系
依赖关系由一个目标和一组该目标所依赖的源文件组成。这里所说的目标就是将要创建或更新的文件,最常见的是可执行文件。
B.规则(规则用来说明怎样使用所依赖得文件来建立目标文件)
target(目标文件或可执行文件) : prerequisities(依赖文件列表,罗列生成target所需的文件或者目标)
command(执行指令,Shell命令)···
这样的规则可以减少重编译,为什么呢?假如我们存在如下的:TestA.c, TestB.c, TestC.c, TestA.h, TestB.h, TestC.h, main.c。
若Makefile中为
test : main.o TestA.o TestB.o TestC.o
g++ -o test main.o TestA.o TestB.o TestC.o
TestB.o : TestB.c TestB.h
g++ -c TestB.c
TestA.o : TestA.c TestA.h
g++ -c TestA.c
TestC.o : TestC.c TestC.h
g++ -c TestC.c
main.o : main.c TestA.h TestB.h TestC.h
g++ -c main.c
则当我们make该文件时,输出:
g++ -c main.c
g++ -c TestA.c
g++ -c TestB.c
g++ -c TestC.c
g++ -o test main.o TestA.o TestB.o TestC.o
执行该文件时输出:
Test A
Test B
Test C
若此时我们改变文件TestA.c中的内容,让其输出Test D,重新make之后输出:
g++ -c TestA.c
g++ -o test main.o TestA.o TestB.o TestC.o
执行该文件时输出:
Test D
Test B
Test C
这说明了只有当prerequisities比target“新”的时候才执行command,减少了重编译次数。
2)Shell脚本
大家都使用过批处理文件吧?从某种程度上说,Shell脚本就是批处理文件。脚本文件是一个可执行文本文件,用户在Shell提示符下所有输入内容都可以放到脚本文件内使用,也就是说,原本在Shell下需要输入的多行命令可以放到Shell脚本文件中,通过使用一个命令完成所有的工作。
3)区别。
A.在Makefile中只能在target下调用Shell脚本和执行Shell命令,而其他地方则不行,但在Shell脚本中,任何地方都可以调用Shell脚本和执行Shell命令
B.在Makefile中一行代码是通过创建一个进程来执行。
C.在Shell脚本中,变量是通过在变量名前加一个$来表示,而在Makefile中,在变量名前加一个$代表Makefile变量,加两个$才代表Shell变量。
其实还有一些通配符或者其他的小区别,在这里就不介绍了。总之,Makefile写得好的话,make命令和Makefile配合使用,能给我们的项目管理带来极大的便利,除了用于管理源代码的编译之外,还用于建立手册页,同时还能将应用程序安装到指定的目录。