外观
09.模块独立编译的支持、第三方库的使用支持
约 1253 字大约 4 分钟
第三方库的使用支持模块独立编译个人随笔
2022-06-20
第二十三部分 :模块独立编译的支持
23.1 问题
一般而言,不同工程师负责不同模块的开发;编译环境中如何支持模块的独立编译?
23.2 问题背景
- 大型项目的代码文件成干上万,完整编译的时间较长
- 编写模块代码时,可通过编译检查语法错误
- 为了提高开发效率,需要支持指定模块的独立编译

23.3 解决方案
- 将模块名( module )作为目标名(伪目标)建立规则
- 目标( module )对应的依赖为build builid/module
- 规则中的命令进入对应的模块文件夹进行编译
- 编译结果存放于build文件夹下
23.4 关键技术点
- 如何获取make命令行中指定编译的模块名?
- 预定义变量:$(MAKECMDGOALS)
- 命令行中指定的目标名(make的命令行参数)

23.5 编程实验:模块的独立编译****make module
- makefile 中的代码复用
- 当不同规则中的命令大量重复时,可考虑自定义函数
- makefile 中的自定义函数是代码复用的一种方式

23.6 思路
- 将编译模块的命令集作为自定义函数的具体实现
- 函数参数为模块名,函数调用后编译参数指定的模块
- 在不同的规则中调用该函数

23.7 编程实验:makefile中的代码复用自定义函数
.PHONY : all compile link clean rebuild $(MODULES)
DIR_PROJECT := $(realpath .)
DIR_BUILD_SUB := $(addprefix $(DIR_BUILD)/, $(MODULES))
MODULE_LIB := $(addsuffix .a, $(MODULES))
MODULE_LIB := $(addprefix $(DIR_BUILD)/, $(MODULE_LIB))
APP := $(addprefix $(DIR_BUILD)/, $(APP))
define makemodule
cd $(1) && \
$(MAKE) all \
DEBUG:=$(DEBUG) \
DIR_BUILD:=$(addprefix $(DIR_PROJECT)/, $(DIR_BUILD)) \
DIR_COMMON_INC:=$(addprefix $(DIR_PROJECT)/, $(DIR_COMMON_INC)) \
CMD_CFG:=$(addprefix $(DIR_PROJECT)/, $(CMD_CFG)) \
MOD_CFG:=$(addprefix $(DIR_PROJECT)/, $(MOD_CFG)) \
MOD_RULE:=$(addprefix $(DIR_PROJECT)/, $(MOD_RULE)) && \
cd .. ;
endef
all : compile $(APP)
@echo "Success! Target ==> $(APP)"
compile : $(DIR_BUILD) $(DIR_BUILD_SUB)
@echo "Begin to compile ..."
@set -e; \
for dir in $(MODULES); \
do \
$(call makemodule, $$dir) \
done
@echo "Compile Success!"
link $(APP) : $(MODULE_LIB)
@echo "Begin to link ..."
$(CC) -o $(APP) -Xlinker "-(" $^ -Xlinker "-)" $(LFLAGS)
@echo "Link Success!"
$(DIR_BUILD) $(DIR_BUILD_SUB) :
$(MKDIR) $@
clean :
@echo "Begin to clean ..."
$(RM) $(DIR_BUILD)
@echo "Clean Success!"
rebuild : clean all
$(MODULES) : $(DIR_BUILD) $(DIR_BUILD)/$(MAKECMDGOALS)
@echo "Begin to compile $@"
@set -e; \
$(call makemodule, $@)23.8 小结
- 编写模块代码时可通过模块独立编译快速检查语法错误
- 自动变量只能在规则的命令中使用,不能在依赖中使用
- makefile 中的自定义函数是代码复用的一种方式
- 当不同规则中的命令大量重复时,可考虑自定义函数
第二十四部分 :第三方库的使用支持
24.1 问题
当需要使用第三方库文件时,编译环境中的makefile 改如何修改?
24.2 经验假设
- 第三方库通过函数调用的方式提供库中的功能
- 库文件发布时都附带了声明库函数原型的头文件
- 编译阶段使用头文件,链接阶段使用库文件
24.3 第三方库在项目中的位置

24.4 第三方库的编译阶段支持
定义变量DIR_LIBS_INC用于指示头文件的存储位置
- DIR_LIBS_INC := $(DIR_PROJECT)/libs/inc
使用DIR_LIBS_INC提示make头文件的存储位置
- vpath %$(TYPE_INC) $(DIR_LIBS_INC)
使用DIR_LIBS_INC提示编译器头文件的存储位置
- CFLAGS += -I$(DIR_LIBS_INC)
24.5 编程实验:第一阶段编译支持
24.6 注意事项
- 定义 DIR_LIBS_LIB := libs/lib(第三方库所在路径)
- 链接时不会直接链接DIR_LIBS_LIB中的库文件
- 需要先将库文件拷贝到DIR_BUILD文件夹
- 必须考虑拷贝后的库文件和原始库文件的新旧关系

24.7 第三方库的链接阶段支持
- 定义变量EXTERNAL_LIB用于保存第三方库列表
- 目标link需要依赖于第三方库列表

第三方库名称与自己的库名称相同时,优先使用自己的库。
24.8 编程实验:第二阶段链接支持
24.9 小结
- 编译环境必须支持第三方库的使用(静态库或动态库)
- 工程开发中一般会使用特殊的文件夹存放第三方库
- 第三方库所附带的头文件用于声明库函数(编译阶段需要)
- 在链接阶段先将库文件拷贝到build文件夹,再进行链接
