写一个常用的通用makefile

想法是可以对于当前目录中子目录分别执行make 得到对应的obj文件

同时可以指定排除某些目录或者文件。

进行一些基础的控制


第一步 获取当前目录中的 子目录 获取.c文件以及.cpp文件

实现排除 不需要编译的目录 排除不需要编译的c 和cpp文件。

寻找当前目录的子目录


dirs := $(shell find . -maxdepth 1 -type d) 利用shell命令


使用模式替换函数patsubst 去掉./ 和.

8.2.2
$(patsubst PATTERN,REPLACEMENT,TEXT)
函数名称:模式替换函数—patsubst。
函数功能:搜索“TEXT”中以空格分开的单词,将否符合模式“TATTERN”替换为
“REPLACEMENT”。参数“PATTERN”中可以使用模式通配符“%”来代表一
个单词中的若干字符。如果参数“REPLACEMENT”中也包含一个“%”,那么
“REPLACEMENT”中的“%”将是“TATTERN”中的那个“%”所代表的字符串。
在“TATTERN”和“REPLACEMENT”中,只有第一个“%”被作为模式字符来
处理,之后出现的不再作模式字符(作为一个字符)。在参数中如果需要将
第一个出现的“%”作为字符本身而不作为模式字符时,可使用反斜杠“\”进行转义处理(转义处理的机制和使用静态模式的转义一致,具体可
参考
5.12.1
静态模式规则的语法
一小节)。
返回值:替换后的新字符串。
函数说明:参数“TEXT”单词之间的多个空格在处理时被合并为一个空格,并忽略前
导和结尾空格。
示例:
$(patsubst %.c,%.o,x.c.c bar.c)
把字串“x.c.c bar.c”中以.c 结尾的单词替换成以.o 结尾的字符。函数的返回结
果是“x.c.o bar.o”


dirs := $(patsubst ./%,%,$(dirs))

dirs := $(patsubst .%,%,$(dirs))


加入过滤选项则是

dirs := $(filter-out $(exclude_dirs),$(dirs))


注意对于=和:=     的区别

“=”

      make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:

            x = foo
            y = $(x) bar
            x = xyz

      在上例中,y的值将会是 xyz bar ,而不是 foo bar 。

      2、“:=”

      “:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。

            x := foo
            y := $(x) bar
            x := xyz

      在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。



接下来就是对子目录能够执行 make命令

$(SUBDIRS):
@for everydirectory in  $(SUBDIRS); do \
echo $$everydirectory; \
done


注意两点

1 shell必须在一行内,因makefile一条命令必须占一行。同时。shell放在一行的时候 必须注意有些命令末尾必须加上分号。

2 对于shell中展开字符串,必须用两个$$符号。第一个$用于在makefile中展开。第二个$用于在shell中展开




简单测试和修改

INTERNAL_OBJ=__internal_target.o

CLEAN_FILES?=
INCLUDE_DIRS?=
LINK_LIBS?=
LINK_LIB_PATH?=
CFLAGS?=


-include option.mk

dirs:=$(shell find . -maxdepth 1 -type d)
dirs:=$(patsubst ./%,%,$(dirs))
dirs:=$(filter-out .%,$(dirs))
dirs:=$(filter-out $(EXCLUDE_DIRS),$(dirs))

SUBDIRS=$(dirs)
SUBDIRS+= ../src/

CFLAGS+= -O3 -Wall

ifdef DEBUG
AT=
else
AT=@
endif


CFILES=$(wildcard *.c)
CPPFILES=$(wildcard *.cpp)

CFILES:=$(filter-out $(EXCLUDE_SRCFILE),$(CFILES))
CPPFILES:=$(filter-out $(EXCLUDE_SRCFILE),$(CPPFILES))

COBJS  :=$(patsubst %.c,%.o,$(CFILES))
CPPOBJS:=$(patsubst %.cpp,%.o,$(CPPFILES))

ALLOBJS:=$(addsuffix /$(INTERNAL_OBJ),$(SUBDIRS))
ALLOBJS:=$(ALLOBJS) $(COBJS) $(CPPOBJS)

CLEAN=clean distclean
.PHONY:$(SUBDIRS) $(CLEAN) $(INTERNAL_OBJ)


ifeq ($(strip $(ALLOBJS)),)
$(INTERNAL_OBJ):
	$(AT)ar -rcs $@
else
$(INTERNAL_OBJ):$(COBJS) $(CPPOBJS) $(SUBDIRS)
	$(AT)ld -r $(ALLOBJS) -o $@
endif



%.o:%.c
	$(AT)gcc $(CFLAGS) -c -o $@ $< $(INCLUDE_DIRS) $(LINK_LIB_PATH) $(LINK_LIBS)


%.o:%.cpp
	$(AT)g++ $(CFLAGS) -c -o $@ $< $(INCLUDE_DIRS) $(LINK_LIB_PATH) $(LINK_LIBS)

$(SUBDIRS):
	$(AT)for everydirectory in $(SUBDIRS);do \
		make -C $$everydirectory;\
	done

$(CLEAN):
	$(AT)rm -rf *.o $(CLEAN_FILES)
	$(AT)for everydirectory in $(SUBDIRS);do \
		make -C $$everydirectory $@;\
	done
	








options.mk中就比较简单了。加入一些基础的编译变量就好了

#option.mk specific flags
#
#CLEAN_FILES
# make clean or make distclean
#example
# CLEAN_FILES+= filea.o fileb.o filec.o
#
#
#INCLUDE_DIRS
#gcc g++ include directory
# example 
#INCLUDE_DIRS+= -I/usr/xxx/include -I../../
#
#
#
#LINK_LIB_PATH
#gcc g++ lib search path
#LINK_LIB_PATH+= -L/lib/xxx/ -L../libx86/
#
#
#
#gcc g++ link library
#LINK_LIBS
#example 
#LINK_LIBS+= -lboost_system -lpthread
#
#
#
#
#CFLAGS
#example
#CFLAGS+= -O3 -Wall -std=c++0x
#-std==c++11
#
#
#EXCLUDE_DIRS
#
#example 
#EXCLUDE_DIRS += doc 
#exclude build dir in current directory
#
#
#
#
#
#
#EXCLUDE_SRCFILE
#example
#EXCLUDE_SRCFILE+= a.c b.c m.cpp w.cpp
#exclude srcfiles in current directory
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#

#EXCLUDE_DIRS+=common
#CFLAGS+= -std=c++0x
#INCLUDE_DIRS+= -I../header/

################################
#
#  build binary example
#
#TARGET_BIN=main
#$(TARGET_BIN):$(INTERNAL_OBJ)
#	g++ -o $(TARGET_BIN) $(CFLAGS) $(INTERNAL_OBJ) $(INCLUDE_DIRS) $(LINK_LIB_PATH) $(LINK_LIBS)
#	strip $(TARGET_BIN)
#
#
#
################################

################################
#
#  build shared library example
#
#CFLAGS+= -std=c++0x -fPIC
#TARGET_SHARED_LIB=libeasycnn.so
#$(TARGET_SHARED_LIB):$(INTERNAL_OBJ)
#	g++ -o $(TARGET_SHARED_LIB) $(CFLAGS) -shared  $(INTERNAL_OBJ)
#	strip $(TARGET_SHARED_LIB)
#CLEAN_FILES+=$(TARGET_SHARED_LIB)

#
#
#
################################


################################
#
#  build static library example
#
#CFLAGS+= -std=c++0x
#TARGET_STATIC_LIB=libmystatic.a
#$(TARGET_STATIC_LIB):$(INTERNAL_OBJ)
#	ar rc $(TARGET_STATIC_LIB) $(INTERNAL_OBJ)
#CLEAN_FILES+=$(TARGET_STATIC_LIB)
#
################################

#LINK_LIBS+= -lpthread
#TARGET_BIN=main
#$(TARGET_BIN):$(INTERNAL_OBJ)
#	g++ -o $(TARGET_BIN) $(CFLAGS) $(INTERNAL_OBJ) $(INCLUDE_DIRS) $(LINK_LIB_PATH) $(LINK_LIBS)
#	strip $(TARGET_BIN)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值