本文共 3105 字,大约阅读时间需要 10 分钟。
需求:程序的规模较大,将各个模块单独存放在子目录中,将头文件保存在include目录下,编写makefile文件可以实现对整个工程的编译。
学习过程:
1.了解makefile的基本规则,
这篇文章是makefile的经典教材,网上找的makefile的大部分资料都是这篇文章,看完这篇文章后,自己写了makefile文件,
INCLUDE=./include#VPATH=.:include:metadata_cache:metadata_op:lockvpath %.h includevpath %.c .:metadata_cache:metadata_op:lockobjects=metadata_bulk.o metadata_chain.o metadata_table.o metadata_big_table.o\ metadata_cache_node.o metadata_cache.o mds_metadata_cache.o\ metadata_op.o\ metadata_lock.o\ mds_radix_tree.o test.o mds:$(objects) gcc -o mds $(objects) -I$(INCLUDE) -lpthreadmetadata_bulk.o:metadata_bulk.c mds_metadata_cache.h gcc -I$(INCLUDE) -c metadata_cache/metadata_bulk.cmetadata_chain.o:metadata_chain.c mds_metadata_cache.h gcc -I$(INCLUDE) -c metadata_cache/metadata_chain.cmetadata_table.o:metadata_table.c mds_metadata_cache.h gcc -I$(INCLUDE) -c metadata_cache/metadata_table.cmetadata_big_table.o:metadata_big_table.c mds_metadata_cache.h gcc -I$(INCLUDE) -c metadata_cache/metadata_big_table.cmetadata_cache_node.o:metadata_cache_node.c mds_metadata_cache.h mds_lock.h gcc -I$(INCLUDE) -c metadata_cache/metadata_cache_node.cmetadata_cache.o:metadata_cache.c mds_metadata_cache.h gcc -I$(INCLUDE) -c metadata_cache/metadata_cache.cmx_metadata_cache.o:mds_metadata_cache.c mds_metadata_cache.h gcc -I$(INCLUDE) -c metadata_cache/mds_metadata_cache.cmetadata_op.o:metadata_op.c mds_metadata_op.h mds_lock.h gcc -I$(INCLUDE) -c metadata_op/metadata_op.cmetadata_lock.o:metadata_lock.c mds_lock.h gcc -I$(INCLUDE) -c lock/metadata_lock.cmx_radix_tree.o:mds_radix_tree.c mds_radix_tree.h gcc -I$(INCLUDE) -c mds_radix_tree.ctest.o:test.c mds_metadata_op.h gcc -I$(INCLUDE) -c test.c发现指定的VPATH和vpath基本没有起到作用,子目录下的文件还是必须使用subdir/filename.c这样的格式,不能直接使用filename.c这样的格式替代。
2.找到了第二篇资料(发现第一篇的资料真的太泛滥的,百度makefile基本都是第一篇文章)
这篇也是大概介绍了makefile的语法,另外介绍了一些生成库的方法,算是对第一篇文章的补充
3可以采用$内部定义的宏简化makefile的编写,最后和上面同样的方法,可以简化成如下形式
INCLUDE=./includeVPATH=.:metadata_cache:metadata_op:lock#vpath %.h include#vpath %.c .:metadata_cache:metadata_op:lockobjects=metadata_bulk.o metadata_chain.o metadata_table.o metadata_big_table.o\ metadata_cache_node.o metadata_cache.o mx_metadata_cache.o\ metadata_op.o\ metadata_lock.o\ mds_radix_tree.o test.o mx:$(objects) gcc -lpthread -g -o $@ $^%.o:%.c gcc -g -o $@ -c $< -I$(INCLUDE)clean: rm -rf *.o mds
makefile内部宏能够极大的简化makefile的编写,而且对于一个很大的工程项目,使用这些内部宏,在添加、删除或是修改工程文件时,只需要对makefile稍做修改即可。
$@表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。$%仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a(bar.o)",那么,"$%"就是"bar.o","$@"就是"foo.a"。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。$ <依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$> <"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。$?所有比目标新的依赖目标的集合。以空格分隔。$^所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。$+这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。$*这个变量表示目标模式中"%"及其之前的部分。如果目标是"dir/a.foo.b",并且目标的模式是"a.%.b",那么,"$*"的值就是"dir /a.foo"。这个变量对于构造有关联的文件名是比较有较。如果目标中没有模式的定义,那么"$*"也就不能被推导出,但是,如果目标文件的后缀是 make所识别的,那么"$*"就是除了后缀的那一部分。例如:如果目标是"foo.c",因为".c"是make所能识别的后缀名,所以,"$*"的值就是"foo"。这个特性是GNU make的,很有可能不兼容于其它版本的make,所以,你应该尽量避免使用"$*",除非是在隐含规则或是静态模式中。如果目标中的后缀是make所不能识别的,那么"$*"就是空值。 依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$>
makefile资料:
经典教程
深入学习make命令
makefile tutorial
转载地址:http://csztb.baihongyu.com/