makefile目标中重复的百分比字符串
我希望以以下形式表示目标和依赖项:makefile目标中重复的百分比字符串,makefile,build,Makefile,Build,我希望以以下形式表示目标和依赖项: 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. 是否有一种不依赖于预先列出模块可能值的解决方法 (这不是的重复,因为他们想为所
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.
是否有一种不依赖于预先列出模块可能值的解决方法
(这不是的重复,因为他们想为所有可能的
(STR1,STR2)
元组集生成形式为dir\u STR1/target\u 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) $@
这是可能的,原则上很简单,但由于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) $@
您可能希望尝试与配方模板一起使用
MODULES = mod1 mod2
define MODULE_RULE
dir_$(1)/target_$(1):dep_$(1)
touch $$@
endef
$(foreach mod,$(MODULES),$(eval $(call MODULE_RULE,$(mod))))
对于模块
中的每个项目,将按照模式dir\u MODULE/target\u MODULE:dep\u MODULE
生成一条显式规则。这是一种非常方便的方法来构造遵循特定模式的多个规则,但不容易用简单的%
-规则来解决
编辑:
如果以前不知道模块列表,并且应该通过扫描所有dep
名称来确定,则只需使用:
MODULES=$(patsubst dep_%,%,$(wildcard dep_*))
获取所有模块名称的步骤
此外,如果您希望将所有dir\u XXX/target\u XXX
目标作为另一个目标的先决条件,例如all
,您可以从模块名称重构所有dir\u XXX/target\u XXX
名称,如下所示:
DIR_NAMES = $(patsubst %,dir_%/,$(MODULES))
TARGET_NAMES = $(patsubst %,target_%,$(MODULES))
FULLPATH_TARGETS = $(join $(DIR_NAMES),$(TARGET_NAMES))
all: $(FULLPATH_TARGETS)
此外,如果以前不存在dir\u XXX
,您可以创建另一个规则来创建它们。完整的生成文件可能如下所示:
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)
您可能希望尝试与配方模板一起使用
MODULES = mod1 mod2
define MODULE_RULE
dir_$(1)/target_$(1):dep_$(1)
touch $$@
endef
$(foreach mod,$(MODULES),$(eval $(call MODULE_RULE,$(mod))))
对于模块
中的每个项目,将按照模式dir\u MODULE/target\u MODULE:dep\u MODULE
生成一条显式规则。这是一种非常方便的方法来构造遵循特定模式的多个规则,但不容易用简单的%
-规则来解决
编辑:
如果以前不知道模块列表,并且应该通过扫描所有dep
名称来确定,则只需使用:
MODULES=$(patsubst dep_%,%,$(wildcard dep_*))
获取所有模块名称的步骤
此外,如果您希望将所有dir\u XXX/target\u XXX
目标作为另一个目标的先决条件,例如all
,您可以从模块名称重构所有dir\u XXX/target\u XXX
名称,如下所示:
DIR_NAMES = $(patsubst %,dir_%/,$(MODULES))
TARGET_NAMES = $(patsubst %,target_%,$(MODULES))
FULLPATH_TARGETS = $(join $(DIR_NAMES),$(TARGET_NAMES))
all: $(FULLPATH_TARGETS)
此外,如果以前不存在dir\u XXX
,您可以创建另一个规则来创建它们。完整的生成文件可能如下所示:
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)
这是有用的信息,但我特别问是否有一个解决方案不涉及硬编码模块列表。这可以通过扩展此答案非常容易地完成。我还以为你在生成规则而不是生成模块名时遇到了麻烦。答案已编辑。您编辑的答案仍然需要一个模块名称列表,只是这次它们被记录在文件系统中。这是有用的信息,但我特别询问是否有一个解决方案不涉及对模块列表进行硬编码。通过扩展此答案,这可以非常容易地完成。我还以为你在生成规则而不是生成模块名时遇到了麻烦。答案已编辑。您编辑的答案仍然需要一个模块名称列表,只是这次它们被记录在文件系统中。