快速编写“专家级”makefile(4.打造更专业的编译环境——实现库链接)

    根据前面所运行结果,main.o 被正确地生成了,但在链接时因为找不到 foo() 函数的实现而出现错误。由于 foo() 函数的实现是放在 libfoo.a 库中的,而 Makefile 中并没有告诉编译器在生成 huge.exe 时需要与 libfoo.a 库链接在一起
    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. LINK_LIBS := $(addprefix -l, $(LINK_LIBS))
  50. endif
  51. $(DIRS) :
  52. $(MKDIR) $@
  53. $(EXE) : $(DEP_DIR_EXE) $(OBJS)
  54. $(CC) -L$(DIR_LIBS) -o $@ $(filter %.o, $^)
  55. $(LIB) : $(DEP_DIR_LIB) $(OBJS)
  56. $(AR) $(ARFLAG) $@ $(filter %.o, $^)
  57. $(DIR_OBJS) / %.o : $(DEP_DIR_OBJS) %.c
  58. $(CC) $(INCLUDE_DIRS) -o $@ -c $(filter %.c, $^)
  59. $(DIR_DEPS) / %.dep : $(DEP_DIR_DEPS) %.c
  60. @echo "Creating $@ ..."
  61. @set -e;\
  62. $(RM) $(RMFLAG) $@.tmp;\
  63. $(CC) $(INCLUDE_DIRS) -E -MM $(filter %.c, $^) > $@.tmp;\
  64. sed 's,\(.*\)\.o[ :]*,objs/\1.o $@: ,g' < $@.tmp > $@;\
  65. $(RM) $(RMFLAG) $@.tmp
  66. clean :
  67. $(RM) $(RMFLAG) $(RMS)
    huge / code / foo / src / Makefile
   
   
  1. EXE =
  2. LIB = libfoo.a
  3. INCLUDE_DIRS = $(ROOT)/code/foo/inc
  4. LINK_LIBS =
  5. include $(ROOT)/build/make.rule
    huge / code / huge / src / Makefile
   
   
  1. EXE = huge.exe
  2. LIB =
  3. INCLUDE_DIRS = $(ROOT)/code/foo/inc
  4. LINK_LIBS = foo
  5. include $(ROOT)/build/make.rule
    其中改动如下:
  1. 增加 LINK_LIBS 变量, 用于存放可执行程序在链接时所需的所有库
  2. 将 $(DIR_LIBS) 通过 gcc 的 -L 选项加入到编译器的库搜索目录列表中。在 huge 项目中,将所有的库文件都放到 DIR_LIBS 目录下,简化了 Makefile 的实现
  3. 在各模块的 src 目录下的 Makefile 中增加了 LINK_LIBS 变量的定义, 且在 code / huge / src / Makefile 中对 LINK_LIBS 赋值为 foo。
    运行结果:
$ make
/Makefile/huge/build/make.rule:43: deps / foo.dep:No such file or directory
mkdir deps
Creating deps / foo.dep
mkdir objs
gcc -I/Makefile/huge/code/foo/libs/inc  -o  objs/foo.o  -c  foo.c
gcc -L/Makefile/huge/build/libs -o /Makefile/huge/build/exes/huge.exe  objs/main.o  -lfoo
$ $ROOT/build/exes/huge.exe
This is foo ()!
    
    现在,往 huge 项目中增加一个 bar 模块,这个模块将生成 libbar.a 静态库
    huge / code / bar / inc / bar.h
  
  
  1. #ifndef __BAR_H
  2. #define __BAR_H
  3. void bar();
  4. #endif
    huge / code / bar / inc / bar.c
  
  
  1. #include <stdio.h>
  2. #include "bar.h"
  3. void bar()
  4. {
  5. printf("This is bar ()!\n");
  6. }
    huge / code / bar / src / Makefile
  
  
  1. EXE =
  2. LIB = libbar.a
  3. INCLUDE_DIRS = $(ROOT)/code/bar/inc
  4. LINK_LIBS =
  5. include $(ROOT)/build/make.rule
    新增目录结构:

                             
    为了构建 libbar.a,需要进入 code / bar / src 目录并运行 make 命令
$ make
/Makefile/huge/build/make.rule:43: deps / bar.dep:No such file or directory
mkdir deps
Creating deps / bar.dep
mkdir objs
gcc -I/Makefile/huge/code/bar/libs/inc  -o  objs/bar.o  -c  bar.c
ar crs /Makefile/huge/build/libs/libbar.a   objs/bar.o
$ ls $ROOT/build/libs
libfoo.a  libbar.a
    在前面 code / huge / src / Makefile 的基础上,作以下改动:
    huge / code / huge / src / main.c
  
  
  1. #include "foo.h"
  2. #include "bar.h"
  3. int main()
  4. {
  5. foo();
  6. bar();
  7. return 0;
  8. }
    huge / code / huge / src / Makefile
  
  
  1. EXE = huge.exe
  2. LIB =
  3. INCLUDE_DIRS = $(ROOT)/code/foo/inc \
  4. $(ROOT)/code/foo/inc
  5. LINK_LIBS = foo bar
  6. incldue $(ROOT)/build/make.rule
    运行结果:
/Makefile/huge/code/huge/src
$ make
Creating deps / main.dep ...
gcc -I/Makefile/huge/code/foo/inc  -I/Makefile/huge/code/bar/inc -o  objs/main.o  -c  main.c
gcc -L/Makefile/huge/build/libs -o /Makefile/huge/build/exes/huge.exe  objs/main.o  -lfoo -lbar
$ $ROOT/build/exes/huge.exe
This is foo ()!
This is bar()!
            参考文献:《专业嵌入式软件开发》李云·著                                                             2016年7月5日,星期二
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值