Chinaunix首页 | 论坛 | 博客
  • 博客访问: 118943
  • 博文数量: 121
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 1210
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-03 23:43
文章分类

全部博文(121)

文章存档

2011年(1)

2010年(6)

2009年(114)

我的朋友

分类: LINUX

2009-10-04 00:37:29


概述

Linux环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员,至少不能称得上是Unix程序员。在Linuxunix)环境下使用GNU make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要我们投入一些时间去完成一个或者多个称之为Makefile文件的编写。此文件正是make正常工作的基础。

所要完成的Makefile文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建那些库文件以及如何创建这些库文件、如何最后产生我们想要得可执行文件。尽管看起来可能是很复杂的事情,但是为工程编写Makefile的好处是能够使用一行命令来完成“自动化编译”,一旦提供一个(通常对于一个工程来说会是多个)正确的Makefile。编译整个工程你所要做的唯一的一件事就是在shell 提示符下输入make命令。整个工程完全自动编译,极大提高了效率。

make是一个命令工具,它解释Makefile中的指令(应该说是规则)Makefile文件中描述了整个工程所有文件的编译顺序、编译规则Makefile有自己的书写格式、关键字、函数。像C语言有自己的格式、关键字和函数一样。而且在Makefile中可以使用系统shell所提供的任何命令来完成想要的工作Makefile(在其它的系统上可能是另外的文件名)在绝大多数的IDE开发环境中都在使用,已经成为一种工程的编译方法。

目前,系统完整的介绍make工具和如何编写Makefile的中文文档比较少。我整理这个文档就是希望能使众多的Linux环境下的程序员能够比较容易的掌握和学会使用GNU make。本文所要介绍的是GNUmake,采用Red Hat FC3(包括最新发布的GNU Linux系统)所集成的GUN make工具。

本文中所有示例均采用C语言的源程序,因为它是目前最普遍使用的一种语言。当然make工具不仅仅是用来管理C语言工程的,只要那些编译器能够在shell下运行的语言所构建的工程都可以使用make工具来管理[i]Make工作不仅仅可以用来编译源代码,它也可以完成一些其它的功能。例如,有这样的需求:当我们修改了某个或者某些文件后,需要能够根据修改的文件来自动对相关文件进行重建或者更新。那么应该考虑使用GNU make工具。GNU make工具为我们实现这个目的提供了非常有利的支持。工程中根据源文件的修改情况来进行代码的编译正是使用了make的这个特征。make执行时,根据Makefile的规则检查文件的修改情况,决定是否执行定义的动作(那些修改过的文件将会被重新编译)。这是GNU make的执行依据。

准备知识

在开始我们关于make的讨论之前,首先需要明确一些基本概念:

编译:把高级语言书写的代码转换为机器可识别的机器指令编译高级语言后生成的指令虽然可被机器识别,但是还不能被执行。编译时,编译器检查高级语言的语法、函数与变量的声明是否正确。只有所有的语法正确、相关变量定义正确编译器就可以编译出中间目标文件。通常,一个高级语言的源文件都可对应一个目标文件。目标文件在Linux中默认后缀为“.o”(如“foo.c”的目标文件为“foo.o”)。

为了和规则的目标文件相区别。本文将编译高级语言后生成的目标文件成为.o文件。

链接:将多.o文件,或者.o文件和库文件链接成为可被操作系统执行的可执行程序(Linux环境下,可执行文件的格式为“ELF”格式)。链接器不检查函数所在的源文件,只检查所有.o文件中的定义的符号.o文件中使用的函数和其它.o或者库文件中的相关符号进行合并,对所有文件中的符号进行重新安排(重定位),并链接系统相关文件(程序启动文件等)最终生成可执行程序。链接过程使用GNU 的“ld”工具。

静态库:又称为文档文件(Archive File)。它是多个.o文件的集合Linux中静态库文件的后缀为“.a”。静态库中的各个成员(.o文件)没有特殊的存在格式,仅仅是一个.o文件的集合。使用“ar”工具维护和管理静态库。

共享库:也是多个.o文件的集合,但是这些.o文件时有编译器按照一种特殊的方式生成(Linux中,共享库文件格式通常为“ELF”格式。共享库已经具备了可执行条件)。模块中各个成员的地址(变量引用和函数调用)都是相对地址。使用此共享库的程序在运行时,共享库被动态加载到内存并和主程序在内存中进行连接多个可执行程序可共享库文件的代码段(多个程序可以共享的使用库中的某一个模块,共享代码,不共享数据)。另外共享库的成员对象可被执行(由libdl.so提供支持)。

参考 info ld了解更加详细的关于ld的说明和用法。


[i] 高级语言主要是相对于汇编语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,如目前流行的VBVCFoxProDelphi等,这些语言的语法、命令格式都各不相同。 

高级语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行,按转换方式可将它们分为两类


解释类:执行方式类似于我们日常生活中的同声翻译,应用程序源代码一边由相应语言的解释器翻译成目标代码(机器语言),一边执行,因此效率比较低,而且不能生成可独立执行的可执行文件,应用程序不能脱离其解释器,但这种方式比较灵活,可以动态地调整、修改应用程序。
 

编译类:编译是指在应用源程序执行之前,就将程序源代码翻译成目标代码(机器语言),因此其目标程序可以脱离其语言环境独立执行,使用比较方便、效率较高。但应用程序一旦需要修改,必须先修改源代码,再重新编译生成新的目标文件( .OBJ)才能执行,只有目标文件而没有源代码,修改很不方便。现在大多数的编程语言都是编译型的,例如Visual C++、Visual FoxproDelphi

阅读(803) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~