1 开发环境
1、软件环境:ubuntu14.04
2. openwrt版本:openwrt 官方15.05版本SDK开发包(CHAOS CALMER 15.05版本)
2 功能说明
在openwrt的package中,如果出现文件夹重名。
例如,出现“package/dir1/a” 和“package/dir2/a” 两个目录结构,在a和a两个目录中分别都含有各自的makefiel和源代码。
如此,则必然出现大量的编译警告:
package/Makefile:196: warning: ignoring old commands for target...
package/Makefile:196: warning: overriding commands for target...
这个问题是由于openwrt本身的索引规则有问题导致的。
3 问题分析
3.1 增加打印调试信息
既然问题出现在“package/Makefile:196”,打开Makefile,可以看到,问题出现的代码为:
$(eval $(call subdir,$(curdir)))
问题来自于调用 subdir 函数,采用warning对该函数进行调试,修改之后,代码如下。
$(warning $(call subdir,$(curdir)))
$(eval $(call subdir,$(curdir)))
3.2 调试信息
增加完打印信息之后,可以看到,信息如下:
package/dir1/a/compile:
@+ $(SUBMAKE) -C package/dir1/a compile BUILD_VARIANT=""
# aliases
package/a/compile: package/dir1/a/compilekage/dir2/a/compile:
@+ $(SUBMAKE) -C package/dir2/a compile BUILD_VARIANT=""
# aliases
package/a/compile: package/dir2/a/compile
从调试信息可以看到,问题在与package/a/compile 这个编译规则被定义了两次。
# aliases
package/a/compile: package/dir1/a/compile
# aliases
package/a/compile: package/dir2/a/compile
所以,出现了编译警告,提示“package/a/compile” 的编译规则被覆盖了,重复定义。
3.3 问题分析
通过调试发现,问题的原因在于openwrt的subdir函数有问题,创建编译规则的时候,总是以目录下最后一个文件夹的名称为标准。
查看subdir函数代码“include/subdir.mk”
# Parameters: <subdir>
47 define subdir
48 $(call warn,$(1),d,D $(1))
49 $(foreach bd,$($(1)/builddirs),
50 $(call warn,$(1),d,BD $(1)/$(bd))
51 $(foreach target,$(SUBTARGETS),
52 $(foreach btype,$(buildtypes-$(bd)),
53 $(call warn_eval,$(1)/$(bd),t,T,$(1)/$(bd)/$(btype)/$(target): $(if $(QUILT),,$($(1)/$(bd)/$(btype)/$(target)) $(call $(1)//$(btyp
54 $(call log_make,$(1)/$(bd),$(target),$(btype),$(filter-out __default,$(variant))) \
55 $(if $(findstring $(bd),$($(1)/builddirs-ignore-$(btype)-$(target))), || $(call ERROR,$(1), ERROR: $(1)/$(bd) [$(btype)] fai
56 $(if $(call diralias,$(bd)),$(call warn_eval,$(1)/$(bd),l,T,$(1)/$(call diralias,$(bd))/$(btype)/$(target): $(1)/$(bd)/$(btype)/$(
57 )
58 $(call warn_eval,$(1)/$(bd),t,T,$(1)/$(bd)/$(target): $(if $(QUILT),,$($(1)/$(bd)/$(target)) $(call $(1)//$(target),$(1)/$(bd))))
59 $(foreach variant,$(if $(BUILD_VARIANT),$(BUILD_VARIANT),$(if $(strip $($(1)/$(bd)/variants)),$($(1)/$(bd)/variants),$(if $($(1)/$
60 $(if $(BUILD_LOG),@mkdir -p $(BUILD_LOG_DIR)/$(1)/$(bd)/$(filter-out __default,$(variant)))
61 $(call log_make,$(1)/$(bd),$(target),,$(filter-out __default,$(variant))) \
62 $(if $(findstring $(bd),$($(1)/builddirs-ignore-$(target))), || $(call ERROR,$(1), ERROR: $(1)/$(bd) failed to build$(if
63 )
64 $(if $(PREREQ_ONLY)$(DUMP_TARGET_DB),,
65 # aliases
66 $(if $(call diralias,$(bd)),$(call warn_eval,$(1)/$(bd),l,T,$(1)/$(call diralias,$(bd))/$(target): $(1)/$(bd)/$(target)))
67 )
68 )
69 )
70 $(foreach target,$(SUBTARGETS),$(call subtarget,$(1),$(target)))
71 endef
其中,问题出现在第66行的“diralias(别名)”函数,该函数的作用为找到最后一个文件夹,取出该文件夹名称。
29 lastdir=$(word $(words $(subst /, ,$(1))),$(subst /, ,$(1)))
30 diralias=$(if $(findstring $(1),$(call lastdir,$(1))),,$(call lastdir,$(1)))
3.4 解决方法
既然问题在于diralias函数总是以最后一个文件夹名称作为返回值,所以有同名文件夹出现警告。那么可以将编译规则修改,让最后的索引方法,采用路径+文件夹名称。这样就不会出现最后的编译规则定义出现重复。
我们最终要实现的目标,实现前:
# aliases
package/a/compile: package/dir1/a/compile
# aliases
package/a/compile: package/dir2/a/compile
实现后
# aliases
package/dir1@a/compile: package/dir1/a/compile
# aliases
package/dir2@a/compile: package/dir2/a/compile
解决方法:
(1)在“include/subdir.mk”文件中,增加一行代码,添加重命名函数:
31 dirRename=$(subst /,@,$(1))
(2)修改openwrt之前定义编译名称的代码
# aliases
$(if $(call diralias,$(bd)),$(call warn_eval,$(1)/$(bd),l,T,$(1)/$(call dirRename,$(bd))/$(target): $(1)/$(bd)/$(target)))
将之前的
$(call diralias,$(bd))/$(target)...
修改为
$(call dirRename,$(bd))/$(target)...
如此,最终编译的时候,创建的编译规则名称如下,问题解决。
# aliases
package/dir1@a/compile: package/dir1/a/compile
# aliases
package/dir2@a/compile: package/dir2/a/compile