当中间文件没有真正改变时,Makefile改进

时间:2015-07-02 09:01:39

标签: makefile

我有像这样的Makefile

all: *.foo
    ./finalstep *.foo > $@

%.foo: %.bar
    ./secondstep < $< > $@

%.bar: %.baz
    ./firststep < $< > $@

事情是,.baz文件中的经常更改是次要的,因为更改后生成的.bar文件是相同的(内容方面,或者如同diff)一样,在变化之前。 由于secondstepfinalstep(以及可能更多的中间步骤)昂贵,如果可以检测到.bar文件中缺少更改并且因此,secondstep(甚至可能finalstep)的调用得以幸免。有没有办法实现这个目标?

我尝试做这样的事情如下:

%.bar: %.baz
    touch $@; cp $@ $@.backup; ./firststep < $< > $@

%.foo: %.bar
    diff -q $< $<.backup || ./secondstep < $< > $@

但这有很多缺点(如果用参数调用make,则无法正常工作)。 有没有更好的方法?基本上,make应考虑.bar个文件的两个不同文件时间:每次运行firststep时都会更新一个文件,并用于确定.bar本身是否需要重新制作。另一个仅在firststep运行导致文件的内容净更改时更新,并用于确定需要重新生成.foo ...

1 个答案:

答案 0 :(得分:0)

我认为您应该尝试使用类似(未经测试)的

all: %.foo
    ./finalstep %.foo > $@

%.foo: %.bar
    @if [[ -f $< && -f $<.backup ]]; then   \
        if diff -q $< $<.backup; then       \
            echo "IDENTICAL => do nothing"; \
        else                                \
            echo "DIFFERENT => proceed";    \
            ./secondstep < $< > $@;         \
        fi;                                 \
    else                                    \
        echo "NOT FOUND => proceed";        \
        ./secondstep < $< > $@;             \
    fi;                                     \
    cp $< $<.backup

%.bar: %.baz
    ./firststep < $< > $@;

基本上,大配方的目的是处理$<$<.backup的所有相关组合(在相同的子shell中!):

  • 两个文件存在并且相等(diff返回0=>什么都不做
  • 两个文件都存在且不同(diff返回1=>执行
  • 其中一个文件=>执行

无论上述选择是什么,最后都要backup