【问题标题】:Loop through files in make file循环遍历make文件中的文件
【发布时间】:2020-08-06 16:39:46
【问题描述】:

现在我的 make 文件中有以下内容,用于创建指向当前目录中文件的符号链接:

MY_FILE := "$(SOME_PATH)/file.txt"

ln -s $(MY_FILE)

我想做的是做某种 glob 操作来链接一堆文件(或没有)。

MY_FILES :=  "$(SOME_PATH)/*.txt"
for file in files:
   ln -s $(MY_FILE)     

谁能指出我这样做的正确方向? 谢谢!

【问题讨论】:

  • 为什么要在构建过程中做很多符号链接?它不会作为环境设置类型的东西运行吗?那你为什么不保留一个 shell/batch 文件来创建这些符号链接呢?
  • 现在我每次都需要将大量数据复制到我当前的工作目录中。我想让它在编译时创建符号链接,所以我不必每次都这样做。我想这可能是一个环境设置,但是对于其他文件,我们使用符号链接,所以我宁愿保持工作流程相同。

标签: makefile wildcard


【解决方案1】:

以下应该做你想要的:

MY_FILES := $(wildcard $(SOME_PATH)/*.txt)
LINKS    := $(notdir $(MY_FILES))

.PHONY: links clean-links
links: $(LINKS)

$(LINKS): %: $(SOME_PATH)/%
    ln -s $<

clean-links:
    rm -f $(LINKS)

解释:

  1. 制作函数。 wildcardnotdir 是两个 make functions。了解 make 函数(至少是最常用的)确实有助于编写漂亮、优雅和高效的 make 文件。当然,如果您的文件名中有空格或特殊字符,您会遇到一些问题,因为大多数 make 函数都将空格视为分隔符。但如果你有这样的文件和目录名,你可能应该使用 make 以外的其他东西。

  2. 静态模式规则:

    $(LINKS): %: $(SOME_PATH)/%
    

    static pattern rule。对于$(LINKS) 中的每个单词foo.txt,它会实例化一个单独的make 规则:

    foo.txt: $(SOME_PATH)/foo.txt
        ln -s $(SOME_PATH)/foo.txt
    

    如果您想编写紧凑和通用的 make 文件,了解如何使用模式规则(静态或非静态)是必不可少的。

  3. 自动变量。 $&lt;automatic variable。在食谱(规则的命令部分)中,它作为第一个列出的先决条件进行扩展。还有很多其他的自动变量,编写通用规则非常方便。

  4. 虚假目标。 linksclean-linksphony targets,因为它们与我们想要创建或更新的真实文件不对应。它们是行动的捷径。 make links 创建所有缺失的链接,make clean-links 将它们全部删除。由于 make 无法猜测这些目标不是常规文件名,因此我们使用 .PHONY 特殊目标告诉它。

【讨论】:

  • 静态规则+1。很难理解如何在实践中使用它们,但阅读它是有道理的:-)。 PHONY 目标始终会重新构建,这对于操作很有用,因为如果存在与命令名称相同的文件或文件夹,它们将停止工作(被认为是最新的并被跳过)。
  • 可以links: | $(LINKS) 为我们节省更新现有链接的工作吗?还是我忽略了什么?
  • @Vroomfondel:默认情况下,make 会考虑符号链接目标的最后修改时间,而不是链接本身的最后修改时间。因此,在link-to-file: file 规则中,如果link-to-filefile 存在,它们将具有相同的修改时间并且make 不会更新链接。它将通过构建保持最新。
【解决方案2】:

Make 从“先决条件”创建“目标”。在您的情况下,MY_FILES 拥有创建(链接)目标的先决条件。单个文件的规则可能如下所示:

file.txt: $(SOME_PATH)/file.txt
    ln -s $<

你想要多个文件,在这种情况下我们可以使用这个模式规则:

%.txt: $(SOME_PATH)/%.txt
    ln -s $<

您现在可以使用 make 命令创建链接:

make file.txt
make otherfile.txt

最后,我们将研究 wildcard 函数来获取所有文件,以及函数 notdir 函数从文件名中获取链接名称。以下规则将打印所有文本文件,并取决于链接到当前工作目录的 SOME_PATH 中的所有文件:

MY_FILES := $(notdir $(wildcard $(SOME_PATH)/*.txt))
cat: $(MY_FILES)
    cat $^

%.txt: $(SOME_PATH)/%.txt
    ln -s $<

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    相关资源
    最近更新 更多