Makefile在多文件项目中的使用心得

原创 2008年09月30日 11:35:00
      昨天为了用Makefile来编译一个几十个源码文件的项目,研究了下Makefile的用法,发现Makefile原来是这么强大,一点心得写在这里。
      首先发现原来的Makefile写的有些问题,文件中对最终生成的目标的依赖项只设了所有的cpp文件,类似于这样:
  1. all:target_program
  2. target_program: XXX.cpp ......
  3.       g++ -o target_program   XXX.cpp ......
      这样写虽然很方便,但是有个问题就是当某个cpp文件依赖的头文件有修改后,make不会检测到,这可能会造成一些莫名奇妙的问题。
      所以我就按照书上的标准格式,参照每个cpp文件依赖的头文件,手写依赖项……终于写完了,并make成功。事后发现自己真是有愚公移山的精神 -_-!
这样做的缺点很明显,工作量太大,而且一旦代码有改动,makefile也可能需要跟着改,很麻烦。于是我查看了一下Eclipse生成的makefile,发现里面写得像甲古文一样跟本看不懂,但是有一点,其中没有涉及到具体的代码文件,所以一定有更简单的方法。
      于是我就到网上找,资料很多,看了不少高手写的功能超强大的Makefile,可惜就是看不懂,所以就东拼西凑,找些尽量简单的来终于完成了一个比较通用又比较简单的Makefile。
  1. all:mserver
  2. # compiler
  3. CC = g++
  4. # include files directory
  5. INCLUDE = -I include
  6. # source files directory
  7. SRCDIR = source
  8. # lib
  9. LIBS = -lpthread -lrt
  10. # options for debug
  11. CFLAGS = -g
  12. # options for release
  13. #CFLAGS = -O
  14. # get name list of all source file 
  15. SRCS = ${wildcard ${SRCDIR}/*.cpp}
  16. # get name list of all object file
  17. OBJS = ${SRCS:.cpp=.o}
  18. # get name list of all dependency file
  19. DEPENDS = ${SRCS:.cpp=.d}
  20. # executable file
  21. FINAL_PROG = mserver
  22. all:${FINAL_PROG}
  23. # 重定义cpp到o的转化规则
  24. .SUFFIXES:  .cpp
  25. .cpp.o:
  26.      ${CC}  -c ${INCLUDE} $< -o $@
  27. # 定义新的后缀.d,并定义从cpp到d的转化规则
  28. .SUFFIXES:  .d
  29. .cpp.d:
  30.      ${CC} -M ${INCLUDE} $< > $@
  31. # 目标文件的依赖关系与生成规则
  32. ${FINAL_PROG}:${OBJS}
  33.      ${CC} ${CFLAGS}  ${LIBS}  ${OBJS}  -o $@
  34. # 加入自动生的的所有cpp文件的依赖规则
  35. -include ${DEPENDS}
  36. clean:
  37.      -rm -rf ${DEPENDS}  ${OBJS}
(要复制代码的朋友请注意:由于这个编辑器不能输入tab,故用空格代替,代码中缩进的部分都是一个tab;
另外,如果中文注释影响make就删掉)


下面对这个Makefile进行解释:
首先文件中定义了一些依赖于具体项目文件结构的MACRO,如头文件的位置,源文件的位置,编译参数等。其中:
  1. SRCS = ${wildcard ${SRCDIR}/*.cpp
这句的作用是从源文件目录中获得一个所有 cpp文件名的列表
wildcard是make内部定义的函数,能够展开一个正则表达式成为一个字符列列表,空格后面是其仅有的一个参数,代码中表示了SRCDIR目录中的所有cpp文件,故
${wildcard ${SRCDIR}/*.cpp}能返回cpp文件列表,这样免去了手动输入的麻烦。
  1. OBJS = ${SRCS:.cpp=.o}
是一个所有.o文件名的列表,它利用现成的MACRO SRCS,将其中的.cpp换成.o,SRCS:.cpp=.o就是这个意思。
  1. DEPENDS = ${SRCS:.cpp=.d}
是一个所有.d文件名的列表,什么是.d文件呢?这是笔者自定义的一个文件,比如main.cpp会有一个对应的main.d,
里面存的是main.cpp中所依赖的头文件,但这个文件是怎么生成的呢,请往下看。
  1. .SUFFIXES:  .d
  2. .cpp.d:
  3.     ${CC} -M ${INCLUDE} $< > $@
这句定义了从cpp到d的转化规则,定义之后当make需要.d文件的时候,就会把cpp文件按规则自动转换成d文件,它事实上是利用了g++的一个功能 -M,这个参数可以让g++输出一个对应某个cpp文件所依赖的头文件列表,如果要生成main.cpp的依赖列表可以这样:
g++ -M  -I includeDir  main.cpp
大家可以试一下这个命令,当然这里我们要将输出结果导到.d文件中,所以就构成了如下命令:
g++ -M  -I includeDir  main.cpp > main.d
Makefile中的命令就是根据这个而来的,只不过用了MACRO代替一些变量,其中:
$<与$@都是make内部定义的MACRO,$<表示当前依赖规则的被依赖项,$@表示目标项,
在.cpp.d:的转换规则定义中.d文件依赖于.cpp,故$<表示main.cpp,$@表示main.d
这样一个完整的依赖关系就能够非常方便的自动建立。

第一篇文章,不容易啊,大家支持一下 : )

iOS项目开发中常用到的数据库之FMDB的使用

什么是FMDB ●  FMDB是iOS平台的SQLite数据库框架 ●  FMDB以OC的方式封装了SQLite的C语言API ●  FMDB的优点 ●  使用起来更加面向对象...
  • whjay520
  • whjay520
  • 2016年09月05日 16:24
  • 465

ActiveMQ的在实际项目中的简单使用

简介 本文达到的目的是会用。 安装服务器: 官网下载win版的,也可是linux版的; 启动服务器:win版的执行activemq.bat 看看是否安装成功:http://local...
  • ljl18566743868
  • ljl18566743868
  • 2016年11月08日 15:54
  • 1096

Solr-项目中的使用

配置中文分析器 在SolrCore的conf下的schema.xml是Solr数据表配置文件,定义了加入索引的数据的数据类型。 主要包括Fields,FieldTypes和其他的一些设置。 ...
  • LLLLLiSHI
  • LLLLLiSHI
  • 2017年05月07日 14:01
  • 618

线程在实际项目中简单的应用

前段时间开发的项目中有一个office在线预览的功能,我们知道需要实现这个功能一般是 后台把用户上传的txt啊excel啊word啊先转换成pdf格式,然后使用pdf.js进行前台预览(有的还 需要转...
  • u014417573
  • u014417573
  • 2017年11月30日 13:50
  • 254

在项目中使用springmvc

什么是springmvcspringmvc是spring框架的一个模块,springmvc和spring无需通过中间整个层进行整合,它是一个基于mvc的web框架。springmvc与struts2的...
  • jinzili777
  • jinzili777
  • 2016年04月09日 08:36
  • 1371

使用性的单例模式,项目中应用

实现阶段进阶: 如果查看书本上单例模式,简单一句话,都是如何实现。 并且实现务必有 Class.GetInstance() 的语句。这种方式的缺点还一个就是代码的可读性受影响; 原因区别于非单...
  • zxf10523
  • zxf10523
  • 2016年11月17日 11:41
  • 157

SpringAOP在项目中的简单应用

 SpringAOP在项目中的简单应用 一、前言 项目背景 由于公司的机房到期,需要做应用迁移(包括数据库),割接到云平台。但是又不能进行一次性割接,需要分三个阶段:第一阶段割...
  • keyingbo2008
  • keyingbo2008
  • 2014年04月03日 21:47
  • 3959

【Redis基础】Redis在项目中实战

redis搭建,集群搭建,多属于运维知识,基本了解就可以。但是在项目如何让redis发挥它的特长就属于我们需要掌握和探索的。接下来讲解一下在项目中如何使用redis来做缓存的。   适用场景 什...
  • u010539352
  • u010539352
  • 2016年06月30日 08:32
  • 8496

项目中多线程的使用

如下两篇文章对Linux 多线程讲的比较深入,详细: Linux pthread详解 http://blog.csdn.net/xueye3000/article/details/7024365 ...
  • huao798480517
  • huao798480517
  • 2013年03月29日 18:49
  • 1092

项目中常用的mysql函数

项目中经常的查询:join GROUP BY经常的流程控制:case when '' then '' else '' end经常用的函数:IFNULL LEFT SUM replaceCURDATE(...
  • u012412427
  • u012412427
  • 2015年11月04日 15:30
  • 160
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Makefile在多文件项目中的使用心得
举报原因:
原因补充:

(最多只允许输入30个字)