Makefile学习笔记系列4:Makefile模板化

Posted fanchenxinok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Makefile学习笔记系列4:Makefile模板化相关的知识,希望对你有一定的参考价值。

在上一个系列3的文章:https://blog.csdn.net/u010312436/article/details/52461906 中已经实现具有子目录层次结构的makefile写法,即主目录Makefile调用到每个子目录中的Makefile编译相应子目录的代码。但是每增加一个子目录又得为这个子目录添加一个为该子目录编译的Makefile文件,似乎有点麻烦。于是想到是不是可以写一个Makefile的模板文件,主目录和子目录只需要include这个模板,并且修改写变量就可以。

百度搜索了下,参考了下https://blog.csdn.net/hmsiwtv/article/details/20905177/这篇文章并修改了下使其可以编译c和c++程序。感谢这篇文章作者的分享。

(1)首先看下我的目录结构:

 

将Makefile模板文件Makefile.base放在include目录下, lib目录存放logout,receiver, responser, sender子模块编译出的静态库。

其中logout为c语言写的程序,其他三个子目录为c++写的程序。

Makefile 的模板 Makefile.base如下,具体说明可以查看https://blog.csdn.net/hmsiwtv/article/details/20905177/

###########  MakeFile.env  ##########
# Top level pattern, include by Makefile of child directory
# in which variable like TOPDIR, TARGET or LIB may be needed

CC=gcc
XX=g++

MAKE=make

AR=ar cr
RM = -rm -rf

CFLAGS+=-Wall -g

### 查找当前目录下的子目录####
dirs:=$(shell find . -maxdepth 1 -type d)
dirs:=$(basename $(patsubst ./%,%,$(dirs)))
dirs:=$(filter-out $(exclude_dirs),$(dirs))
SUBDIRS := $(dirs)

XX_SRCS=$(wildcard *.cpp)
SRCS=$(wildcard *.c)

XX_OBJS=$(XX_SRCS:%.cpp=%.o)
OBJS+=$(SRCS:%.c=%.o)

XX_DEPENDS=$(XX_SRCS:%.cpp=%.d)
DEPENDS=$(SRCS:%.c=%.d)

all:$(TARGET) $(XX_TARGET) $(LIB) subdirs

$(LIB):$(XX_OBJS) $(OBJS)
	$(AR)  $@  $^
	cp $@ $(LIBPATH)

#######如果不是main 所在的目录
#######当target和xx_target都不存在的时候
#ifeq ($(TARGET)$(XX_TARGET),)   
#	for dir in $(SUBDIRS);\\
#		do $(MAKE) -C $$dir all||exit 1;\\
#	done
#endif

####编译目标文件前先编译子目录的文件#####
$(TARGET):$(OBJS) subdirs	
	$(CC) -o $@ $< $(LDFLAGS)
	#cp $@ $(EXEPATH)

$(XX_TARGET):$(XX_OBJS) subdirs
	$(XX) -o $@ $< $(LDFLAGS)
	#cp $@ $(EXEPATH)

subdirs:$(SUBDIRS)
	for dir in $(SUBDIRS);\\
		do $(MAKE) -C $$dir all||exit 1;\\
	done

$(OBJS):%.o:%.c
	$(CC) -c $< -o $@ $(CFLAGS)
	
$(XX_OBJS):%.o:%.cpp
	$(XX) -c $< -o $@ $(CFLAGS)

-include $(DEPENDS)

$(DEPENDS):%.d:%.c
	set -e; rm -f $@; \\
	$(CC) -MM $(CFLAGS) $< > $@.$$$$; \\
	sed 's,\\($*\\)\\.o[:]*,\\1.o $@:,g' < $@.$$$$ > $@; \\
	rm $@.$$$$

-include $(XX_DEPENDS)

$(XX_DEPENDS):%.d:%.cpp
	set -e; rm -f $@; \\
	$(XX) -MM $(CFLAGS) $< > $@.$$$$; \\
	sed 's,\\($*\\)\\.o[:]*,\\1.o $@:,g' < $@.$$$$ > $@; \\
	rm $@.$$$$
	
.PHONY : clean
clean:
	$(RM) mainApp lib/*.a
	for dir in $(SUBDIRS);\\
		do $(MAKE) -C $$dir clean||exit 1;\\
	done
	$(RM) $(TARGET) $(LIB)  $(OBJS) $(DEPENDS) \\
			$(XX_TARGET) $(XX_OBJS) $(XX_DEPENDS)

 主目录下的Makefile如下:

TOPDIR=.

exclude_dirs= include lib

XX_TARGET=mainApp

LIBPATH=$(TOPDIR)/lib/
EXEPATH=$(TOPDIR)

CFLAGS=  -I$(TOPDIR)/include/ -I$(TOPDIR)/sender/ -I$(TOPDIR)/receiver/\\
		-I$(TOPDIR)/responser/ -I$(TOPDIR)/logout/ 
LDFLAGS= -L$(LIBPATH) -lSender -lResponser -lReceiver -lLogout -lpthread -lrt

include $(TOPDIR)/include/Makefile.base

exclude_dirs:表示遍历该文件下子目录时需要排除的目录,因为include和lib目录不需要编译所以在这里把它们添加进去。

XX_TARGET:表示编译出的目标可执行文件

CFLAGS 指定头文件的目录

LDFLAGS 指定需要的链接库

 可以看出这个makefile只需定义一些参数然后include 模板Makefile.base文件即可。

再来看下子目录的Makefile写法:

TOPDIR=./..

LIB=libReceiver.a

LIBPATH=$(TOPDIR)/lib
CFLAGS= -I$(TOPDIR)/include/ -I$(TOPDIR)/responser/ -I./

include $(TOPDIR)/include/Makefile.base

也变得更简单了。

有了模板其他目录的Makefile写的更简单了有木有。哈哈

代码github仓库地址:https://github.com/fanchenxinok/Makefile_models

有错误麻烦指出,谢谢。

 

 

 

 

以上是关于Makefile学习笔记系列4:Makefile模板化的主要内容,如果未能解决你的问题,请参考以下文章

Makefile学习笔记

makefile学习笔记

[转]Linux学习笔记——例说makefile 头文件查找路径

Linux -- Makefile的学习笔记以及多级目录下Makefile的编写

Linux学习笔记——例说makefile 索引博文

linux学习笔记--工具