Makefile 10——打造更专业的编译环境-huge项目
先手工创建几个文件目录:
接下来先创建code/foo/src目录下的Makefile:
1 .PHONY: all clean 2 3 MKDIR = mkdir 4 RM = rm 5 RMFLAGS = -rf 6 7 CC =gcc 8 AR =ar 9 ARFLAGS =crs 10 11 DIR_OBJS=objs 12 DIR_EXES=../../../build/exes 13 DIR_DEPS=deps 14 DIR_LIBS=../../../build/libs 15 DIRS =$(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(DIR_LIBS) 16 RMS=$(DIR_OBJS) $(DIR_DEPS) 17 18 EXE= 19 ifneq ("$(EXE)","") 20 EXE :=$(addprefix $(DIR_EXES)/,$(EXE)) 21 RMS +=$(EXE) 22 endif 23 24 LIB=libfoo.a 25 ifneq ("$(LIB)","") 26 LIB :=$(addprefix $(DIR_LIBS)/,$(LIB)) 27 RM +=$(LIB) 28 endif 29 30 SRCS=$(wildcard *.c) 31 OBJS=$(SRCS:.c=.o) 32 OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS)) 33 DEPS=$(SRCS:.c=.dep) 34 DEPS:=$(addprefix $(DIR_DEPS)/,$(DEPS)) 35 36 ifeq ("$(wildcard $(DIR_OBJS))","") 37 DEP_DIR_OBJS :=$(DIR_OBJS) 38 endif#dir_objs 39 ifeq ("$(wildcard $(DIR_EXES))","") 40 DEP_DIR_EXES :=$(DIR_EXES) 41 endif#dir_exes 42 ifeq ("$(wildcard $(DIR_DEPS))","") 43 DEP_DIR_DEPS :=$(DIR_DEPS) 44 endif#dir_deps 45 ifeq ("$(wildcard $(DIR_LIBS))","") 46 DEP_DIR_LIBS :=$(DIR_LIBS) 47 endif#dir_libs 48 49 all: $(EXE) $(LIB) 50 ifneq ($(MAKECMDGOALS),clean) 51 include $(DEPS) 52 endif#clean 53 54 $(DIRS): 55 $(MKDIR) $@ 56 $(EXE):$(DEP_DIR_EXES) $(OBJS) 57 $(CC) -o $@ $(filter %.o,$^) 58 $(LIB):$(DEP_DIR_LIBS) $(OBJS) 59 $(AR) $(ARFLAGS) $@ $(filter %.o,$^) 60 $(DIR_OBJS)/%.o:$(DEP_DIR_OBJS) %.c 61 $(CC) -o $@ -c $(filter %.c,$^) 62 $(DIR_DEPS)/%.dep:$(DEP_DIR_DEPS) %.c 63 @echo "Creating $@ ..." 64 @set -e;\ 65 $(RM) $(RMFLAGS) $@.tmp;\ 66 $(CC) -E -MM $(filter %.c,$^) > $@.tmp;\ 67 sed 's,\(.*\)\.o[:]*,objs/\1.o $@:,g' <$@.tmp >$@;\ 68 $(RM) $(RMFLAGS) $@.tmp 69 70 clean: 71 $(RM) $(RMFLAGS) $(RMS)
具体和complicated项目的差别可以看书或者上篇随笔。
第一个提示没有那个目录,可以在include的时候加上'-'就可以忽略这个,因为这里对我们的项目没有实质影响,但是新手对于报错或者警告总是不放心,故再次提示一下。
从运行结果来看,的确在build/libs目录下生成了一个libfoo.a库文件。运行make clean之后,也没有删除build/libs这个目录,而只是删除库文件libfoo.a
下面要做的就是将这个Makefile运用到code/huge/src目录。
增进复用性:
可以将公用部分放入一个独立的文件中——这就是bulid目录下make.rule文件的作用。这需要我们却别哪些是公用哪些是不能公用的变量。
在考虑复用的情况下,foo模块的Makefile有两部分组成,分别是bulid目录中的make.rule和code/foo/src目录中的Makefile。
foo模块中的Makefile比较简单,因为大部分代码移植道理make.rule中:
make.rule如下:
1 .PHONY: all clean 2 3 MKDIR = mkdir 4 RM = rm 5 RMFLAGS = -rf 6 7 CC =gcc 8 AR =ar 9 ARFLAGS =crs 10 11 DIR_OBJS=objs 12 DIR_EXES=$(ROOT)/build/exes 13 DIR_DEPS=deps 14 DIR_LIBS=$(ROOT)/build/libs 15 DIRS =$(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(DIR_LIBS) 16 RMS=$(DIR_OBJS) $(DIR_DEPS) 17 18 19 ifneq ("$(EXE)","") 20 EXE :=$(addprefix $(DIR_EXES)/,$(EXE)) 21 RMS +=$(EXE) 22 endif 23 24 25 ifneq ("$(LIB)","") 26 LIB :=$(addprefix $(DIR_LIBS)/,$(LIB)) 27 RM +=$(LIB) 28 endif 29 30 SRCS=$(wildcard *.c) 31 OBJS=$(SRCS:.c=.o) 32 OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS)) 33 DEPS=$(SRCS:.c=.dep) 34 DEPS:=$(addprefix $(DIR_DEPS)/,$(DEPS)) 35 36 ifeq ("$(wildcard $(DIR_OBJS))","") 37 DEP_DIR_OBJS :=$(DIR_OBJS) 38 endif#dir_objs 39 ifeq ("$(wildcard $(DIR_EXES))","") 40 DEP_DIR_EXES :=$(DIR_EXES) 41 endif#dir_exes 42 ifeq ("$(wildcard $(DIR_DEPS))","") 43 DEP_DIR_DEPS :=$(DIR_DEPS) 44 endif#dir_deps 45 ifeq ("$(wildcard $(DIR_LIBS))","") 46 DEP_DIR_LIBS :=$(DIR_LIBS) 47 endif#dir_libs 48 49 all: $(EXE) $(LIB) 50 ifneq ($(MAKECMDGOALS),clean) 51 include $(DEPS) 52 endif#clean 53 54 $(DIRS): 55 $(MKDIR) $@ 56 $(EXE):$(DEP_DIR_EXES) $(OBJS) 57 $(CC) -o $@ $(filter %.o,$^) 58 $(LIB):$(DEP_DIR_LIBS) $(OBJS) 59 $(AR) $(ARFLAGS) $@ $(filter %.o,$^) 60 $(DIR_OBJS)/%.o:$(DEP_DIR_OBJS) %.c 61 $(CC) -o $@ -c $(filter %.c,$^) 62 $(DIR_DEPS)/%.dep:$(DEP_DIR_DEPS) %.c 63 @echo "Creating $@ ..." 64 @set -e;\ 65 $(RM) $(RMFLAGS) $@.tmp;\ 66 $(CC) -E -MM $(filter %.c,$^) > $@.tmp;\ 67 sed 's,\(.*\)\.o[:]*,objs/\1.o $@:,g' <$@.tmp >$@;\ 68 $(RM) $(RMFLAGS) $@.tmp 69 70 clean: 71 $(RM) $(RMFLAGS) $(RMS)
如果想运行foo模块中的Makefile,先要在shell上导出所需的ROOT变量:
期间出现了一个问题,我检查了很久Makefile并没有发现问题,但是就是显示没有规则创建目标,最后,用vim重新输入了一下include后面的路径,就解决了,用vscode输入莫名奇妙不行,又没有出现TAB建这样字符,可能是文本编辑器本身的差异吧,但是vim是肯定不会出现格式不兼容问题的。所以以后还是用vim写Makefile把。
完成上面的之后,我们需要考虑把code/huge/src目录中的Makefile了,我们希望这个目录中存放的程序能生成一个可执行文件。在测试Makefile之前,我们现在该目录中放一个main.c文件,内容如下:
1 int main(void) 2 { 3 return 0; 4 }
Makefile如下所示:
1 EXE =huge_app 2 3 LIB = 4 5 include $(ROOT)/build/make.rule
从结果看huge_app已经成功生成了。
欢迎加入作者的小圈子
扫描下方左边二维码加入QQ交流群,扫描下方右边二维码关注个人微信公众号并获取更多隐藏干货,QQ交流群:816747642 微信公众号:Crystal软件学堂
作者:Crystal软件学堂 bilibili视频教程地址:https://space.bilibili.com/5782182 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在转载文章页面给出原文连接。 如果你觉得文章对你有所帮助,烦请点个推荐,你的支持是我更文的动力。 文中若有错误,请您务必指出,感谢给予我建议并让我提高的你。 |