Makefile在多文件项目中的使用心得
2008-09-30 11:35
197 查看
昨天为了用Makefile来编译一个几十个源码文件的项目,研究了下Makefile的用法,发现Makefile原来是这么强大,一点心得写在这里。
首先发现原来的Makefile写的有些问题,文件中对最终生成的目标的依赖项只设了所有的cpp文件,类似于这样:
all:target_program
target_program: XXX.cpp ......
g++ -o target_program XXX.cpp ......
这样写虽然很方便,但是有个问题就是当某个cpp文件依赖的头文件有修改后,make不会检测到,这可能会造成一些莫名奇妙的问题。
所以我就按照书上的标准格式,参照每个cpp文件依赖的头文件,手写依赖项……终于写完了,并make成功。事后发现自己真是有愚公移山的精神 -_-!
这样做的缺点很明显,工作量太大,而且一旦代码有改动,makefile也可能需要跟着改,很麻烦。于是我查看了一下Eclipse生成的makefile,发现里面写得像甲古文一样跟本看不懂,但是有一点,其中没有涉及到具体的代码文件,所以一定有更简单的方法。
于是我就到网上找,资料很多,看了不少高手写的功能超强大的Makefile,可惜就是看不懂,所以就东拼西凑,找些尽量简单的来终于完成了一个比较通用又比较简单的Makefile。
all:mserver
# compiler
CC = g++
# include files directory
INCLUDE = -I include
# source files directory
SRCDIR = source
# lib
LIBS = -lpthread -lrt
# options for debug
CFLAGS = -g
# options for release
#CFLAGS = -O
# get name list of all source file
SRCS = ${wildcard ${SRCDIR}/*.cpp}
# get name list of all object file
OBJS = ${SRCS:.cpp=.o}
# get name list of all dependency file
DEPENDS = ${SRCS:.cpp=.d}
# executable file
FINAL_PROG = mserver
all:${FINAL_PROG}
# 重定义cpp到o的转化规则
.SUFFIXES: .cpp
.cpp.o:
${CC} -c ${INCLUDE} $< -o $@
# 定义新的后缀.d,并定义从cpp到d的转化规则
.SUFFIXES: .d
.cpp.d:
${CC} -M ${INCLUDE} $< > $@
# 目标文件的依赖关系与生成规则
${FINAL_PROG}:${OBJS}
${CC} ${CFLAGS} ${LIBS} ${OBJS} -o $@
# 加入自动生的的所有cpp文件的依赖规则
-include ${DEPENDS}
clean:
-rm -rf ${DEPENDS} ${OBJS}
(要复制代码的朋友请注意:由于这个编辑器不能输入tab,故用空格代替,代码中缩进的部分都是一个tab;
另外,如果中文注释影响make就删掉)
下面对这个Makefile进行解释:
首先文件中定义了一些依赖于具体项目文件结构的MACRO,如头文件的位置,源文件的位置,编译参数等。其中:
SRCS = ${wildcard ${SRCDIR}/*.cpp
这句的作用是从源文件目录中获得一个所有 cpp文件名的列表
wildcard是make内部定义的函数,能够展开一个正则表达式成为一个字符列列表,空格后面是其仅有的一个参数,代码中表示了SRCDIR目录中的所有cpp文件,故${wildcard ${SRCDIR}/*.cpp}能返回cpp文件列表,这样免去了手动输入的麻烦。
OBJS = ${SRCS:.cpp=.o}
是一个所有.o文件名的列表,它利用现成的MACRO SRCS,将其中的.cpp换成.o,SRCS:.cpp=.o就是这个意思。
DEPENDS = ${SRCS:.cpp=.d}
是一个所有.d文件名的列表,什么是.d文件呢?这是笔者自定义的一个文件,比如main.cpp会有一个对应的main.d,
里面存的是main.cpp中所依赖的头文件,但这个文件是怎么生成的呢,请往下看。
.SUFFIXES: .d
.cpp.d:
${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,$<表示当前依赖规则的被
4000
依赖项,$@表示目标项,
在.cpp.d:的转换规则定义中.d文件依赖于.cpp,故$<表示main.cpp,$@表示main.d
这样一个完整的依赖关系就能够非常方便的自动建立。
第一篇文章,不容易啊,大家支持一下 : )
首先发现原来的Makefile写的有些问题,文件中对最终生成的目标的依赖项只设了所有的cpp文件,类似于这样:
all:target_program
target_program: XXX.cpp ......
g++ -o target_program XXX.cpp ......
这样写虽然很方便,但是有个问题就是当某个cpp文件依赖的头文件有修改后,make不会检测到,这可能会造成一些莫名奇妙的问题。
所以我就按照书上的标准格式,参照每个cpp文件依赖的头文件,手写依赖项……终于写完了,并make成功。事后发现自己真是有愚公移山的精神 -_-!
这样做的缺点很明显,工作量太大,而且一旦代码有改动,makefile也可能需要跟着改,很麻烦。于是我查看了一下Eclipse生成的makefile,发现里面写得像甲古文一样跟本看不懂,但是有一点,其中没有涉及到具体的代码文件,所以一定有更简单的方法。
于是我就到网上找,资料很多,看了不少高手写的功能超强大的Makefile,可惜就是看不懂,所以就东拼西凑,找些尽量简单的来终于完成了一个比较通用又比较简单的Makefile。
all:mserver
# compiler
CC = g++
# include files directory
INCLUDE = -I include
# source files directory
SRCDIR = source
# lib
LIBS = -lpthread -lrt
# options for debug
CFLAGS = -g
# options for release
#CFLAGS = -O
# get name list of all source file
SRCS = ${wildcard ${SRCDIR}/*.cpp}
# get name list of all object file
OBJS = ${SRCS:.cpp=.o}
# get name list of all dependency file
DEPENDS = ${SRCS:.cpp=.d}
# executable file
FINAL_PROG = mserver
all:${FINAL_PROG}
# 重定义cpp到o的转化规则
.SUFFIXES: .cpp
.cpp.o:
${CC} -c ${INCLUDE} $< -o $@
# 定义新的后缀.d,并定义从cpp到d的转化规则
.SUFFIXES: .d
.cpp.d:
${CC} -M ${INCLUDE} $< > $@
# 目标文件的依赖关系与生成规则
${FINAL_PROG}:${OBJS}
${CC} ${CFLAGS} ${LIBS} ${OBJS} -o $@
# 加入自动生的的所有cpp文件的依赖规则
-include ${DEPENDS}
clean:
-rm -rf ${DEPENDS} ${OBJS}
(要复制代码的朋友请注意:由于这个编辑器不能输入tab,故用空格代替,代码中缩进的部分都是一个tab;
另外,如果中文注释影响make就删掉)
下面对这个Makefile进行解释:
首先文件中定义了一些依赖于具体项目文件结构的MACRO,如头文件的位置,源文件的位置,编译参数等。其中:
SRCS = ${wildcard ${SRCDIR}/*.cpp
这句的作用是从源文件目录中获得一个所有 cpp文件名的列表
wildcard是make内部定义的函数,能够展开一个正则表达式成为一个字符列列表,空格后面是其仅有的一个参数,代码中表示了SRCDIR目录中的所有cpp文件,故${wildcard ${SRCDIR}/*.cpp}能返回cpp文件列表,这样免去了手动输入的麻烦。
OBJS = ${SRCS:.cpp=.o}
是一个所有.o文件名的列表,它利用现成的MACRO SRCS,将其中的.cpp换成.o,SRCS:.cpp=.o就是这个意思。
DEPENDS = ${SRCS:.cpp=.d}
是一个所有.d文件名的列表,什么是.d文件呢?这是笔者自定义的一个文件,比如main.cpp会有一个对应的main.d,
里面存的是main.cpp中所依赖的头文件,但这个文件是怎么生成的呢,请往下看。
.SUFFIXES: .d
.cpp.d:
${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,$<表示当前依赖规则的被
4000
依赖项,$@表示目标项,
在.cpp.d:的转换规则定义中.d文件依赖于.cpp,故$<表示main.cpp,$@表示main.d
这样一个完整的依赖关系就能够非常方便的自动建立。
第一篇文章,不容易啊,大家支持一下 : )
相关文章推荐
- IT咨询顾问:一次吐血的项目救火 java或判断优化小技巧 asp.net core Session的测试使用心得 【.NET架构】BIM软件架构02:Web管控平台后台架构 NetCore入门篇:(十一)NetCore项目读取配置文件appsettings.json 使用LINQ生成Where的SQL语句 js_jquery_创建cookie有效期问题_时区问题
- 项目中Global.asax 文件的使用
- [导入]在 Visual Studio .NET IDE 内使用“从源代码管理打开”时出现无法读取项目文件的错误
- Java学习笔记之使用MyEclipse将java项目打包成jar文件,并生成Javadoc帮助文档
- maven多级项目使用 slf4j+log4j,以及自定义配置文件路径
- 【spark】使用scala读取项目中的文件的方法
- Seal Report使用教程(二)——项目文件
- 使用gulp为项目中的文件自动添加版本号之实践思路
- 使用XML作为项目的配置文件使用,并解析之,获得数据作为链接数据库的参数
- makefile文件详解七--使用函数
- ssm项目使用Mybatis动态拼接sql语句,生成的sql中文全部显示为???的问题(配置文件sql语句中文解析问题)
- vue-cli构建项目在index.html中使用静态文件
- IOS ARC项目使用非ARC文件 MRC项目使用ARC文件
- pyinstaller使用-python项目转换成exe可执行文件
- cocos2dx项目中使用cocostudio ui编辑器的导出文件
- 删除项目中未使用的图片和类文件
- 关于使用Android Studio 开发NDK项目生成.h文件方法
- 使用Maven管理依赖JAR文件,自定义项目布局,利用ANT生成不同的发布包
- 使用idea初次创建maven项目无法创建Java文件的解决办法