动态生成 Makefile 规则

Lud*_*ope 4 makefile

我有一个 Makefile,我用它来调用不同的子 Makefile。

我有几个规则:

  • 全部
  • 干净的
  • 清洁
  • 关于

我已经可以使用这些规则,它们将使用相同的规则调用每个子 makefile。

我有几个项目,我想用这种格式生成规则:

$(PROJECT_NAME)-$(RULES)

有了这个,我想为每个项目制定每个规则:

project1-all

project1-clean

...

project2-all

project2-clean

...
Run Code Online (Sandbox Code Playgroud)

这样,我就可以为特定项目调用特定规则,例如project1-fclean.

我试过了:

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)  \
    )                                                                     \
)
Run Code Online (Sandbox Code Playgroud)

但它似乎不起作用。我已经搜索过了,但我还没有找到高级的 makefile 技术来实现这一点。请帮忙。

Chr*_*odd 5

问题是,当您将行与这样的行延续组合在一起时,它会压缩所有换行符和其他无关的空格(包括您尝试插入的那些换行符$(NEWLINE)),从而导致一行上的巨大混乱,而不是多行具有多种图案的线条。要正确执行此操作,您需要将规则编写为带参数的宏,然后调用它:

define PROJ_RULE
$(1)-$(2):
        $(MAKE) $(ARGS) $(PROJECT_DIR)$(1) $(2)
endef

$(foreach _rule, $(RULES),
    $(foreach _proj, $(PROJECTS),
        $(eval $(call PROJ_RULE, $(_proj), $(_rule)))))
Run Code Online (Sandbox Code Playgroud)

请注意,GNU中的所有这些defineforeach内容都是特定的——其他 make 风格不支持它。

  • 它似乎对我不起作用,它告诉我“多目标模式”。我知道你不能将多个模式组合为目标(比如 `%.o`),这里这一切都取决于 `$(1)-$(2)` 是否是一个模式。我猜是。我现在找到了一个“丑陋”的解决方案,但你的看起来更美观。 (3认同)

Lud*_*ope 3

好吧,我终于设法这样做了:

$(foreach _rule, $(RULES), $(addsuffix -$(_rule),$(PROJECTS))):
            $(eval _rule := $(lastword $(subst -, ,$@)))
            $(eval _proj := $(@:%-$(_rule)=%))
            @$(MAKE) $(ARGS) $(PROJECT_DIR)$(_proj) $(_rule)
Run Code Online (Sandbox Code Playgroud)

我将对其进行分解以获得更好的解释:

$(foreach _rule, $(RULES), ...)):
Run Code Online (Sandbox Code Playgroud)

我们循环每个规则并将其存储在 _rule 中。

$(addsuffix -$(_rule),$(PROJECTS))
Run Code Online (Sandbox Code Playgroud)

我们将该规则作为前缀添加到每个项目中。这部分为每个“组合规则”生成一个规则。与projet1project2它应该导致:

project1-all project2-all project1-clean project2-clean project1-fclean project2-fclean project1-re project2-re:
Run Code Online (Sandbox Code Playgroud)

这样,对于任何这些规则名称,都将执行相同的规则。

$(eval _rule := $(lastword $(subst -, ,$@)))
Run Code Online (Sandbox Code Playgroud)

这里我们获取目标(如果我调用project2-clean,$@将会 project2-clean),我们-用一个空格替换来获取project2 clean并获取最后的工作,它将在clean这里。然后我们评估它并将其存储到_rule.

$(eval _proj := $(@:%-$(_rule)=%))
Run Code Online (Sandbox Code Playgroud)

我们使用相同的技术将项目名称存储到_proj. 我们只是使用模式替换来删除规则名称和破折号。

@$(MAKE) $(ARGS) $(PROJECT_DIR)$(_proj) $(_rule)
Run Code Online (Sandbox Code Playgroud)

最后,我们称我们的子makefile为正确的路径和正确的规则!