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已經成功生成了。

相關文章
相關標籤/搜索