22. 建一个名为huge的项目,组织架构如下图,引入了静态库的build,其中ar -crs:ar是用来管理档案文件的,在嵌入式系统中主要是用来对静态库进行管理的,c用于创建一个档案文件,r表示向档案文件中增加文件,t用于显示档案文件中存在哪些文件
.PHONY: all clean$(RM) $(RMFLAGS) $(RMS)
23. 对22,我们需要抽象和拆分,这样才能为以后复用和维护做好应有的准备,我们把22中可以提炼公共的部分进行修改后放到build目录下的make.rule,把foo特有的部分替换掉原有的makefile,然后通过共用make.rule来达到抽象和拆分的效果,这里引入了一个取名为ROOT环境变量,更改后如下:
make.rule
/////////////////
.PHONY: all clean
MKDIR = mkdir
RM = rm
RMFLAGS = -fr
CC = gcc
AR = ar
ARFLAGS = crs
DIR_OBJS = objs
DIR_EXES = $(ROOT)/build/exes
DIR_DEPS = deps
DIR_LIBS = $(ROOT)/build/libs
DIRS = $(DIR_DEPS) $(DIR_OBJS) $(DIR_EXES) $(DIR_LIBS)
RMS = $(DIR_OBJS) $(DIR_DEPS)
ifneq ($(EXE), "")
EXE := $(addprefix $(DIR_EXES)/,$(EXE))
RMS += $(EXE)
endif
ifneq ($(LIB), "")
LIB := $(addprefix $(DIR_LIBS)/, $(LIB))
RMS += $(LIB)
endif
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
DEPS = $(SRCS:.c=.dep)
DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))
ifneq ($(EXE), "")
all: $(EXE)
endif
ifneq ($(LIB), "")
all: $(LIB)
endif
ifeq ("$(wildcard $(DIR_DEPS))", "")
DEPS_DIR_DEPS := $(DIR_DEPS)
endif
ifneq ($(MAKECMDGOALS), clean)
-include $(DEPS)
endif
$(DIRS):
$(MKDIR) $@
$(EXE): $(DIR_EXES) $(OBJS)
$(CC) -o $@ $(filter %.o,$^)
$(LIB): $(DIR_LIBS) $(OBJS)
$(AR) $(ARFLAGS) $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o: $(DIR_OBJS) %.c
$(CC) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.dep: $(DEPS_DIR_DEPS) %.c
@set -e; \
echo "Making $@ ..."; \
$(RM) $(RMFLAGS) [email protected]; \
$(CC) -E -MM $(filter %.c,$^) > [email protected]; \
set 's,\(.*\)\.o[ :]*,objs/\1.o $@: ,g' < [email protected] > $@; \
$(RM) $(RMFLAGS) [email protected]
clean:
$(RM) $(RMFLAGS) $(RMS)
makefile
//////////////
EXE =
LIB = libfoo.a
include $(ROOT)/build/make.rule
设置ROOT环境变量必须到最外层那个huge目录,然后按以下方式执行command
// screen content begin
$export ROOT=`pwd`
// screen contend end
24. 最后想给出一个模板,不多作解释,并想感谢作者李云老师提供的public文档,让我受益匪浅
~/huge/build
makefile
//////////////
.PHONY: all clean
DIRS = $(ROOT)/source/foo/src \
$(ROOT)/source/bar/src \
$(ROOT)/source/huge/src
RM = rm
RMFLAGS = -fr
RMS = $(ROOT)/build/exes $(ROOT)/build/libs
all:
@set -e; \
for dir in $(DIRS); \
do \
cd $$dir && $(MAKE); \
done
@echo ""
@echo ":-) Completed"
@echo ""
clean:
@set -e; \
for dir in $(DIRS; \
do \
cd $$dir && $(MAKE) clean; \
done
$(RM) $(RMFLAGS) $(RMS)
@echo ""
@echo ":-) Completed"
@echo ""
make.rule
/////////////////
.PHONY: all clean
MKDIR = mkdir
RM = rm
RMFLAGS = -fr
CC = gcc
AR = ar
ARFLAGS = crs
DIR_OBJS = objs
DIR_EXES = $(ROOT)/build/exes
DIR_DEPS = deps
DIR_LIBS = $(ROOT)/build/libs
DIRS = $(DIR_DEPS) $(DIR_OBJS) $(DIR_EXES) $(DIR_LIBS)
RMS = $(DIR_OBJS) $(DIR_DEPS)
ifneq ($(EXE), "")
EXE := $(addprefix $(DIR_EXES)/,$(EXE))
RMS += $(EXE)
endif
ifneq ($(LIB), "")
LIB := $(addprefix $(DIR_LIBS)/, $(LIB))
RMS += $(LIB)
endif
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
DEPS = $(SRCS:.c=.dep)
DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))
ifneq ($(EXE), "")
all: $(EXE)
endif
ifneq ($(LIB), "")
all: $(LIB)
endif
ifeq ("$(wildcard $(DIR_DEPS))", "")
DEPS_DIR_DEPS := $(DIR_DEPS)
endif
ifneq ($(MAKECMDGOALS), clean)
include $(DEPS)
endif
ifneq ($INC_DIRS), "")
INC_DIRS := $(strip $(INC_DIRS))
INC_DIRS := $(addprefix -I, $(INC_DIRS))
endif
ifneq ($(LINK_LIBS), "")
LINK_LIBS := $(strip $(LINK_LIBS))
LINK_LIBS := $(addprefix -l, $(LINK_LIBS))
endif
$(DIRS):
$(MKDIR) $@
$(EXE): $(DIR_EXES) $(OBJS)
$(CC) -L$(DIR_LIBS) -o $@ $(filter %.o,$^) $(LINK_LIBS)
$(LIB): $(DIR_LIBS) $(OBJS)
$(AR) $(ARFLAGS) $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o: $(DIR_OBJS) %.c
$(CC) $(INC_DIRS) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.dep: $(DEPS_DIR_DEPS) %.c
@set -e; \
echo "Making $@ ..."; \
$(RM) $(RMFLAGS) [email protected]; \
$(CC) $(INC_DIRS) -E -MM $(filter %.c,$^) > [email protected]; \
set 's,\(.*\)\.o[ :]*,objs/\1.o $@: ,g' < [email protected] > $@; \
$(RM) $(RMFLAGS) [email protected]
clean:
$(RM) $(RMFLAGS) $(RMS)
~/huge/source/bar/src
makefile
///////////////
EXE =
LIB = libbar.a
INC_DIRS = $(ROOT)/source/bar/inc
LINK_LIBS =
include $(ROOT)/build/make.rule
~/huge/source/foo/src
makefile
//////////////
EXE =
LIB = libfoo.a
INC_DIRS = $(ROOT)/source/foo/inc
LINK_LIBS =
include $(ROOT)/build/make.rule
~/huge/source/huge/src
EXE = huge.exe
LIB =
INC_DIRS = $(ROOT)/source/foo/inc \
$(ROOT)/source/bar/inc
LINK_LIBS = foo bar
include $(ROOT)/build/make.rule
如果需要全部build,则可以在~/huge/build目录下进行make,该makefile已经遍历了所有的从静态库的build到最后exe的build的过程,运用了MAKE特殊变量(表示的是make命令名是什么)。当然,也可以分头build,都在各自的src目录下的makefile。