Makefile学习笔记系列3:具有子目录层次结构的makefile写法
2016-09-07 21:41
429 查看
在系列1和系列2的基础上再次对目录的结构及makefile进行改进。
(1)首先还是介绍下目录结构:
(2)和系列2相比较,在主目录下多了lib这个子目录,lib是用来存放其他三个模块(receiver, responser, sender)编译出来的.a静态库。include目录下存放公共的头文件。
三个子模块目录的结构如下:(以receiver目录为例)
(3)接下来先来看下主目录下的makefile
主Makefile分析:
主要以下几个重点:
<1> AR是编译.a静态库工具, ARFLAG 为编译静态库参数
<2> CLIBS 指定了.o文件链接为target所需要加载的库, -L 指定库的目录, -lSender表示链接的库名称为 libSender.a
<3> SUBDIRS 指定了编译main.cpp需要关联的子目录
<4> export操作将主makefile中定义的 几个变量导出,这样在子目录的makefile中就可以用这些变量了。
<5> 注意这句:$(TARGET) : $(OBJECTS) $(SUBDIRS)
TARGET的生成除了需要依赖OBJECTS指定的.o文件外还需要依赖$(SUBDIRS)。再往下看
$(SUBDIRS):ECHO
+$(MAKE) -C $@在SUBDIRS的依赖关系后面会执行$(MAKE)命令,会执行每个子目录下的makefile。这样就可以保证生成TARGET之前先执行子目录的makefile产生其所需要的静态库。
ECHO:仅仅是打印log。
<6> clean虚目标里面多添加了一个for循环来调用子目录的makefile的make clean命令,清除子目录下产生的目标文件。
<7> 先来看下执行完make以后Lib目录下会产生的静态库文件如下图:
(4)主makefile分析完毕,现在来分析子makefile, 以receiver目录下的为例:
receiver目录下的makefile代码如下:
LIB_DIR = ./../lib/
TOP_DIR = ./..
SOURCES = $(wildcard ./*.cpp)
INCLUDE_DIRS = -I$(TOP_DIR)/include -I$(TOP_DIR)/responser/ -I./
TARGET = libReceiver.a
OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES))
$(TARGET) : $(OBJECTS)
$(AR) $(ARFLAG) $@ $^
cp $@ $(LIB_DIR)
$(OBJECTS) : %.o : %.cpp
$(XX) -c $(CFLAGS) $< -o $@ $(INCLUDE_DIRS)
.PHONY : clean
clean:
rm -rf $(TARGET) $(OBJECTS)
说明:
<1> TOP_DIR 指定顶层目录, LIB_DIR指定静态库文件位置,INCLUDE_DIRS指定了receiver.cpp需要Include的头文件。
<2> TARGET 指定生成为一个静态链接库文件。 命名规则必须为 libXXX.a的形式。
<3> $(TARGET) : $(OBJECTS)
$(AR) $(ARFLAG) $@ $^
cp $@ $(LIB_DIR)
这段代码生成静态库文件,并将静态库文件拷贝到 顶层目录的Lib目录下。
其他没什么说明了,就这三点重点。
编译完会生成的文件如下图:
其他目录下的子makefile类似。
总结:
这种Makefile的写法主要是编译子模块文件并生成静态链接库,主makefile编译并链接静态库生成可执行程序。
这种写法每个子目录都需要编写自己的makefile, 貌似有点麻烦。是不是可以写一个makefile的模版然后子目录的makefile只要include这个模版并写几条简单的语句就可以了。
接下来序列4和序列5将实现这个目标。
谢谢观看,作者水平有限,有错误麻烦指正。
(1)首先还是介绍下目录结构:
(2)和系列2相比较,在主目录下多了lib这个子目录,lib是用来存放其他三个模块(receiver, responser, sender)编译出来的.a静态库。include目录下存放公共的头文件。
三个子模块目录的结构如下:(以receiver目录为例)
(3)接下来先来看下主目录下的makefile
XX = g++ AR = ar ARFLAG = -rcs CFLAGS = -g CLIBS = -L./lib/ -lSender -lReceiver -lResponser -lpthread SUBDIRS = ./receiver ./responser ./sender INCLUDES = $(wildcard ./include/*.h ./sender/*.h ./receiver/*.h ./responser/*.h) # INCLUDE = a.h b.h ... can't be defined like "INCLUDE = ./*.h" #SOURCES = $(wildcard ./*.cpp ./sender/*.cpp ./receiver/*.cpp ./responser/*.cpp) INCLUDE_DIRS = -I./include -I./sender/ -I./receiver/ -I./responser/ #指定头文件目录,代码中就不需要把头文件的完整路径写出来了 TARGET = mainApp #OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES)) OBJECTS = main.o export XX CFLAGS AR ARFLAG $(TARGET) : $(OBJECTS) $(SUBDIRS) $(XX) $< -o $@ $(CLIBS) # $< 表示依赖列表的第一个 也就是 $(OBJECTS) $(OBJECTS) : %.o : %.cpp $(XX) -c $(CFLAGS) $< -o $@ $(INCLUDE_DIRS) $(SUBDIRS):ECHO +$(MAKE) -C $@ ECHO: @echo $(SUBDIRS) @echo begin compile .PHONY : clean clean: for dir in $(SUBDIRS);\ do $(MAKE) -C $$dir clean||exit 1;\ done rm -rf $(TARGET) $(OBJECTS) ./lib/*.a
主Makefile分析:
主要以下几个重点:
<1> AR是编译.a静态库工具, ARFLAG 为编译静态库参数
<2> CLIBS 指定了.o文件链接为target所需要加载的库, -L 指定库的目录, -lSender表示链接的库名称为 libSender.a
<3> SUBDIRS 指定了编译main.cpp需要关联的子目录
<4> export操作将主makefile中定义的 几个变量导出,这样在子目录的makefile中就可以用这些变量了。
<5> 注意这句:$(TARGET) : $(OBJECTS) $(SUBDIRS)
TARGET的生成除了需要依赖OBJECTS指定的.o文件外还需要依赖$(SUBDIRS)。再往下看
$(SUBDIRS):ECHO
+$(MAKE) -C $@在SUBDIRS的依赖关系后面会执行$(MAKE)命令,会执行每个子目录下的makefile。这样就可以保证生成TARGET之前先执行子目录的makefile产生其所需要的静态库。
ECHO:仅仅是打印log。
<6> clean虚目标里面多添加了一个for循环来调用子目录的makefile的make clean命令,清除子目录下产生的目标文件。
<7> 先来看下执行完make以后Lib目录下会产生的静态库文件如下图:
(4)主makefile分析完毕,现在来分析子makefile, 以receiver目录下的为例:
receiver目录下的makefile代码如下:
LIB_DIR = ./../lib/
TOP_DIR = ./..
SOURCES = $(wildcard ./*.cpp)
INCLUDE_DIRS = -I$(TOP_DIR)/include -I$(TOP_DIR)/responser/ -I./
TARGET = libReceiver.a
OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES))
$(TARGET) : $(OBJECTS)
$(AR) $(ARFLAG) $@ $^
cp $@ $(LIB_DIR)
$(OBJECTS) : %.o : %.cpp
$(XX) -c $(CFLAGS) $< -o $@ $(INCLUDE_DIRS)
.PHONY : clean
clean:
rm -rf $(TARGET) $(OBJECTS)
说明:
<1> TOP_DIR 指定顶层目录, LIB_DIR指定静态库文件位置,INCLUDE_DIRS指定了receiver.cpp需要Include的头文件。
<2> TARGET 指定生成为一个静态链接库文件。 命名规则必须为 libXXX.a的形式。
<3> $(TARGET) : $(OBJECTS)
$(AR) $(ARFLAG) $@ $^
cp $@ $(LIB_DIR)
这段代码生成静态库文件,并将静态库文件拷贝到 顶层目录的Lib目录下。
其他没什么说明了,就这三点重点。
编译完会生成的文件如下图:
其他目录下的子makefile类似。
总结:
这种Makefile的写法主要是编译子模块文件并生成静态链接库,主makefile编译并链接静态库生成可执行程序。
这种写法每个子目录都需要编写自己的makefile, 貌似有点麻烦。是不是可以写一个makefile的模版然后子目录的makefile只要include这个模版并写几条简单的语句就可以了。
接下来序列4和序列5将实现这个目标。
谢谢观看,作者水平有限,有错误麻烦指正。
相关文章推荐
- Makefile学习笔记系列2:一个简单的Makefile(增加子目录结构)
- 如何实现具有层次结构的 TreeView <二> (WPF/TreeView/Style/Template)
- 如何实现具有层次结构的 TreeView <四> (WPF/TreeView/Style/Template)
- 微软BI 之SSAS 系列 - 维度的优化,灌木丛属性关系,以及自然层次结构与非自然层次结构的概念
- Makefile学习笔记系列1:一个简单的Makefile
- JDBC系列-<驱动加载原理全面解析>-<JDBC层次结构和基本构成>-存储过程 CallableStatement(创建和使用)
- Mondrian系列(五)-深入维度、层次和级别(3)-Level显示和多层次结构
- MS MDS系列之MDS层次结构(Hierarchy)
- Makefile之大型工程项目子目录Makefile的一种通用写法
- Makefile之大型工程项目子目录Makefile的一种通用写法
- 老调重弹:JDBC系列 之 <JDBC层次结构和基本构成>
- 【大型网站开发系列第一篇】——网站结构层次
- SharePoint 【架构系列】-- Sharepoint的服务器端对象模型(Server Object Model) 01.物理对象层次结构
- Sharepoint学习笔记 –架构系列—Sharepoint的服务器端对象模型(Server Object Model) 3.服务层次结构
- 老调重弹:JDBC系列 之 <JDBC层次结构和基本构成>
- Makefile之大型工程项目子目录Makefile的一种通用写法
- 如何实现具有层次结构的 TreeView <三> (WPF/TreeView/Style/Template)
- Sharepoint学习笔记 –架构系列—Sharepoint的服务器端对象模型(Server Object Model) 2.内容层次结构
- SharePoint 【架构系列】-- Sharepoint的服务器端对象模型(Server Object Model) 03.服务层次结构
- 如何实现具有层次结构的 TreeView 模版使用