11

我想在 makefile中读取一个名为metafile的文件。

元文件看起来像这样:
file1
file2
file3

我需要逐行读取我的makefile中的这个元文件,并检查里面提到的文件是否存在,并且只打印存在的文件的名称。

我已经尝试了一些没有成功的事情。喜欢:

FILE=`cat metafile`
for line in $(FILE); if [ -e $${line} ]; then echo $${line} fi; done;
4

1 回答 1

17

您可以将任意一段 shell 脚本放入目标中。将文件的内容保存在 Makefile 变量中对我来说没有任何意义,除非您出于其他原因还需要其他目标中的数据。(如果是这样,无论如何你不能使用反引号。)

target:
        @while read -r file; do \
            test -e "$$file" && echo "$$file"; \
        done <metafile

值得一提的是,与使用反引号while的循环相比,循环是一种更安全、更惯用的方式来循环 shell 脚本中的文件行,即使您经常看到这种方式。for

@防止 Make 回显 shell 脚本命令;如果出于某种原因您需要查看它们,请将其删除。事实上,我建议不要使用它,尤其是在你调试的时候——一旦你确信你的配方可以正常工作,就使用它make -s来静默运行。make

在 Makefile 中执行此操作的一种更惯用的方法是让目标依赖于这些文件,并使用 Make 自己的逻辑:

target: file1 file2 file3
        @echo $(filter-out $?,$^)

这是 GNU Make 语法;如果您想移植到其他 Make 风格,它可能会变得更加复杂(毕竟可能 shell 脚本更可取)。它将在一行上回显所有内容,但如果您需要单独的行,那应该是一个简单的修复。

我会简单地构建一个小的辅助 Makefile 片段并包含依赖项:

target: target.d
target.d: metafile
        sed 's/^/target: /' $< >$@
include target.d

这会构建一个小的依赖项列表,因此您无需在target:依赖项中明确列出它们;所以不是file1 file2 file3在上面的配方中,依赖项将存在于生成target.d的包含

target: file1
target: file2
target: file3

您需要过滤掉对的依赖target.d(或不声明它;我相信 GNU Make 应该可以应付)。

于 2012-11-28T21:12:30.877 回答