VxWorks操作系统MakeFile.doc_第1页
VxWorks操作系统MakeFile.doc_第2页
VxWorks操作系统MakeFile.doc_第3页
VxWorks操作系统MakeFile.doc_第4页
VxWorks操作系统MakeFile.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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工具将执行相应的命令,以更新目的文件。一个makefile主要含有以下的规则:.(tab)(tab).例:=make file 开始=myprog:foo.o bar.ogcc foo.o bar.o -o myprogfoo.o: foo.c foo.h bar.hgcc -c foo.c -o foo.obar.o: bar.c bar.hgcc -c bar.c -o bar.o=make file 结束=这是一个非常典型的makefile。make从最上面开始,把上面第一个目的, myprog,作为它的主要目标。给出跪着说明只要文件myprog比文件foo.o或者bar.o中的任何一个旧,则下一行命令将会被执行。但是在检查文件foo.o和bar.o的文件戳之前,它会往下查找那些把foo.o或者bar.o作为目标文件的规则,以此递归,直到找到最新的目标文件,并执行该目标文件下的命令。 从此可以看出,make工具通过这种递归查找最新时间戳的方式,保证当你修改任何代码的时候(可能是只有修改了一个源码文件,或者一个头文件),保证与之关联的文件都可以被编译。当然,你必须保证你在makefile中写的编译规则,都是正确的,只列出了那些在源码文件中被包括的头文件。编写Make的规则:通过上节的介绍,知道了怎么去生成一个makefile文件。当文件较少的时候,采用上述的方法是可行的。但是随着文件数目的增加,已经各个文件相互依赖关系变复杂以后,以上生成makefile的方式已经不再具有可行性了。幸好很多编译器都具有自动生成makefile的功能。以gcc为例:打开-m开关,则gcc可以将你输入的C文件,根据其中包含的头文件自动生成依赖文件。注意,如果采用-mm的方式,采用“”方式包含的头文件将不生成依赖文件。通过gcc生成的makefile,不会包含命令部分,该部分你可以自己补充,或者直接使用它的隐藏规则。 为了便于编写makefile文件,下面将具体介绍生成的makefile文件中的一些基本概念:1、makefile变量makefile变量类似于环境变量,起对大小写敏感,一般使用大写字母表示,它可以在任何地方引用,主要具有如下的功能:a. 用于存储文件列表名。 生成可执行文件的makefile,需要指定一些目标文件作为依赖文件;或者在命令行部分,需要会执行那些文件作为gcc命令的输入文件,通过变量的方式来存储这些文件名,更便于makefile的维护;b.用于存储可执行文件名。 如果你使用的是一个非gcc的编译器,则可能你需要修改所有命令行的使用的gcc的编译名部分,你可以定义一个变量保存编译器名称,则当编译器不同时,简单的修改该变量名称从而实现对不同编译器的命令的整体替代修改。c.存储编译器的旗标。 如果你某些编译命令的选项使用的地方很多,你可以将该部分相同的选项部分定义为一变量,便于对编译命令的维护。其实从上可以看出,这里makefile中变量的功用和一般的代码文件中的变量的功用是一致的。变量的设定:变量名 = 变量的值变量的引用:$(变量名)使用上述规则将前面提到的一个makefile重新整理:=make file 开始=OBJS = foo.o bar.oCC = gccCFLAGS = -Wall -O -gmyprog:$(OBJS)$(CC) $(OBJS) -o myprog foo.o: foo.c foo.h bar.h$(CC) $(CFLAGS) -c foo.c -o foo.obar.o: bar.c bar.h$(CC) $(CFLAGS) -c bar.c -o bar.o=make file 结束=此外还有一些已经定义好的内部变量可以直接引用,常用的有如下几个:i. : 当前规则的目的文件名;ii. :依赖文件列表中的第一个依赖文件名;iii. : 依赖文件列表中的所有依赖文件名(已经去除了重复的文件名称);注意:内部变量的引用不需要加括号; 利用上述的内部文件名,上面的makefile可以重新改写为:=make file 开始=OBJS = foo.o bar.oCC = gccCFLAGS = -Wall -O -gmyprog:$(OBJS)$(CC) $ -o $ foo.o: foo.c foo.h bar.h$(CC) $(CFLAGS) -c $ -o $bar.o: bar.c bar.h$(CC) $(CFLAGS) -c $ -o $=make file 结束=正如代码中常常使用的变量一样,makefile中变量的使用也非常灵活!编写vxworks的MakeFile 收藏 MakeFile文件内容如下 CPU = XXX1000 CPU类型TOOL = gnu 用gcc编译ADDED_CFLAGS= -g g表示生成用于Debug的目标文件TARGET = target.o 目标文件OBJS = example1.o ¥ 目标文件由Example1和2.o连接而成example2.o ¥$(TARGET):$(OBJS)$(LD) -r -o $ $(OBJS)example1.o : example1.h 当头文件变更时重新编译example.oexample2.o: example2.hinclude$(WIND_BASE)/target/h/make/defs.bsp 以下是链接中使用的文件include$(WIND_BASE)/target/h/make/make.$(CPU)$(TOOL)include$(WIND_BASE)/target/h/make/defs.$(WIND_HOST_TYPE)include$(WIND_BASE)/target/h/make/rules.bsp编译用的批处理文件Link.batdel *.oset WIND_HOST_TYPE=x86-win32 设置相应的环境变量set WIND_BASE=c:Tornadopath C:Tornadohostx86-win32binmake -f Makefi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论