工程管理器,顾名思义,是指管理较多的文件,Make工程管理器也就是个“自动编译管理器”,这里的“自动”是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量,同时,它通过读入Makefile文件文件的内容来执行大量的编译工作,Make将只编译改动的代码文件,而不用完全编译。
makefile工具是在Linux下的make编译命令的基础上得以存在的。下面说说makefile文件的执行过程:
1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2、如果找到,它会找文件中的第一个目标文件(target),在下面的例子中,他会找到“test”这个文件,并把这个文件作为最终的目标文件。
3、如果main文件不存在,或是main所依赖的后面的 .o 文件的文件修改时间要比main这个文件新,那么,它就会执行后面所定义的命令来生成main这个文件。
4、如果main所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
5、当然,你的c文件和h文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行文件main了。
PS:整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即如果在我找了依赖关系之后,冒号后面的文件还是不在,那么就不工作啦。
1、文件包含:
语法:include 文件名
作用:将其它makefile文件包含进来,组成一个更大的makefile文件,这样有利于makefile模块化编程。通常我们将一些配置选项分开成一个独立的makefile文件,这样有利于makefile文件的管理,或将模块代码的依赖关系和需要编译的文件信息独自写到一个 makefile文件中,最终通过include命令形成一个顶层makefile文件来完成整个工程代码的编译和链接。
2、变量定义
在makefile中,经常先定义一个变量,然后往该变量中追加新的值(通过+=符号),比如先定义一个C_SRCS变量(该值可以为空),然后将代码文件test1.c和test2.c添加到C_SRCS中,其代码如下所示:
C_SRCS :=
C_SRCS += test1.c test2.c
在makefile中有一类特殊的变量,其名称为 自动变量,自动变量的值会依据规则中的target 和 prerequisites(先决条件)自动计算其值,自动变量一般以开头$为起始,下面将列出一些常见的自动变量:
(1) $@ 为规则中的target名称。
(2) $< 为规则中第一个prerequisite名称
3、规则定义:
规则是makefile中最重要的概念,其告诉make 目标文件的依赖关系,以及如何生成及更新这些目标文件。在makefile文件规则有2种,一种是显式规则,另一种是隐式规则。
(1)显式规则用于说明何时及如何重新生成目标,其列出了目标依赖的文件信息,并通过调用命令来创建或更新目标,其语法一般为:
targets : prerequisites
recipe
…
targets为要生成或更新的目标,prerequisites为目标依赖的关系,recipe为生成目标的命令,一个规则可以有多条recipe,比如
foo.o : foo.c defs.h
cc -c -g foo.c
其中foo.o为target,foo.c defs.h 为prerequisites,cc -c -g foo.c为recipe。
(2)隐式规则用于说明何时及如何来重新生成一类目标文件根据其名称,其描述了目标是如何依赖于名称相似的文件(一般来说除去后缀信息,其目标与依赖文件的名称是一样的),并调用命令来创建或更新目标。
4、文件搜索路径设置
Make命令默认会在当前路径中搜索prerequisites中的文件,比如头文件,但我们在写程序时,经常将头文件和源文件隔开放在不同的文件夹下,这种该怎么处理呢?
1、我们可以通过VPATH变量来解决,2、我们可以通过vpath指令来解决。
(1)VPATH变量
VPATH变量为所有的prerequisites指定文件路径,路径之间可以通过 :或空格隔开,比如
VPATH = src:…/headers
(2)vpath指令
vpath指令的作用与变量VPATH的作用差不多,但vpath有更多的灵活性,其语法为:
vpath pattern directories
pattern为需要查找的文件匹配模式信息,directories为要查找的文件路径,例如:
vpath %.h ../headers
其代表在上一层文件夹headers中查找 .h头文件信息。
在学习了上面的makefile编写的知识以后,下面我将写一个简单的makefile文件实现一下我多个文件的编译工作。如下:
test:main.o channle.o
gcc main.o channle.o -o test
main.o:main.c function.h
gcc -c main.c -o main.o
channle.o:channle.c WavHead.h
gcc -c channle.c -o channle.o -std=c99
.PHONY:clean
clean:
-rm -rf *.o
执行的过程简单说就是最终需要生成一个名为test的文件,这个文件需要main.o和channle.o,于是继续往下执行,然后通过命令gcc -c main.c -o main.o得到了main.o文件,同理再得到channle.o文件,最后通过命令gcc main.o channle.o -o test进行链接最终就会得到一个名为test的可执行文件了。
上面的代码在linux的命令窗口下输入make命令就可以执行了,最终会生成一个test的可执行文件。 如果需要清除生成的中间.o文件,输入make clean就可以全部清除了。
PS:(.PHONY)是伪目标标记, 伪目标标记后的命令,不会和目录下文件重复,也就是说clean如果没有伪目标标记的话,目录下有一个clean的文件make clean将不会正确执行!
参考文章:
参考1
参考2