想法是可以对于当前目录中子目录分别执行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)