上一节我们完成了第一阶段的任务,这一节我们来完成第二阶段的任务:

编译静态库的工作是调用模块的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自动解决掉。

 

 

posted on 2018-10-01 18:04  周伯通789  阅读(221)  评论(0编辑  收藏  举报