Makefile学习11————打造更专业的编译环境-huge项目

先手工建立几个文件目录:shell

 

接下来先建立code/foo/src目录下的Makefile:vim

.PHONY: all clean

MKDIR = mkdir
RM = rm
RMFLAGS = -rf

CC =gcc
AR =ar
ARFLAGS =crs

DIR_OBJS=objs
DIR_EXES=../../../build/exes
DIR_DEPS=deps
DIR_LIBS=../../../build/libs
DIRS =$(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(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))
RM +=$(LIB)
endif

SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS))
DEPS=$(SRCS:.c=.dep)
DEPS:=$(addprefix $(DIR_DEPS)/,$(DEPS))

ifeq ("$(wildcard $(DIR_OBJS))","")
DEP_DIR_OBJS :=$(DIR_OBJS)
endif#dir_objs
ifeq ("$(wildcard $(DIR_EXES))","")
DEP_DIR_EXES :=$(DIR_EXES)
endif#dir_exes
ifeq ("$(wildcard $(DIR_DEPS))","")
DEP_DIR_DEPS :=$(DIR_DEPS)
endif#dir_deps
ifeq ("$(wildcard $(DIR_LIBS))","")
DEP_DIR_LIBS :=$(DIR_LIBS)
endif#dir_libs

all: $(EXE) $(LIB)
ifneq ($(MAKECMDGOALS),clean)
include $(DEPS)
endif#clean

$(DIRS):
    $(MKDIR) $@
$(EXE):$(DEP_DIR_EXES) $(OBJS)
    $(CC) -o $@ $(filter %.o,$^)
$(LIB):$(DEP_DIR_LIBS) $(OBJS)
    $(AR) $(ARFLAGS) $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o:$(DEP_DIR_OBJS) %.c 
    $(CC) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.dep:$(DEP_DIR_DEPS) %.c
    @echo "Creating $@ ..."
    @set -e;\
    $(RM) $(RMFLAGS) $@.tmp;\
    $(CC) -E -MM $(filter %.c,$^) > $@.tmp;\
    sed 's,\(.*\)\.o[:]*,objs/\1.o $@:,g' <$@.tmp >$@;\
    $(RM) $(RMFLAGS) $@.tmp

clean:
    $(RM) $(RMFLAGS) $(RMS)

 

具体和complicated项目的差异能够看书或者上篇随笔。app

 

第一个提示没有那个目录,能够在include的时候加上'-'就能够忽略这个,由于这里对咱们的项目没有实质影响,可是新手对于报错或者警告老是不放心,故再次提示一下。编辑器

 

从运行结果来看,的确在build/libs目录下生成了一个libfoo.a库文件。运行make clean以后,也没有删除build/libs这个目录,而只是删除库文件libfoo.a 测试

下面要作的就是将这个Makefile运用到code/huge/src目录。ui

增进复用性:spa

能够将公用部分放入一个独立的文件中——这就是bulid目录下make.rule文件的做用。这须要咱们区别哪些是公用哪些是不能公用的变量。code

在考虑复用的状况下,foo模块的Makefile由两部分组成,分别是bulid目录中的make.rule和code/foo/src目录中的Makefile。blog

foo模块中的Makefile比较简单,由于大部分代码移植到make.rule中:class

EXE=
LIB =libfoo.a
include $(ROOT)/build/make.rule

make.rule以下:

.PHONY: all clean

MKDIR = mkdir
RM = rm
RMFLAGS = -rf

CC =gcc
AR =ar
ARFLAGS =crs

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


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


ifneq ("$(LIB)","")
LIB :=$(addprefix $(DIR_LIBS)/,$(LIB))
RM +=$(LIB)
endif

SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS))
DEPS=$(SRCS:.c=.dep)
DEPS:=$(addprefix $(DIR_DEPS)/,$(DEPS))

ifeq ("$(wildcard $(DIR_OBJS))","")
DEP_DIR_OBJS :=$(DIR_OBJS)
endif#dir_objs
ifeq ("$(wildcard $(DIR_EXES))","")
DEP_DIR_EXES :=$(DIR_EXES)
endif#dir_exes
ifeq ("$(wildcard $(DIR_DEPS))","")
DEP_DIR_DEPS :=$(DIR_DEPS)
endif#dir_deps
ifeq ("$(wildcard $(DIR_LIBS))","")
DEP_DIR_LIBS :=$(DIR_LIBS)
endif#dir_libs

all: $(EXE) $(LIB)
ifneq ($(MAKECMDGOALS),clean)
include $(DEPS)
endif#clean

$(DIRS):
    $(MKDIR) $@
$(EXE):$(DEP_DIR_EXES) $(OBJS)
    $(CC) -o $@ $(filter %.o,$^)
$(LIB):$(DEP_DIR_LIBS) $(OBJS)
    $(AR) $(ARFLAGS) $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o:$(DEP_DIR_OBJS) %.c 
    $(CC) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.dep:$(DEP_DIR_DEPS) %.c
    @echo "Creating $@ ..."
    @set -e;\
    $(RM) $(RMFLAGS) $@.tmp;\
    $(CC) -E -MM $(filter %.c,$^) > $@.tmp;\
    sed 's,\(.*\)\.o[:]*,objs/\1.o $@:,g' <$@.tmp >$@;\
    $(RM) $(RMFLAGS) $@.tmp

clean:
    $(RM) $(RMFLAGS) $(RMS)

若是想运行foo模块中的Makefile,先要在shell上导出所需的ROOT变量:

期间出现了一个问题,我检查了好久Makefile并无发现问题,可是就是显示没有规则建立目标,最后,用vim从新输入了一下include后面的路径,就解决了,用vscode输入莫名奇妙不行,又没有出现TAB建这样字符,多是文本编辑器自己的差别吧,可是vim是确定不会出现格式不兼容问题的。因此之后仍是用vim写Makefile把。

完成上面的以后,咱们须要考虑把code/huge/src目录中的Makefile了,咱们但愿这个目录中存放的程序能生成一个可执行文件。在测试Makefile以前,咱们如今该目录中放一个main.c文件,内容以下: 

 int main(void)
 {
     return 0;
 }

Makefile以下所示:

 EXE =huge_app
 
 LIB =
 
 include $(ROOT)/build/make.rule

从结果看huge_app已经成功生成了。

相关文章
相关标签/搜索