【问题标题】:Wildcard expansion in makefile targetsmakefile 目标中的通配符扩展
【发布时间】:2014-10-27 04:47:27
【问题描述】:

假设我有一组源文件:

src/foo/file.abc
src/foo/otherfile.abc

我想做一些操作(为了简单起见,我们只说复制)导致目标文件位于几个不同的地方:

dest/bar/file.xyz
dest/bar/otherfile.xyz
dest/baz/file.xyz
dest/baz/otherfile.xyz
dest/something/file.xyz
dest/something/otherfile.xyz

如何在 Makefile 中表达这种依赖关系,以便更新必备文件导致配方重新创建目标?

GNU Make manual 表示“通配符扩展由 make 在目标和先决条件中自动执行”。顺其自然,我会期待

dest/*/%.xyz : src/foo/%.abc
    install -d $< $@

工作,但失败:

$ make -f test.mk dest/bar/file.xyz
make: *** No rule to make target `dest/bar/file.xyz'.  Stop.

我是否误解了目标中的通配符扩展?有没有更好的方法来实现我的目标?

环境: GNU Make 3.82.90
32 位 Cygwin

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    目前还不完全清楚你在追求什么。这个怎么样:

    dest/%.xyz:
        cp src/foo/$(notdir $*).abc $@
    

    现在make -f test.mk dest/bar/file.xyz 会将src/foo/file.abc 复制到dest/bar/file.xyz。这就是您想要它做的所有事情,还是您希望它也将文件复制到其他目的地,或者在同一操作中复制其他文件,还是什么?

    【讨论】:

    • 这行得通,只是它是我真正关心的依赖项检查。如果src/foo/file.abc被更新,那么所有的dest/*/file.xyz都需要重新创建。
    【解决方案2】:

    执行通配符扩展,根据 shell。如果您没有任何目标文件开始,则扩展将一事无成。 Make 无法神奇地找出你想要的目标文件。

    所以,你需要声明你想要的目标文件,然后像这样继续:

    DEST_FILES := \
        dest/bar/file.xyz \
        dest/bar/otherfile.xyz \
        dest/baz/file.xyz \
        dest/baz/otherfile.xyz \
        dest/something/file.xyz \
        dest/something/otherfile.xyz \
    
    .PHONY: all
    all: $(DEST_FILES)
    
    .SECONDEXPANSION:
    
    $(DEST_FILES): %xyz: src/foo/$$(notdir $$*)abc Makefile
        cp $< $@
    

    【讨论】:

      【解决方案3】:

      我找到了一个依赖于 GNU 扩展 .SECONDEXPANSION 的解决方案,虽然并不理想,但总比没有好:

      .SECONDEXPANSION:
      dest/%.xyz : src/foo/$$(@F)
          install -D $< $@
      

      【讨论】:

        猜你喜欢
        • 2010-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多