首页 > 解决方案 > 如何将 makefile 目标更改为函数?

问题描述

我正在寻找一种干净的方法来将我在 makefile 中创建的一些目标声明更改为更具功能性的类型声明,在该声明中我可以传递变量并且输出将保持一致。

例如:

default: clean run1 run2

run1:
    for entity in $(FLIST_01); do \
        echo $entity ; \
    done

run2:
    for entity in $(FLIST_02); do \
         echo $entity ; \
    done

理想情况下,我想删除重复的运行目标声明,并且只有 1 个。

FLIST_01 = my_flist.txt
FLIST_02 = other.txt

default: clean run

run:
    $(run_func $(FLIST_01))
    $(run_func $(FLIST_02))

我如何创建一个自定义函数make来执行 run_func 应该做的事情(传递给它的文件列表变量的 for 循环读取?

更新:

到目前为止,我的尝试是这样的:

run:
    runfunc() { \
        echo "test" \
        for entity in $1; do \
            echo $(entity); \
        done \
    }

    runfunc $(FLIST_01)
    runfunc $(FLIST_02)

但我在 do 行出现语法错误:意外标记“do”附近的语法错误

标签: shellmakefileshgnu-make

解决方案


另一个twopenn'orth。

首先,我们要扩展$FLIST_01目标run1FLIST_02目标run2。一个干净的方法可能是:

FLIST_run1 := a b c
FLIST_run2 := 1 2 3

.PHONY: run1 run2
run1 run2:
    for entity in ${FLIST_$@}; do echo $entity; done

对于一个稍微模糊的解决方案,我们注意到您尝试做的事情可以用make的 noddy 模式匹配来描述:

.PHONY: run1 run2
run%: run1 run2:
    for entity in ${FLIST_$*}; do echo $entity; done

这里我们使用静态模式规则。在配方中,$*扩展为与%模式中匹配的任何内容。这个解决方案对我有黄疸的眼睛来说看起来很干净。

我敦促您寻找惯用的制作而不是惯用的外壳。您的 makefile 几乎总是会感谢您。

首先,保留两个运行目标,而不是将它们合并到同一个配方中。

.PHONY: run1 run2
run%: run1 run2:
    for entity in ${FLIST_$*}; do echo $entity; done

.PHONY: run
run: run1
run: run2
run: ; echo $@ Success

在这里,例如,当您make run时, make首先执行run1的配方,然后执行run2的配方,最后执行 run的配方。

这有什么好处吗?当然。如果你运行make -j2 run那么 run1 和 run2 的命令并行运行真正的全部意义。

最后一个问题是摆脱 shell 循环,并用单独的命令替换它。这样,make将为您检查echo的退出代码,如果合适的话,甚至可以并行运行它们。当然,在这个点头示例中没有帮助,但它们可以是例如编译命令。


推荐阅读