为什么$(shell ls)在makefile任务开始时被扩展?

时间:2018-09-09 16:18:41

标签: bash shell makefile

我有以下代码:

foo:

    touch foo

    $(foreach f, $(shell ls | grep foo), \
        echo $f; \
    )

它不会列出上面的foo创建的文件touch foo,而是列出任务开始之前foo文件是否已经存在,像这样:

$ make foo # first time call, file 'foo' doesn't exists yet

$ make foo # second time call, file 'foo' already exists
  foo

在执行了以上所有命令之后,是否可以评估ls

1 个答案:

答案 0 :(得分:1)

这就是Make的工作方式。解析Makefile并调用任何Makefile函数,然后然后评估一个或多个配方。

您是否有理由不仅仅使用shell循环?

foo:
    touch foo
    for f in *foo*; do \
         echo "$$f"; \
    done

请注意,需要如何将美元符号加倍以使其免受make的评估,以及通常应如何将Shell变量加双引号,除非您特别要求Shell在以下位置执行空白标记和通配符扩展值。

另一方面,更“虚假”的方法是显式记录所有依赖项。

.PHONY: all
all: foo
     printf '%s\n' $^
foo:
     touch $@

现在all依赖于foo,因此,如果foo不存在,则必须知道必须创建all才能执行foo配方,或相对于其自身的依赖关系已过时(当然,目前没有依赖关系)。

make变量$^引用当前目标的依赖项,$@扩展到当前配方目标。 printf shell脚本是一种更经济的方式,每行打印一件事而没有循环。