一个C++项目的Makefile编写-Tony与Alex的对话系列- -
Tony : Hey Alex, How are you doing?
Alex : 不怎么样。(显得很消沉的样子)
Tony : Oh , Really ? What is the matter?
Alex : 事情是这样的。最近有一个Unix下的C++项目要求我独自完成,以前都是跟着别人做,现在让自己独立完成,还真是不知道该怎么办,就连一个最简单的项目的Makefile都搞不定。昨晚看了一晚上资料也没有什么头绪。唉!!
Tony : 别急,我曾经有一段时间研究过一些关于Makefile的东西,也许能帮得上忙,来,我们一起来设计这个项目的Makefile。
Alex : So it is a deal。(一言为定)
Tony : 我们现在就开始吧,给我拿把椅子过来。
(Tony坐在Alex电脑的旁边)
Tony : 把你的项目情况大概给我讲讲吧。
Alex : No Problem ! 这是一个“半成品”项目,也就是说我将提供一个开发框架供应用开发人员使用,一个类似MFC的东西。
Tony : 继续。
sqlyog怎么调整字体大小Alex : 我现在头脑中的项目目录结构是这样的:
APL (Alex's Programming Library)
-Make.properties
-Makefile(1)
-include //存放头文件
-Module1_1.h
-Module1_2.h
-Module2_1.h
-Module2_2.h
-src //存放源文件
-Makefile(2)
-module1
-Module1_1.cpp
-Module1_2.cpp
-Makefile(3)
-module2
-Module2_1.cpp
-Module2_2.cpp
-Makefile(3)
-...
-lib //存放该Project依赖的库文件,型如libxxx.a
-dist //存放该Project编译连接后的库文件libapl.a
-examples //存放使用该“半成品”搭建的例子应用的源程序
Makefile(4)
-appdemo1
-Makefile(5)
-src //存放应用源代码
-include
-bin //存放应用可执行程序
-appdemo2
-Makefile(5)
-src //存放应用源代码
-include
-bin //存放应用可执行程序
-...
Tony : I got it!
dom4j教程Alex : 下面我们该如何做呢?
properties是什么文件
Tony : 我们来分析一下各个Makefile的作用。你来分析一下各个级别目录下的Makefile的作用是什么呢?
Alex : (思考了一会儿)我想应该是这样的吧。
Makefile(3)负责将其module下的.cpp源文件编译为同名.o文件,同时其phony target "clean"负责删除该目录下的所有.o文件;
Makefile(2)负责调用src目录下所有module的Makefile文件。
Makefile(1)负责先调用src中的Makefile生成静态库文件,然后调用examples中的Makefile构建基于该框架的应用。
至于Make.properties,定义通用的目录信息变量、编译器参数变量和通用的依赖关系。
Tony : 说得很好。我们一点一点来,先从src中每个module下的Makefile着手,就如你所说在每个module下的Makefile负责将该module下的.cpp文件编译为同名的.o文件。
Alex : 好的,我来写吧,这个我还是能搞定的。看下面:
module1下的Makefile如下:
#
# Makefile for module1
#
all : Module1_1.o Module1_2.o
Module1_1.o : Module1_1.cpp
g++ -c $^ -I ../../include
Module1_2.o : Module1_2.cpp
g++ -c $^ -I ../../include
clean :
typescript用的人多吗 rm -f *.o
module2下的Makefile如下:
#
# Makefile for module2
#
all : Module2_1.o Module2_2.o
Module2_1.o : Module2_1.cpp
g++ -c $^ -I ../../include
Module2_2.o : Module2_2.cpp
g++ -c $^ -I ../../include
clean :
rm -f *.o
make一下,顺利产生相应的.o文件。
/*=============================================================
Note: 关于$^、$<和$@的用法说明:
$@ -- “$@”表示目标的集合,就像一个数组,“$@”依次取出目标,并执于命令。
$^ -- 所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。
$< -- 依赖目标中的第一个目标名字
举例: Module1_1.o Module1_2.o : Module1_1.cpp Module1_2.cpp
则$@ -- Module1_1.o Module1_2.o
$^ -- Module1_1.cpp Module1_2.cpp
ps菜单栏在哪$< -- Module1_1.cpp
==============================================================*/
Tony : Well done! 不过发现什么问题了么?
Alex : 什么问题?
Tony : 存在重复的东西。在重构中我们知道如果两个子类中都定义相同的接口函数,我们会将其pull up到基类中。同样我们可以重构我们的Makefile,把一些重复的东西拿到外层去。
Alex : (似乎略微明白了一些)我想有三处重复:a)查头文件的路径是重复的; b)g++这个字符串可以用一个变量定义代替 c)编译器的编译参数可以也定义到一个变量中。我知道Make工具支持include一个文件,我们就建立一个公用的文件来存放一些通用的东西吧。
Tony : 没错,Just do it.
Alex : 就按我原先的想法,把这些公共的部分放到Make.properties中吧。
#
# Properties for demo's Makefile
#
MAKEFILE = Makefile
readonly用法BASEDIR = $(HOME)/proj/demo
>>>>
# Directory layout #
>>>>
SRCDIR = $(BASEDIR)/src
INCLUDEDIR = $(BASEDIR)/include
LIBDIR = $(BASEDIRE)/lib
DISTDIR = $(BASEDIR)/dist
>>>>
# Compiler options #
# F_ -- FLAG #
>>>>
CC = g++
# Compiler search options
F_INCLUDE = -I$(INCLUDEDIR)
F_LIB = -L $(LIBDIR)
CFLAGS =
CPPFLAGS = $(CFLAGS) $(F_INCLUDE)
然后修改一下,各个module中的Makefile文件,以module1为例,修改后如下:
#
# Makefile for module1
#
include ../../Make.properties
all : Module1_1.o Module1_2.o
Module1_1.o : Module1_1.cpp
$(CC) -c $^ $(CPPFLAGS)
Module1_2.o : Module1_2.cpp
$(CC) -c $^ $(CPPFLAGS)
clean :
rm -f *.o
Tony : 其实这两个Makefile中还有一个隐含的重复的地方
Alex : 你是指依赖规则么?
Tony : 嗯,这个依赖规则在src中的各个module中都会用得到的。
Alex : 没错,我也是这么想的,我现在就把这个规则抽取出来,然后你来评审一下。我想利用make工具的传统的“后缀规则”来定义通用依赖规则,我在Make.properties加入下面的变量定义:
>>>>
# Common depends #
>>>>
DEPS = .cpp.o
然后还是以module1为例,修改module1的Makefile后如下:
#
# Makefile for module1
#
include ../../Make.properties
all : Module1_1.o Module1_2.o
$(DEPS):
$(CC) -c $^ $(CPPFLAGS)
clean :
rm -f *.o
Tony : 基本满足需求。我们可以进行上一个层次的Makefile的设计了。我们来设计Makefile(2)。Alex,你来回顾一下Makefile(2)的作用。
/*=============================================================
Note: 关于后缀规则的说明
后缀规则中所定义的后缀应该是make 所认识的,如果一个后缀是make 所认识的,那么这个规则就是单后缀规则,而如果两个
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
liquibase的changelog详解
« 上一篇
最新最全的SpringBoot面试题,附答案!
下一篇 »
热门文章
-
利用正则表达式实现文本数据提取与处理
2025-02-08 -
正则表达式零宽断言详解
2025-02-08 -
文本匹配规则
2025-02-08 -
excel中使用正则
2025-02-08 -
1-31正则表达式
2025-02-08 -
anki之高级筛选
2025-02-08 -
BUAA_OO_2021_第一单元总结
2025-02-08 -
insert语句递增写法
2025-02-08 -
sublime text 3在行前插入递增数字序号的方法
2025-02-08 -
字符串只允许数字和英文的正则
2025-02-08 -
powerbuilder 正则表达式
2025-02-08 -
Shell脚本编写的高级技巧利用正则表达式进行字符串匹配
2025-02-08 -
JAVA正则表达式的三种模式:贪婪,勉强和占有的讨论
2025-02-08 -
go regexp匹配规则
2025-02-08 -
oracle regexp_substr 实现原理
2025-02-08 -
基本的元字符 回溯引用和前后查 匹配模式
2025-02-08 -
elasticsearch query dsl正则
2025-02-08 -
oracle sql正则表达式
2025-02-08 -
GA-设置目标
2025-02-08 -
仅匹配全角片假名的正则表达式
2025-02-08
最新文章
-
java正则表达式 选择题
2025-02-12 -
工龄小数点提取
2025-02-08 -
非零金额 正则表达式
2025-02-08 -
提取文本中数字的函数
2025-02-08 -
vue数字相加小数点变长-概述说明以及解释
2025-02-08 -
vue validate 正则验证小数长度
2025-02-08
发表评论