先手工建立幾個文件目錄: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已經成功生成了。