Chinaunix首页 | 论坛 | 博客
  • 博客访问: 24802
  • 博文数量: 7
  • 博客积分: 320
  • 博客等级: 一等列兵
  • 技术积分: 90
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-17 19:01
文章分类

全部博文(7)

文章存档

2009年(1)

2008年(4)

2007年(2)

我的朋友
最近访客

分类: C/C++

2009-03-24 22:51:56

Makefile学习

  虽然工作很忙,没什么空闲时间,但arraya也在像蜗牛一样慢慢地向前爬行,现在变成多目录了,编译就比较麻烦了,不用Makefile真不方便,于是自己在网上找来了通用的Makefile文件,看了看,就自己写了个出来,一编译,出错,明明定义的类,系统说找不到,哦,Makefile写得不对,改了又改还是有这样那样的错误,于是痛定思痛,系统地学习下Makefile,以后写什么程序,小项目,都自己写个Makefile,把这个基础搞定。

  正式开始学习...

  以前看过一点,知道Makefile最基本的结构,所以学习目标定为多文件多目录的Makefile有关于东西,另外要学习的是gcc命令,没经验啊,都不好意思说工作半年了。

  第一条,make可以自动推导文件以及文件依赖关系的命令,所以没有必要去在每一个[.o]文件后都写上类似的命令,可以这样写:

obj = main.o command.o fun.o


execute : &(obj)

cc -o edit &(obj)


main.o : dfs.h

command.o : dfs.h command.h

fun.o : dfs.h fun.h


第二条,在Makefile中使用include关键字可以把别的Makefile包含进来,被包含的文件会原模原样的放在当前文件的包含位置


第三条,wildcard,如果想使用通配符[*],那么你就要使用这个wildcard了,例如:

obj = *.o #语法是正确的,但语义上并不表示当前目录下的所有.o文件

obj = $(wildcard *.o) #这才是你要的所有.o文件


第四条,VPATH特殊变量,定义这个变量可以让不同的目录成为make的默认搜寻目录,大概就是环境变量的意思,不同的目录以:分开,例如

VPATH = src:../include:../base #make时,会搜寻定义的三个目录来找Makefile规则中的文件


第五条是和第四条相对应的,vpath,这个关键字也是为make指定搜寻,这个更为灵活,它可以指定不同的文件在不同的搜索目录中:

vpath < pattern> < directories> 

为符合模式< pattern>的文件指定搜索目录< directories>

vpath < pattern>

清除符合模式< pattern>的文件的搜索目录。

vpath 

清除所有已被设置好了的文件搜索目录。

vapth使用方法中的需要包含“%”字符。“%”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件。指定了要搜索的文件集,而< directories>则指定了的文件集的搜索的目录。例如:

vpath %.h ../headers

该语句表示,要求make在“../headers”目录下搜索所有以“.h”结尾的文件。(如果某文件在当前目录没有找到的话)


第六条,伪目标,通常的make clean中的clean就是一个伪目标,这样写:

clean:

rm *.o

.PHONY : clean #这个是声明clean是一个伪目标,也就是说这个目标不是真实的文件

由第六条,可以得到使用一次make,得到多个可执行文件的方法:

all : prog1, prog2, prog3

.PHONY : all


prog1 : prog1.o

cc -o prog1 prog1.o


prog2 : prog2.o

cc -o prog2 prog2.o


prog3 : prog3.o

cc -o prog3 prog3.o

   为什么以上的Makefile可以生成三个可能执行文件prog1,prog2,prog3呢?make会把Makefile文件里第一个目标作为默认目标,所以以all这个伪目标作为默认目标,这个伪目标是不可能产生的实际文件的,它是依赖于三个文件,这三个文件是实际的文件,所以执行到这三个目标后,会生成三个可执行文件。


第七条,静态模式,这个东东好难讲清楚,举个例子:

OBJ = foo.o bar.o

all : $(OBJ)

$(OBJ) : %.o: %.c  #这里就是静态模型,意思是等价于 $(OBJ) : foo.c bar.c

$(CC) -c $(CFLAGS) $< -o $@


第八条,自动生成依赖性,即.d文件的规则。让每一个.c文件都生成一个.d的文件Makefile文件,.d文件中就存放对应.c文件的依赖关系。在Makefile文件中写程序.c和 .d的依赖关系,让make自动更新或生成.d文件,并把其包含在我们的主Makefile中,一个模型规则产生的.d文件:

%.d: %.c

@set -e; rm -f $@; \

$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \

sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \

rm -f $@.$$$$

   这个规则的意思是,所有的[.d]文件依赖于[.c]文件,“rm -f $@”的意思是删除所有的目标,也就是[.d]文件,第二行的意思是,为每个依赖文件“$<”,也就是[.c]文件生成依赖文件,“$@”表示模式“%.d”文件,如果有一个C文件是name.c,那么“%”就是“name”,“$$$$”意为一个随机编号,第二行生成的文件有可能是“name.d.12345”,第三行使用sed命令做了一个替换,关于sed命令的用法请参看相关的使用文档。第四行就是删除临时文件。


第九条嵌套执行make,大的工程中,不同的模块源文件可能在不同的目录中,每个目录都可以写一个相应的Makefile,这有利于让我们的Makefile变得更加简洁。

例如,有一个子目录subdir,这个目录有个Makefile文件,来指明了这个目录下的文件编译规则,我们总控的Makefile可以这样书写:

subsystem:

cd subdir && $(MAKE) #MAKE是变量,表示make,可能有一些参数

另外,使用export声明变量,可以传递到子目录下的Makefile中使用


一些默认变量:

$@

表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。

$%

仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a (bar.o)",那么,"$%"就是"bar.o","$@"就是"foo.a"。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。

$<

依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。

阅读(1239) | 评论(0) | 转发(0) |
0

上一篇:aranya之URL(2)

下一篇:没有了

给主人留下些什么吧!~~