首页 > 解决方案 > 干出我的 Makefile:当命令因单个可派生参数而异时,避免重复 Makefile 配方

问题描述

我正在使用 Makefile 从一组参数文件中生成模板。参数文件被命名values-<something>.yml,生成的模板被命名template-<something>-<network_mode>.yml,其中<network_mode>可以是podbridge

除了网络模式参数(可以从目标文件名派生)之外,生成两个模板的命令相同。

我希望我能写出这样的规则:

%-template-bridge.yml %-template-pod.yml: values-%.yml
    NM=$@; NM=$${NM#*template-}; NM=$${NM%.yml}; \
    echo "something something network mode $$NM" > $@ || {rm -f $@; exit 1}

不幸的是,虽然这在请求单个文件时效果很好:

$ make cirros-template-bridge.yml
touch "cirros-template-bridge.yml"
$ make cirros-template-pod.yml
touch "cirros-template-pod.yml"

请求多个文件时它不起作用:

$ make cirros-template-bridge.yml cirros-template-pod.yml
touch "cirros-template-bridge.yml"
make: Nothing to be done for 'cirros-template-pod.yml'.
$ make cirros-template-bridge.yml cirros-template-pod.yml
make: 'cirros-template-bridge.yml' is up to date.
touch "cirros-template-pod.yml"

注意它第一次生成,但在第二次调用之前cirros-template-bridge.yml拒绝生成。cirros-template-pod.yml我认为这是因为我尝试使用的语法意味着“以下配方将生成这两个文件”,这是不正确的。

这里有什么解决方案?我显然可以创建两个单独的模式规则,像这样......

%-template-pod.yml: values-%.yml
    echo "something something network mode pod" > $@ || {rm -f $@; exit 1}

%-template-bridge.yml: values-%.yml
    echo "something something network mode bridge" > $@ || {rm -f $@; exit 1}

...但这意味着我需要使两个配方的命令行保持同步。我真的想要像Make“子程序”这样的东西。有更好的选择吗?

标签: templatesmakefile

解决方案


如果你有很多这样的东西,你可以做一些事情,比如foreach用等创建一个循环,eval但由于你只有两个规则,我认为最简单的解决方案是将配方放入一个变量中,并在两个规则中使用它,如下所示:

MAKE_TEMPLATE = NM=$@; NM=$${NM\#*template-}; NM=$${NM%.yml}; \
    echo "something something network mode $$NM" > $@ || { rm -f $@; exit 1; }

%-template-pod.yml: values-%.yml
        $(MAKE_TEMPLATE)
%-template-bridge.yml: values-%.yml
        $(MAKE_TEMPLATE)

推荐阅读