make与makefile浅谈
最近, 看了一些关于makefile方面的一些知识.我想写下来以防自己在将来忘记,同时也给自己在学习的过程中留下一些脚印.(最近,老觉得记忆力差).
其实,之前我就对makefile有过一定的了解,现在想在那个基础上在做一下更深的介绍.因为自己对make和makefile有了更深一层的认识.
本文主要将make的过程以及makefile的一些基本结构,如果想更深\更详细的了解makefile可以阅读gun make或者到gun官方网站上找gun manual.那里有很详细的描述.
在阐述Makefile文件之前,我觉得先对我们天天的代码有一个比较全面本质的理解是非常必要的,那就是如何让我们的代码能够运行起来。这些对windows成程序员来说可能是一点必要都没有,但是对linux程序员来说是非常必要的,如果你想成为一个能够在linux环境下熟练的写代码并能很好的运行(像你所希望的那样)。
那么在linux环境下,写好了代码之后到底还要做一些什么事呢?在linux,环境下,具体的工作是:
1、编译:一般来说,无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译。编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。其实,编译器并不是一个单一的庞大的程序。他们通常由多达六七个小的程序所组成。这些程序由一个叫做“编译驱动器(compiler driver)”的控制程序来调用。这些可以方便地从编译器中分离出来的单独程序包括:预处理器(preprocessor)、语法和语义检查器(syntactic and semantic checker)、代码生成器(code generator)、汇编程序(assembler)、优化器(optimizer)和连接器(linker),当然还包括一个调用所有这些程序并想各个程序传递正确选项的驱动程序(driver program)。所有这些编译器的功能都可以在gcc中有选择参数的表示出来。比如-O表示优化。-L表示连接。具体的gcc的编译选项和功能可以参考gun的官方网站。
2.连接:把大量的Object File合成执行文件,这个动作叫作链接(link)。
链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件。
总结一下,源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成Object File。而在链接程序时,链接器会在所有的Object File中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error),在VC下,这种错误一般是:Link 2001错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的Object File.
好,言归正传,GNU的make有许多的内容,闲言少叙,还是让我们开始吧
makefile的结构
本文只是简单的讲一讲makefile文件的一些基本结构.其实很多工程中都把makefile文件命名为Makefile.
在linux环境下,对以个比较大的工程来说,没有Makefile文件几乎是不可能的。Makefile的文件从语法的角度来看主要有三部分组成:目标、建立目标所依赖的文件和具体生成目标文件的命令。
make是如何工作的:
对于make,大部分写过linux代码的人都是很熟悉的.那么make到底是怎么工作的呢?
首先,make命令(或者说是工具)会在同一级目录下找makefile文件.并按照makefile文件中的规则来执行,最后根据依赖文件和命令来生成目标。 通常在Makefile中会有多个目标。比如:all、 install、clean等我们一个make命令之后到底会生成哪个目标?根据gun makefile我们知道,如果我们就在shell下敲入一个make之后那么默认的在makefile中的第一个目标就是我们make多要建立的目标这个目标被称为终极目标。当然,我们也可以自己写入自己想生成的目标。比如make clean(通常这个命令是清除一些临时的中间文件)。
如果不是第一次编译(make),那么编译器就会找从你上一次编译后到这一次编译这段时间你修改了哪些文件并对那些文件和与修改过的文件做编译,与修改文件无关的文件则不做编译。
阅读(743) | 评论(0) | 转发(0) |