快速编写“专家级”makefile(4.打造更专业的编译环境——管理对库的依赖关系)

    对于前面的 Makefile , 当我们改动了 foo.c 文件时,会导致 libfoo.a 库的重新编译,但并没有使得 huge.exe 重新编译。原因是:我们只是指定了 huge.exe 生成时所需的库,并没有让 huge.exe 依赖于这些库文件,所以库文件的改动并不能使得 huge.exe 被重新编译
    解决:前面提出, LINK_LIBS 已经指明了 huge.exe 生成时所需库文件,我们可以让 huge.exe 依赖于这些库。要让 huge.exe 依赖于这些库,必须列出库的具体路径。LINK_LIBS 变量中可能会指定一些并非是由 huge 项目生成的库,比如系统库 libc.a 等。显然,对于不是有 huge 项目生成的库, huge.exe 不应该依赖于它们。对此,LINK_LIBS 变量中的库文件,应当需要检查它们是否存在于 build / libs 目录中,如果不存在于这一目录中,则不应该将这些库当做是 huge.exe 的先决条件。
    huge / build / make.rule
  
  
  1. .PHONY : all clean
  2. NKDIR = mkdir
  3. RM = rm
  4. RMFLAG = -rf
  5. CC = gcc
  6. AR = ar
  7. ARFLAG = crs
  8. DIR_OBJS = objs
  9. DIR_EXES = $(ROOT)/build/exes
  10. DIR_DEPS = deps
  11. DIR_LIBS = $(ROOT)/build/libs
  12. DIRS = $(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(DIR_LIBS)
  13. RMS = $(DIR_OBJS) $(DIR_DEPS)
  14. ifneq("$(EXE)", "")
  15. EXE := $(addprefix $(DIR_EXES)/, $(EXE))
  16. RMS += $(EXE)
  17. endif
  18. ifneq("$(LIB)", "")
  19. LIB := $(addprefix $(DIR_LIBS)/, $(LIB))
  20. RMS += $(LIB)
  21. endif
  22. SRCS = $(wildcard *.c)
  23. OBJS = $(SRCS :.c = .o)
  24. OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
  25. DEPS = $(SRCS :.c = .dep)
  26. DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))
  27. ifeq("$(wildcard $(DIR_OBJS))", "")
  28. DEP_DIR_OBJS := $(DIR_OBJS)
  29. endif
  30. ifeq("$(wildcard $(DIR_EXES))", "")
  31. DEP_DIR_EXES := $(DIR_EXES)
  32. endif
  33. ifeq("$(wildcard $(DIR_DEPS))", "")
  34. DEP_DIR_DEPS := $(DIR_DEPS)
  35. endif
  36. ifeq("$(wildcard $(DIR_LIBS))", "")
  37. DEP_DIR_LIBS := $(DIR_LIBS)
  38. endif
  39. all : $(EXE) $(LIB)
  40. ifneq($MAKECMDGOALS, clean)
  41. include $(DEPS)
  42. endif
  43. ifneq($(INCLUDE_DIRS), "")
  44. INCLUDE_DIRS := $(strips $(INCLUDE_DIRS))
  45. INCLUDE_DIRS := $(addprefix -I, $(INCLUDE_DIRS))
  46. endif
  47. ifneq($(LINK_LIBS), "")
  48. LINK_LIBS := $(strip $(LINK_LIBS))
  49. LIB_ALL := $(notdir $(wildcard $(DIR_LIBS)/*))
  50. LIB_FILTERED := $(addsuffix %, $(addprefix lib, $(LINK_LIBS)))
  51. $(eval DEP_LIBS = $(filter $(LIB_FILTERED), $(LIB_ALL)))
  52. DEP_LIBS := $(addprefix $(DIB_LIBS)/, $(DEP_LIBS))
  53. LINK_LIBS := $(addprefix -l, $(LINK_LIBS))
  54. endif
  55. $(DIRS) :
  56. $(MKDIR) $@
  57. $(EXE) : $(DEP_DIR_EXE) $(OBJS) $(DEP_LIBS)
  58. $(CC) -L$(DIR_LIBS) -o $@ $(filter %.o, $^)
  59. $(LIB) : $(DEP_DIR_LIB) $(OBJS)
  60. $(AR) $(ARFLAG) $@ $(filter %.o, $^)
  61. $(DIR_OBJS) / %.o : $(DEP_DIR_OBJS) %.c
  62. $(CC) $(INCLUDE_DIRS) -o $@ -c $(filter %.c, $^)
  63. $(DIR_DEPS) / %.dep : $(DEP_DIR_DEPS) %.c
  64. @echo "Creating $@ ..."
  65. @set -e;\
  66. $(RM) $(RMFLAG) $@.tmp;\
  67. $(CC) $(INCLUDE_DIRS) -E -MM $(filter %.c, $^) > $@.tmp;\
  68. sed 's,\(.*\)\.o[ :]*,objs/\1.o $@: ,g' < $@.tmp > $@;\
  69. $(RM) $(RMFLAG) $@.tmp
  70. clean :
  71. $(RM) $(RMFLAG) $(RMS)
    其中,第一次使用到 notdir 和 eval 函数以获得 huge.exe 所依赖的库文件的具体路径。$(DEP_LIBS) 最后被当做 $(EXE) 目标的先决条件
    运行结果:
/Makefile/huge/build
$ touch /Makefile/huge/code/foo/src/foo.c
$ make
make[1] : Entering directory  /Makefile/huge/code/foo/src
make[1] : Nothing to be done for all'
make[1] : Leaving directory  /Makefile/huge/code/foo/src
make[1] : Entering directory  /Makefile/huge/code/bar/src
Creating deps / bar.dep ...
make[1] : Leaving directory  /Makefile/huge/code/bar/src
make[1] : Entering directory  /Makefile/huge/code/bar/src
gcc -I/Makefile/huge/code/foo/inc  -o  objs/bar.o  -c  bar.c
ar crs /Makefile/huge/build/libs/libbar.a  objs/bar.o
make[1] : Leaving directory  /Makefile/huge/code/bar/src
make[1] : Entering directory  /Makefile/huge/code/huge/src
gcc -L/Makefile/huge/build/libs -o /Makefile/huge/build/exes/huge.exe  objs/main.o  -lfoo -lbar
make[1] : Leaving directory  /Makefile/huge/code/huge /src
:-) Completed
            参考文献:《专业嵌入式软件开发》李云·著                                                             2016年7月6日,星期三
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值