【问题标题】:GNU Make and wildcards - missing filesGNU Make 和通配符 - 缺少文件
【发布时间】:2010-12-01 05:30:30
【问题描述】:

我有一个具有以下规则类型的 Makefile:

%.html:
    ./generate-images.py > $@
    make $(patsubst %.png,%.gif,$(wildcard *.png))

generate-images 脚本不仅将 HTML 文件(至标准输出)写入当前目录,还将多个 .png 文件写入当前目录。这里的目标是将它们转换为 .gif。 (不是真的,但这是一个例子)

如果我直接调用它,这将有效。问题是:如果我从 foo.html 是依赖项的另一个规则调用它,则通配符语句无法找到任何文件。换句话说,它只是调用了make,没有任何参数,这不是我想要的。

通配符有什么用?或者,有没有更好的方法来做到这一点?

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    虽然您的问题可能有所不同,但我清楚地看到了一个。

    同时处理规则中所有命令的整个文本,以便扩展make的函数和变量。假设您在目录中没有.png 文件,并且您调用make,因此它应该重新生成它们:a.pngb.png。然后,在您调用 make 之后,规则的文本实际上将如下所示:

    file.html:
        ./generate-images.py > file.html
        make 
    

    因为在读取 makefile 的那一刻没有.png 文件!第一行执行后,文件会出现,但下一行已经生成只是“make”。

    只有当你第二次调用你的makefile时,它才会扩展为

    file.html:
        ./generate-images.py > file.html
        make a.gif b.gif
    

    这不是你想要的。所以我建议以正确的方式来做。

    # If you have batch conversion program, this may be helpful
    images.stamp: *.png
         convert_all_images $?
         touch images.stamp
    
    # OR, if you want convert one-by-one with means of make
    images.stamp: $(wildcard *.png)
        touch images.stamp
    
    %.gif: %.png
        convert_one --from=$^ --to=$@
    
    # HTML would look like
    %.html:
         ./generate-images.py > $@
         make images.stamp
    

    因此,当您调用make all 时,它会生成 html 并转换新生成的图像。请注意,它只会转换已更新的图像,这正是您想要的。


    感谢 Beta 指出 gif/png 扩展的混乱。

    【讨论】:

    • 这就是我的帖子的目的。
    • +1 用于清楚地解释通配符问题,-1 用于过度复杂和错误的规则(即使在编辑之后),+1 用于令人惊讶的新见解:如果没有递归,你真的无法做到这一点!
    • @Beta:我真的很想知道我的规则中有哪些错误!请给个提示——我会编辑我的答案并给你正确的归属。顺便说一句,实际上,您可以在没有递归的情况下做到这一点 :-) 这就是为什么我从我的帖子中删除了该声明 :-) 但这会使我的帖子更加复杂......
    • 您的 %.png:%.gif 规则应该是相反的,并且您的 images.stamp 规则将没有 preqs(并且不制作 gif),直到有人以另一种方式制作 gif。现在你怎么能在没有递归的情况下做到这一点(并且没有,例如,放入一个巨大的 Perl 脚本,它基本上是一个精简的 make 实现)?如果有办法,那你已经连续两次让我吃惊了!
    • @Beta:我们可以使用重新加载 makefile 的能力来代替递归。如果我们写目标Makefile: htmls // touch Makefile,处理htmls后make会重新读取makefile,因为它已经更新了。然后它还会重新扩展我们的通配符。
    【解决方案2】:

    这听起来像是在处理Makefile 时评估所有$() 表达式,而不是在执行每个规则时。您可以像这样向您的 makefile 添加规则:

    images: $(patsubst %.png,%.gif,$(wildcard *.png))
    .PHONY: images
    

    然后将您的示例 sn-p 更改为

    %.html:
        ./generate-images.py > $@
        make images
    

    以便 Make 在正确的时间评估 glob。这是值得查看手册的内容。

    【讨论】:

      猜你喜欢
      • 2011-01-29
      • 1970-01-01
      • 2021-12-04
      • 2020-06-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 2019-05-07
      相关资源
      最近更新 更多