makefile 笔记(下)

22. 建一个名为huge的项目,组织架构如下图,引入了静态库的build,其中ar -crs:ar是用来管理档案文件的,在嵌入式系统中主要是用来对静态库进行管理的,c用于创建一个档案文件,r表示向档案文件中增加文件,t用于显示档案文件中存在哪些文件

makefile 笔记(下)_第1张图片

.PHONY: all clean

MKDIR = mkdir
RM = rm
RMFLAGS = -fr

CC = gcc
AR = ar
ARFLAGS = crs

DIR_OBJS = objs
DIR_EXES = ../../../build/exes
DIR_DEPS = deps
DIR_LIBS = ../../../build/libs
DIRS = $(DIR_DEPS) $(DIR_OBJS) $(DIR_EXES) $(DIR_LIBS)
RMS = $(DIR_OBJS) $(DIR_DEPS)

EXE = 
ifneq ($(EXE), "")
EXE := $(addprefix $(DIR_EXES)/,$(EXE))
RMS += $(EXE)
endif

LIB = libfoo.a
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)


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文档,让我受益匪浅


makefile 笔记(下)_第2张图片

~/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。

你可能感兴趣的:(makefile 笔记(下))