一般而言,不同的工程师负责不同的模块开发,写一段代码之后我们一般要先编译一下,确定一下有没有语法错误,但是,如果将整个工程完整编译一遍非常耗费时间,那么编译环境如何支持模块的独立编译呢?
上图中我们执行make main则只编译main模块。模块独立编译也方便了单元测试。
模块独立编译的解决方案:
关键技术:
第一个依赖是build文件夹,第二个依赖是build文件夹下的模块文件夹。
依赖中不要使用自动变量,依赖中的$@并不会被make解释器认为是目标的名字。
使用MAKECMDGOALS,MAKECMDGOALS是预定义的变量,是make命令的目标。执行make common时,common就是make的目标。
上一节的编译环境:
我们的工作就是修改pro-rule.mk文件的内容,支持模块独立编译。
pro-rule.mk的最新代码如下:
1 .PHONY : all compile link clean rebuild $(MODULES) 2 3 DIR_PROJECT := $(realpath .) 4 DIR_BUILD_SUB := $(addprefix $(DIR_BUILD)/, $(MODULES)) 5 MODULE_LIB := $(addsuffix .a, $(MODULES)) 6 MODULE_LIB := $(addprefix $(DIR_BUILD)/, $(MODULE_LIB)) 7 8 9 APP := $(addprefix $(DIR_BUILD)/, $(APP)) 10 11 define makemodule 12 cd $(1) && \ 13 $(MAKE) all \ 14 DEBUG:=$(DEBUG) \ 15 DIR_BUILD:=$(addprefix $(DIR_PROJECT)/, $(DIR_BUILD)) \ 16 DIR_COMMON_INC:=$(addprefix $(DIR_PROJECT)/, $(DIR_COMMON_INC)) \ 17 CMD_CFG:=$(addprefix $(DIR_PROJECT)/, $(CMD_CFG)) \ 18 MOD_CFG:=$(addprefix $(DIR_PROJECT)/, $(MOD_CFG)) \ 19 MOD_RULE:=$(addprefix $(DIR_PROJECT)/, $(MOD_RULE)) && \ 20 cd .. ; 21 endef 22 23 all : compile $(APP) 24 @echo "Success! Target ==> $(APP)" 25 26 compile : $(DIR_BUILD) $(DIR_BUILD_SUB) 27 @echo "Begin to compile ..." 28 @set -e; \ 29 for dir in $(MODULES); \ 30 do \ 31 $(call makemodule, $$dir) \ 32 done 33 @echo "Compile Success!" 34 35 link $(APP) : $(MODULE_LIB) 36 @echo "Begin to link ..." 37 $(CC) -o $(APP) -Xlinker "-(" $^ -Xlinker "-)" $(LFLAGS) 38 @echo "Link Success!" 39 40 $(DIR_BUILD) $(DIR_BUILD_SUB) : 41 $(MKDIR) $@ 42 43 clean : 44 @echo "Begin to clean ..." 45 $(RM) $(DIR_BUILD) 46 @echo "Clean Success!" 47 48 rebuild : clean all 49 50 $(MODULES) : $(DIR_BUILD) $(DIR_BUILD)/$(MAKECMDGOALS) 51 @echo "Begin to compile $@" 52 @set -e; \ 53 $(call makemodule, $@) 54
第一行中添加模块的名字,每一个模块的名字都作为伪目标。这样就可以独立编译模块了。
我们定义了makemodule函数,在第53行调用。这样就防止了代码的复制粘贴。
MAKECMDGOALS是预定义的变量,是make命令的目标。
小结: