动态生成Makefile规则
我有一个Makefile,用来调用不同的子Makefile 我有几条规则:动态生成Makefile规则,makefile,Makefile,我有一个Makefile,用来调用不同的子Makefile 我有几条规则: 全部 干净的 fclean 再 我已经可以使用这些规则了,它们将使用相同的规则调用每个子makefile 我有几个项目,我想用这种格式生成规则: $(项目名称)-(规则) 因此,我希望每个项目都有以下规则: project1-all project1-clean ... project2-all project2-clean ... 这样,我就可以为特定的项目调用特定的规则,比如project1fclea
- 全部
- 干净的
- fclean
- 再
$(项目名称)-(规则)
因此,我希望每个项目都有以下规则:
project1-all
project1-clean
...
project2-all
project2-clean
...
这样,我就可以为特定的项目调用特定的规则,比如project1fclean
我试过:
RULES= all clean fclean re
PROJECTS= project1 project2
define NEWLINE
endef
$(foreach _rule, $(RULES), \
$(foreach _proj, $(PROJECTS), \
$(_proj)-$(_rule): $(NEWLINE) \
$(MAKE) $(ARGS) $(PROJECT_DIR)$(_proj) $(_rule) $(NEWLINE) \
) \
)
但它似乎不起作用。我已经搜索过了,但还没有找到实现这一点的高级makefile技术。Plz帮助。问题是,当您将行与这样的行连续体组合在一起时,它会压缩掉所有的换行符和其他无关的空格(包括您试图用
$(换行符)
插入的换行符),从而导致单行上出现巨大的混乱,而不是使用多个模式的多行。要正确执行此操作,您需要将规则编写为带有参数的宏,然后调用它:
define PROJ_RULE
$(1)-$(2):
$(MAKE) $(ARGS) $(PROJECT_DIR)$(1) $(2)
endef
$(foreach _rule, $(RULES),
$(foreach _proj, $(PROJECTS),
$(eval $(call PROJ_RULE, $(_proj), $(_rule)))))
请注意,GNU中所有这些
定义和foreach
东西都是make-specific的——其他make风格不支持它。好的,所以我最终设法这样做:
$(foreach _rule, $(RULES), $(addsuffix -$(_rule),$(PROJECTS))):
$(eval _rule := $(lastword $(subst -, ,$@)))
$(eval _proj := $(@:%-$(_rule)=%))
@$(MAKE) $(ARGS) $(PROJECT_DIR)$(_proj) $(_rule)
为了更好地解释,我将对其进行分解:
$(foreach _rule, $(RULES), ...)):
我们循环每个规则并将其存储在_rule中
$(addsuffix -$(_rule),$(PROJECTS))
我们将该规则作为前缀添加到每个项目中。该部分使用每个“组合规则”生成一个规则。对于projet1
和project2
,应导致:
project1-all project2-all project1-clean project2-clean project1-fclean project2-fclean project1-re project2-re:
这样,对于这些规则名称中的任何一个,都将执行相同的规则
$(eval _rule := $(lastword $(subst -, ,$@)))
在这里,我们将目标(如果我将project2称为clean,$@
将成为
),我们将-
替换为一个空格,以获得project2 clean
,并将最后一个工作,它将是clean
。然后我们对其进行评估,将其存储到\u rule
中
$(eval _proj := $(@:%-$(_rule)=%))
我们使用相同的技术将项目名称存储到\u proj
中。我们只是使用一个模式替换来删除规则名和破折号
@$(MAKE) $(ARGS) $(PROJECT_DIR)$(_proj) $(_rule)
最后,我们称我们的子基文件为正确路径和正确规则 它似乎对我不起作用,它告诉我多目标模式。我知道不能将多个模式组合为目标模式(如%.o
),在这里,这取决于$(1)-(2)
是否为模式。我想是的。我现在已经找到了一个“丑陋”的解决方案,但你的解决方案似乎更美观。是的,如果在$(项目)
或$(规则)
中有任何%%
,这将不起作用,但你的示例似乎不需要%
,所以我不确定它们来自何处。这个答案几乎是正确的,但它没有接到eval的电话,所以它不起作用。用$(eval)包装顶级foreach,它就工作了。我回到这里是因为我仍然有问题。看来克里斯搞定了。为什么不在每个顶层添加$(eval)呢?但是,像Chris在这里所做的那样,将其放在内部确实有效。由于$(foreach
开始于第一列(没有前面的选项卡或空格),在始终展开之后,它应该作为makefile语法进行计算,因此显式$(eval不应该是必需的,但它似乎只在GNUmake的某些版本中起作用。在其他版本中,eval是必需的;我不确定是哪一个版本。显然,您有一个版本不仅需要eval,而且必须在foreach中。$(call
line可能是问题的原因;显式的$(调用前后立即eval
可以避免这种情况。与其递归调用make
,我建议您看看非递归的makefile
方法。有一篇文章介绍了递归make的缺点:。您可以尝试使用我的模板库获取非递归的makefile: