上一节我们完成了第一阶段的任务,这一节我们来完成第二阶段的任务:
编译静态库的工作是调用模块的makefile完成的。
实现要点:
只有知道了项目中有哪些模块,才能知道对应的文件夹的名字。
我们做如下的假设:项目中的模块基本稳定,模块名字直接写到makefile中去
makefile中嵌入shell的for循环:
set-e告诉make解释器,遇到错误立即退出执行。
shell for循环示例如下:
结果如下:
makefile中嵌入shell for循环示例:
结果如下:
工程的顶层makefile:
本节的目录架构如下:
进入到模块的文件夹后会调用模块的makefile。
各个模块的静态库有了之后会进行最终的链接。
上一节中的makefile是每个模块的makefile,模块makefile在模块的根目录下,这一节的顶层makefile会调用模块makefile。
顶层的makefile如下:
1 .PHONY : all compile link clean rebuild 2 3 MODULES := common 4 module 5 main 6 7 MKDIR := mkdir 8 RM := rm -fr 9 10 CC := gcc 11 LFLAGS := 12 13 DIR_PROJECT := $(realpath .) 14 DIR_BUILD := build 15 DIR_BUILD_SUB := $(addprefix $(DIR_BUILD)/, $(MODULES)) 16 MODULE_LIB := $(addsuffix .a, $(MODULES)) 17 MODULE_LIB := $(addprefix $(DIR_BUILD)/, $(MODULE_LIB)) 18 19 APP := app.out 20 APP := $(addprefix $(DIR_BUILD)/, $(APP)) 21 22 all : compile $(APP) 23 @echo "Success! Target ==> $(APP)" 24 25 compile : $(DIR_BUILD) $(DIR_BUILD_SUB) 26 @echo "Begin to compile ..." 27 @set -e; 28 for dir in $(MODULES); 29 do 30 cd $$dir && $(MAKE) all DEBUG:=$(DEBUG) && cd .. ; 31 done 32 @echo "Compile Success!" 33 34 link $(APP) : $(MODULE_LIB) 35 @echo "Begin to link ..." 36 $(CC) -o $(APP) -Xlinker "-(" $^ -Xlinker "-)" $(LFLAGS) 37 @echo "Link Success!" 38 39 $(DIR_BUILD) $(DIR_BUILD_SUB) : 40 $(MKDIR) $@ 41 42 clean : 43 @echo "Begin to clean ..." 44 $(RM) $(DIR_BUILD) 45 @echo "Clean Success!" 46 47 rebuild : clean all
执行make之后的现象:
build文件夹下内容如下:
链接要点:
默认情况下的遵循自左向右的依赖关系,如果库的实际依赖关系不是这样的话则链接会报错。
-Xlinker会让gcc去确定依赖关系,只是会耗一点时间。
上图中为-Xlinker的固定格式,依赖关系会由gcc自动解决掉。