本文主要讲解“如何使用makefile”。本文的解释简单明了,易学易懂。请跟随边肖的思路一起学习和学习“如何使用makefile”!
概述
什么是生成文件?可能很多Winodws程序员都不知道这个事情,因为那些Windows IDEs已经为你做了这个工作,但是我觉得要做一个好的、专业的程序员,makefile还是需要理解的。就好像现在有那么多的HTML编辑器,但是如果你想成为一个专业人士,你还是需要知道HTML标志的含义。尤其是Unix下的软件编译,忍不住自己写makefile。你会写makefile吗?这从一个侧面说明了一个人是否有能力完成大型项目。
因为makefile关系到整个项目的编译规则。一个项目中的源文件不计算在内,按照类型、功能、模块分别放在几个目录中。makefile定义了一系列规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至执行更复杂的功能操作,因为makefile就像一个Shell脚本,它也可以执行操作系统的命令。
makefile的优点是——“自动编译”。一旦写好,只需要一个make命令,整个项目完全自动编译,大大提高了软件开发的效率。Make是一个解释makefile中指令的命令工具。一般来说,大多数ide都有这个命令,比如Delphi的make,Visual C的nmake,Linux下的GNU的make。可见makefile已经成为工程上的一种编译方法。
现在关于如何写makefile的文章很少,这也是我想写这篇文章的原因。当然,来自不同制造商的make是不同的,有不同的语法,但其本质是制造一个“文件依赖”的问题。这里我只说GNU make,我的环境是红帽Linux 8.0,make的版本是3.80。没想到,这种制作是应用最广、使用最多的。并且最符合IEEE 1003.2-1992标准(POSIX.2)。
00-1010在这里,我想多说一些程序编译的规范和方法。一般来说,不管是C、C还是pas,首先都要把源文件编译成中间代码文件,也就是,Windows和下的obj文件。UNIX下的文件,即目标文件。这个动作叫做编译。然后,大量的对象文件被合成为可执行文件。这个动作叫做链接。
编译时,编译器需要的是正确的语法和函数、变量的正确声明。对于后者,通常需要告诉编译器头文件的位置(头文件应该只是一个声明,定义应该放在C/C文件中)。只要所有语法正确,编译器就可以编译中间目标文件。一般来说,每个源文件应该对应一个中间目标文件(O文件或OBJ文件)。
在链接时,我们主要链接函数和全局变量,所以我们可以使用这些中间目标文件(O文件或OBJ文件)来链接我们的应用程序。链接器不关心函数所在的源文件,只关心函数的中间对象文件。很多时候由于源文件太多,编译生成的中间对象文件太多,链接时需要明确指出中间对象文件名,对于编译来说非常不方便。所以我们需要为中间对象文件做一个包,在Windows下叫做“库文件”,也就是,lib文件,它在UNIX中。
综上所述,源文件会先生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检查程序语法以及是否声明了函数和变量。如果没有声明函数,编译器会给出警告,但它可以生成一个对象文件。当链接程序时,链接器将在所有对象文件中寻找函数的实现。如果找不到,它将报告一个链接器错误。在VC下,这个错误一般是:Link 2001错误,表示链接器找不到函数的实现。您需要指定函数的对象文件。
好了,让我们言归正传。GNU的make有很多内容,让我们开始吧。
当执行
关于程序的编译和链接
make命令时,需要一个Makefile来告诉make命令如何编译和链接程序。
首先,我们用一个例子来说明Makefile的编写规则。从而给大家一个有趣的理解。这个例子来自GNU的make手册。在这个例子中,我们的项目有8个C文件和3个头文件。我们将编写一个Makefile来告诉make命令如何编译和链接这些文件。我们的规则是:
1)如果这个项目还没有编译,那么我们所有的C文件都要编译链接。
2)如果这个项目的一些C文件被修改,那么我们只编译修改后的C文件并链接目标程序。
3)如果这个项目的头文件发生了变化,那么我们需要编译引用这些头文件的C文件,并链接目标程序。
只要我们的Makefile写得好,只需要一个make命令就可以完成这一切,它会根据当前文件修改情况,自动智能地判断哪些文件需要重新编译,从而自己编译。
的文件和链接目标程序。
一、Makefile的规则
在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则。
target ... : prerequisites ... command ... ...
-
target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
-
prerequisites就是,要生成那个target所需要的文件或是目标。
-
command也就是make需要执行的命令。(任意的Shell命令)
这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。
说到底,Makefile的东西就是这样一点,好像我的这篇文档也该结束了。呵呵。还不尽然,这是Makefile的主线和核心,但要写好一个Makefile还不够,我会以后面一点一点地结合我的工作经验给你慢慢到来。内容还多着呢。:)
二、一个示例
正如前面所说的,如果一个工程有3个头文件,和8个C文件,我们为了完成前面所述的那三个规则,我们的Makefile应该是下面的这个样子的。
edit : main.o kbd.o command.o display.o / insert.o search.o files.o utils.o cc -o edit main.o kbd.o command.o display.o / insert.o search.o files.o utils.o main.o : main.c defs.h cc -c main.c kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : rm edit main.o kbd.o command.o display.o / insert.o search.o files.o utils.o
反斜杠(/)是换行符的意思。这样比较便于Makefile的易读。我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中,然后在该目录下直接输入命令“make”就可以生成执行文件edit。如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下“make clean”就可以了。
在这个makefile中,目标文件(target)包含:执行文件edit和中间目标文件(*.o),依赖文件(prerequisites)就是冒号后面的那些 .c 文件和 .h文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件 edit 的依赖文件。依赖关系的实质上就是说明了目标文件是由哪些文件生成的,换言之,目标文件是哪些文件更新的。
在定义好依赖关系后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个Tab键作为开头。记住,make并不管命令是怎么工作的,他只管执行所定义的命令。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。
这里要说明一点的是,clean不是一个文件,它只不过是一个动作名字,有点像C语言中的lable一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。要执行其后的命令,就要在make命令后明显得指出这个lable的名字。这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等。
感谢各位的阅读,以上就是“makefile怎么使用”的内容了,经过本文的学习后,相信大家对makefile怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/154112.html