【问题标题】:Makefile: order of dependency evaluationMakefile:依赖评估的顺序
【发布时间】:2011-01-23 06:58:10
【问题描述】:

假设一个目标foo.tar,这取决于文件列表foo.files,例如

FOO_FILES := $(shell cat foo.files)

foo.tar: foo.files $(FOO_FILES)
    tar -cf foo $(FOO_FILES)

现在假设需要生成 foo.files 例如:

foo.files: foo.files.template
    sed -e "s/@{VERSION}/$(VERSION)/" < $< > $@

很明显foo.files 依赖于foo.files.template,但是如何确保在生成 foo.files 之后评估 FOO_FILES?

【问题讨论】:

    标签: makefile dependencies gnu-make file-generation


    【解决方案1】:

    你原来的规则是正确的。因为更新 foo.files 会导致 FOO_FILES 的值过时,所以您只需要确保当 foo.files 通过使您的 Makefile 依赖于 foo.files 来更新时,您的 Makefile 由 gnu make 重新评估:

    Makefile : foo.files
    

    【讨论】:

    • 是的。简单优雅(尽可能用make)。
    【解决方案2】:

    所以,我在 mad-scientist.net 上找到了关于 Advanced Auto-Dependency Generation 的答案。基本上,可以通过 GNU/Make 功能重新评估 makefile。当有规则生成包含的makefile时,整个makefile会在包含文件生成后被重新读取。因此——

    # -*- mode: make -*-
    VERSION := 1.2.3
    
    foo.tar: foo.files $(FOO_FILES)
        tar cf $@ $(FOO_FILES)
    
    clean:
        rm -f foo.files foo_files.mk foo.tar
    
    foo.files: foo.files.template
        sed -e "s/@{VERSION}/$(VERSION)/" < $< > $@
    
    # -- voodoo start here --
    # This will ensure that FOO_FILES will be evaluated only
    # *after* foo.files is generated.
    foo_files.mk: foo.files
        echo "FOO_FILES := `xargs < $<`" > $@
    
    include foo_files.mk
    # -- voodoo ends here --
    
    .PHONY: clean
    

    -- 似乎做对了。


    ...只是为了完整性:

    foo.files.template 是:

    a-$(VERSION)
    b-$(VERSION)
    

    并假设存在a-1.2.3b-1.2.3

    【讨论】:

      【解决方案3】:

      不能一次性完成; Make 确定在实际执行任何规则之前必须重建哪些目标,在这种情况下,目标的完整列表在其中一个规则执行之前不存在。

      应该这样做:

      FOO_FILES := $(shell cat foo.files)
      
      foo.tar: foo.files
          $(MAKE) foo-tarball
      
      .PHONY: foo-tarball
      foo-tarball: $(FOO_FILES)
          tar -cf foo $^
      

      编辑:
      正如 OP 指出的那样,这不会像书面的那样工作;我遗漏了一个先决条件:

      foo.tar: foo.files $(FOO_FILES)
          ...
      

      请注意,即使foo.files 没有更改,这也会递归,这不是绝对必要的;可以纠正这一点,但不能优雅地纠正。 (作为比较,我承认选择的解决方案比我的更干净,即使目标与 foo.tar 无关,也会递归。)

      【讨论】:

      • 这看起来不对。它只会因为 foo-tarball 是 .PHONY 而起作用,但在这种情况下,为什么还要打扰所有其他规则呢?此外,foo.tar 规则根本不正确(foo.files 中列出的文件之一可能会在foo.files 保持不变时发生变化)。雪上加霜的是这个 Makefile 是递归的(这被认为是有害的)。
      • @Chen Levy:你说得对,规则不对,我已经修正了。在我的辩护中,1)其他规则是必要的,2)Maxim Yegarushkin 的解决方案也是递归的,只是以一种不那么明显的方式。 (我通常建议人们对递归 make 做出自己的决定——有时它是必要的,就像在这种情况下一样,而且我认为更多的人参考“被认为是有害的”论文而不是实际阅读它。)
      猜你喜欢
      • 1970-01-01
      • 2012-02-10
      • 2013-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      相关资源
      最近更新 更多