Makefile的简介
一个工程中的源文件数不胜数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
依赖关系和依赖方法
示例:使用make指令将当前目录下的main.c文件编译生成一个名为hello的可执行程序。main.c的内容是非常简单的printf一句字符串hello world。
1、首先我们需要在构建项目的目录下创建一个名为“Makefile” 或 “makefile” 的文件。然后以文本方式打开Makefile编写里头的内容,写上依赖关系和依赖方法:
hello:main.c 是 依赖关系,表示hello的生成需要依赖main.c这个文件,main.c是依赖文件,而hello是目标文件。
gcc main.c -o hello 是 依赖方法,表示生成目标文件hello所需要执行的方法。注意:依赖方法必须以一个制表符Tab开头,即键入一个Tab,而不能以多个空格代替Tab。
2、 然后我们保存并退出Makefile文件,执行make指令,就能帮我们自动执行生成目标文件的指令,hello可执行文件就随之生成好了,就像在Visual Studio中的生成解决方案那样方便。
扫描二维码关注公众号,回复: 17475266 查看本文章![]()
如果不想上面红框里的 gcc main.c -o hello 依赖方法被回显出来,可以在编辑Makefile的依赖方法前面加上@。
保存并退出,我们rm掉之前生成hello可执行文件,再次运行一下make命令,这次就没有依赖方法的回显了。
清理项目
好了,现在可以使用make指令方便的构建项目了,那么现在我们要使用make clean来清理掉所构建的项目,就像在Visual Studio中的清理解决方案一样。
我们打开之前的Makefile,添加上如下的内容,目标文件clean的名字是用户自定义的,clean没有对应的依赖文件:
保存退出,然后输入make clean命令:
我们的hello就顺利的被清理掉了,至于.PHONY干什么用,,后面详细讲解。
推导多个依赖关系
上面我们直接将main.c编译生成了hello的可执行文件。我们也可以像下面这样把编译链的过程详细写出来生成可执行文件,依赖关系为hello -> main.o -> main.s -> main.i -> main.c:
保存退出,执行make命令:
这个过程有点类似于递归,即如果找不到生成目标文件所需的依赖文件,则会往下查看这个依赖文件是否可以通过其依赖关系和对应的依赖方法生成,不断进行上述过程,直到我们所需的依赖文件出现为止,然后通过这个依赖文件不断回溯构造出每一层所需的依赖文件,如果该过程结束了还是没找到对应的依赖文件,那么makefile则会终止执行并报错。
.PHONY
我们在上面使用.PHONY来定义clean为伪目标,表示目标文件clean不是一个真实存在的文件,执行make clean时能够直接执行对应的依赖方法。.PHONY适用于那些不生成实际文件的任务,如清理临时文件、构建依赖于时间戳的任务等,使用.PHONY定义伪目标的方法能够保证生成伪目标的依赖方法总是被执行的。
.PHONY可以让编译源文件时忽略掉源文件和可执行程序的修改时间对比,即不管如何都直接重新编译生成可执行文件。
假如我们目录中已经有一个hello可执行文件了,我们再次执行make命令想要重新编译生成一个新的hello可执行文件时,会发生错误:
显示hello是最新的版本。因为hello可执行文件的生成依赖于main.c,makefile会检查对比当前目录下的目标文件hello的最后修改时间和main.c的最后修改时间,发现hello的修改时间在main.c之后,证明hello已经是最新的了,不需要再进行重新编译的无用操作。当main.c被再次修改,也就是main.c修改时间在hello之后,再次执行make才能重新编译生成一个新的hello可执行文件。
而我们使用.PHONY将目标文件hello定义为伪目标,那么make就不会通过进行时间对比决定是否重新编译生成新的可执行文件,而是无论如何都会编译生成一个新的hello可执行文件。
将hello目标文件定义为伪目标:
也可以通过列表的方式一次定义多个伪目标。
保存退出,执行make指令:
正常来说不要给hello定义为伪目标,这里只是演示一下。
变量
我们可以在开头定义一些变量,并在下面的多条语句中使用。
这样当我们编译的源文件名不再是main.c,或者要生成的目标文件名不再是hello时,只需要把Makefile里的变量的值修改成别的值即可。这样使用变量来适应变化,减少了硬编码,提供了更高的灵活性。
通配符%的使用
例子:使用makefile来编译链接多个源文件来生成可执行程序,将func.c 和 main.c 编译链接成可执行程序 add。
fun.h func.c 以及 main.c的内容如下:
Makefile文件内容如下:
保存退出,运行make指令:
以上就是使用makefile来自动化编译生成可执行程序的方法。