VxWorks操作系统MakeFile

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

VxWorks操作系统MakeFile(一)

时间:2008-8-24 夜

版权申明:本文为水煮鱼为水煮鱼@博客园撰写,不得用于商业用途,如需摘用,请与水煮鱼联系。

1、介绍

本文将介绍为什么要将你的C源代码分离成几个合理的独立文档,什么时候需要拆分,那又怎么拆分呢?

然后再介绍如何使用GUN Make使你的编译和链接步骤自动化。可能你使用的是其他的make工具,但是其实道理都差不多。当然如果你对自己的编程工具有怀疑的话,可以不妨实际的试试。

2、多文件项目介绍

a. why?

为什么使用多文件项目?他们有什么好处呢?

从表面上看,多文件项目是够复杂的了,又要头文件,又需要extern申明,并且如果你要查找一个文件的话,还需要在更多的文件里搜索。

但是如果把其考虑成一个项目,那一个项目根据功能划分为小的模块,那就不难理解了。

想想如果是一个一万行代码,如果你把其放到一个文件里,则在编译的时候,则需要对一万行代码进行重新编译。不过如果你如果把其放到不同的文件里,那修改一行,则只需要编译一个文件就可以了。可能你会说,一万行代码,就算全部编译,那点时间也基本可以忽略不计,但是实际情况是,在一个大的系统里,可能代码达到几十万甚至上百万,千万行代码的规模。以我们的项目为例,目前代码规模已经达到了上千万行的级别,如果全部重新编译,则将耗费几个小时甚至半天的时间。如果将其划分多多个文件,则修改一行所引入的编译代码,将不会随着你代码规模的增大而增大。所以多个文件的优点不言自明了。

不过对于不便于搜索的问题,其实只要文件划分得当,也并不会造成多大的困难。其实,从多个目标文件生成一个程序包比从一个单一文件生成程序包要好的多。当然,实际上这是不是一个优势还与你所使用的系统有关。但是当使用gcc/ld(一个GUN C编译器/连接器)把一个程序包连接到一个程序时,在连接的过程中,它会尝试不去连接没有使用到的部分,但它每次只能从程序包中把一个完整的目标文件排除在外。因此,如果你修改了一个程序包中某一个目标文档中任何一个符号的话,那么这个目标文件整个都会被连接进来。要是一个程序包被非常充分的分解的话,那么经过链接后,得到的可执行文件会比从一个大目标文件组成的程序包连接得到的文件小的多。

并且常常我们的程序是模块化的,高内聚,低耦合,使得文件之间共享部分被减少到了最少,因此采用多文件的方式,可以比较容易的找到代码中的bug。

b.when?

那什么时候分解你的项目?

如果你开发的是一个大项目,在开始前,应该好好考虑一下你将如何实现,并且将生成几个文件来存放你的代码。当然,在项目的开发过程中,你可以建立新的我文件,但是这将打乱你的整体布局,可能造成你整体结构的调整。因此特别建

议在做之前,需要想想细细的考虑清楚,开发过程中允许有小范围的调节,但是涉及到整体结构的修改,将为你的项目引入过多的风险。

如果你开发的是一个中型的项目,你可以向上面介绍的那样,想清楚了再开始动手,但是你也可以想当然的写到哪就到哪,当你发现你的代码已经多到难以管理的时候在进行分解,但是希望你尽量先有一个好的谋局后,再动手,你将花费的代码最小。

c.how?

如何分解呢?

一下仅仅是个人的建议,如果你有自己的风格的话,如果你认为更好,那请保持你原来的做法:

i. 不用使用一个header指向多个源代码。使用一个头文件对应一个源代码文件,不仅更容易查询,方便代码的阅读,而且,无需修改一个头文件,而引起更多的文件的重新编译。

ii.如果可以的话,推荐采用多个头文件指向一个源代码文件的方式。有时将不可公开调用的函数原型,类型定义等,从它们的C源嗲吗文件中分离出来是非常有用的。可以使用一个库文件装共用的变量,而使用另外一个库文件装私用的变量,这样不会导致你修改源代码文件的内部结构时,你只需要重新编译这个源代码文件,而无需重新编译调用了公开的库文件的其他源代码。

iii.不要再多个库文件中重复定义。这个不说,大家应该都知道为什么了。

iv. 在每一个源代码文件中,#include那些申明了源代码符号的所有头文件。这样一来,你在源文件和头文件对某些函数做出的矛盾声明就可以比较容易的被编译器发现。

编译中常见的一些错误:

1、定义符在源码文件中的矛盾。

在C语言里,变量和函数的缺省状态是公用的。因此任何C源码的文件都可以引用存在于其他源码文件中的全局函数和全局变量,即使在这个源码文件中,并没有该全局函数或者全局变量的声明或者原型。因此你必须保证在你的全局函数或者全局变量没有重复的定义,否则在连接的时候会出现错误,可能在编译的时候也会提示告警。

解决方法:一种有效的解决方法,就是在你申明的全局函数或者全局变量名前,加入一个可以区分文件的前缀名:比如如果在gfx.c里的函数完全就可以加上前缀名gfx_。

如果要防止一个符号在它被定义的源文件以外看到,可以在它的定义前加上关键字“static", 则该关键字定义了该符号的局部属性,仅能在定义的文件内使用。(请注意,改关键字”static“的使用与局部变量定义时的区别)。

2、多次定义的符号。

当你用#include包含一个库文件的时候,实际上在编译的时候仅仅是在该处使用你包含的库文件逐字替换。如果头文件被#include到多个文档中时,该头文件中的所有定义都会在你引用的源代码中重新定义一次。重复定义,会导致链接出现错误。

解决方法:不要在头文件中定义变量。定义变量一般放到使用他们的源码问文件中,而在其他文件中声明一下就可以了。对于初学者来说,定义和声明,总是

容易混淆。定义的时候,编译器会给该变量分配实际的内存空间,而声明,仅仅是通知编译器该变量存在,并且告知该变量的类型。声明一个变量的时候,需要在它的前面加上extern的关键字。

由于函数的原型中已经有了隐式的extern,所以不要考虑该问题。

3、重复定义、重复声明或者类型矛盾

考虑如果你的源码文件中#include了头文件a.h和b.h,但是你的头文件中a.h又包含了b.h,则编译的时候会出现什么结果呢?很明显,b.h中定义的宏或者声明都会被执行两次。从理论上讲,这样的重复都是完全一样的拷贝,不会出现问题,但是在实际的编译中,这是不符合C的基本语法,可鞥编译的时候会出现错误,至少也是一个告警。

解决办法:确定每一个头文件中在任何一个源码文件中仅仅包含了一次。但是随着代码规模的扩大,通过认为控制的手段实在有点低效。聪明的方法是使用预处理器。

常用的用法是:

#ifndef MACRO_XXXX

#define MACRO_XXXX XXXX

#endif

但是如果每一个宏都这么放一条,是不是显得也太低效了呢?(还不说,我还真的看到了这么做的,呵呵!!)

在实际的应用中,我们只需在头文件的开头处定义:

#ifndef FILENAME_H

#define FILENAME_H

在库文件的最后处定义:

#endif

使用库文件的文档名代替上面的FILENAME就可以了

Makefile的结构:

一般编译的步骤为:

1、将每一个单独的源代码文件首先编译成为目标文件。

2、通过链接器,将目标文件连接成为可执行文件。

由于本文只讨论vxworks中的makefile,因此本文主要以常用的gcc为例。

通过-c开关,可以使用gcc将源文件编译成为期望的目标文件。生成文件以.o为后缀名。然后通过命令gcc -o exec_filename *.o,将生成的目标文件连接成为可执行文件。在gcc中,生成的可执行文件以.out为后缀名。

对于一个多文件的项目,这些非常繁琐。但是GNU Make工具让一切都可以变得很简单。

GUN Make的输入是一个文本文件:makefile。在这个文件中,主要描述了目的文件是从那些依靠文件中产生的关联关系。根据文本中描述的关系,make通过检查磁盘上的文件,如果目的文件的时间戳比至少它一个依靠文件的时间戳旧的话,make工具将执行相应的命令,以更新目的文件。

相关文档
最新文档