我想以以下形式表示目标和依赖项:
dir_MODULE/target_MODULE: dep_MODULE
然而,直观的解决方案不起作用:
dir_%/target_%: dep_%
@echo 1
dir_%/target_$*: dep_%
@echo 2
> make: *** No rule to make target `dir_test/target_test'. Stop.
是否有一种不依赖于预先拥有MODULE可能值列表的解决方案?
(这不是我可以在一个makefile目标中有多个%符号吗?,因为他们想为所有可能的(STR1,STR2)
元组的集合生成形式为dir_STR1/target_STR2
的目标;由于STR1 = STR2
的约束,我的情况更简单。
这是可能的,并且原则上很简单,但是由于Make缺乏正则表达式能力,唯一的解决方案(我可以看到)是丑陋的。
您可以使用"匹配任何东西"规则捕获目标,将该目标的新规则写入单独的文件(special.mk
),然后使用该规则重新运行Make:
-include special.mk
special.mk: # not really necessary, but it soothes Make
@:
ruler = dir_$(1)/target_$(1): dep_$(1)
%:
@echo $(call ruler,$(subst target_,,$(notdir $@))) > special.mk
@echo 't'@echo now building '$@' somehow from $$^ >> special.mk
@$(MAKE) $@
您可能想尝试将eval函数与配方模板一起使用
MODULES = mod1 mod2
define MODULE_RULE
dir_$(1)/target_$(1):dep_$(1)
touch $$@
endef
$(foreach mod,$(MODULES),$(eval $(call MODULE_RULE,$(mod))))
对于MODULES
中的每个条目,将生成一个遵循模式dir_MODULE/target_MODULE: dep_MODULE
的显式规则。这是一种非常方便的方式来构造遵循特定模式的多个规则,但不容易用简单的%
规则来解决。
如果模块列表以前不知道,应该通过扫描所有dep
名称来确定,那么只需使用:
MODULES=$(patsubst dep_%,%,$(wildcard dep_*))
获取所有模块名
同样,如果您想让所有dir_XXX/target_XXX
目标成为另一个目标的先决条件,例如all
,您可以从模块名称中重建所有dir_XXX/target_XXX
名称,如下所示:
DIR_NAMES = $(patsubst %,dir_%/,$(MODULES))
TARGET_NAMES = $(patsubst %,target_%,$(MODULES))
FULLPATH_TARGETS = $(join $(DIR_NAMES),$(TARGET_NAMES))
all: $(FULLPATH_TARGETS)
同样,如果以前不存在dir_XXX
,您可以创建另一个规则来创建它们。完整的makefile可能如下所示:
MODULES = $(patsubst dep_%,%,$(wildcard dep_*))
DIR_NAMES = $(patsubst %,dir_%/,$(MODULES))
TARGET_NAMES = $(patsubst %,target_%,$(MODULES))
FULLPATH_TARGETS = $(join $(DIR_NAMES), $(TARGET_NAMES))
dir_%:
mkdir -p $@
define MODULE_RULE
dir_$(1)/target_$(1):dep_$(1) dir_$(1)
touch $$@
endef
$(foreach mod,$(MODULES),$(eval $(call MODULE_RULE,$(mod))))
all: $(FULLPATH_TARGETS)