避免重新生成不会更改的文件

时间:2011-10-03 00:27:16

标签: makefile gnu-make

我有一个包含这种形式的几个规则的Makefile

protolist.c: $(PROTOCOLS) Makefile src/genmodtable.sh
    $(SHELL) $(srcdir)/src/genmodtable.sh \
        $@ $(filter-out %Makefile %genmodtable.sh, $^)

顾名思义,protolist.c最终包含.c$(PROTOCOLS)个文件定义的所有“协议”的列表。这个文件的内容正式依赖于$(PROTOCOLS),Makefile和生成器脚本中的所有内容,但当其中一个{{1}时,文件实际更改的情况非常少见。 }文件被编辑。因此,.c被编码为不更改genmodtable.sh的时间戳,如果它不会对其内容进行任何更改。这会导致Make在没有必要时跳过重建protolist.c及其依赖项。

一切正常; 问题就是这样,因为protolist.o现在似乎已经过时了依赖项,Make认为它必须尝试重新生成{{1}每次跑步。这不是性能问题 - 脚本速度非常快 - 但这是令人困惑的行为。我朦胧地回忆起一个涉及时间戳文件的成语,可以用来阻止Make这样做,但是我无法重建它或者在任何地方找到它。有谁知道它是什么?

(如果有人可以建议如何摆脱那个愚蠢的protolist.c构造,那将会有所帮助,因为这是这个Makefile中唯一的GNUmakeism。)

1 个答案:

答案 0 :(得分:3)

这看起来类似于Fortran编程和make的问题,涉及编译模块时生成的文件。 (不相关,除此之外,我选择了如何做到这一点。)

您想要的是将protolist.o的时间戳与protolist.c的时间戳进行比较,该时间戳保持“旧”,并决定运行protolist.c的配方,具体取决于在时间戳上,以及时间戳文件,每次运行配方时都会更新 为了使这项工作,你必须用空规则将两者联系起来。

protolist.o: protolist.c
    [...]

protolist.c: protolist.c.time ;

protolist.c.time: $(PROTOCOLS) Makefile src/genmodtable.sh
    $(SHELL) $(srcdir)/src/genmodtable.sh \
        protolist.c $(filter-out %Makefile %genmodtable.sh, $^)
    touch protolist.c.time

在我自己的makefile中,我必须声明时间戳文件作为特殊目标.PRECIOUS的先决条件,以防止make删除它们,但我正在使用模式规则;我不是百分百肯定,但我认为在使用显式规则时这不是必需的,比如这里。

要避免$(filter-out ...)构造,您是否可以简单地将其替换为$(PROTOCOLS)
(虽然,就个人而言,我会坚持Paul's First Rule of Makefiles:不要轻易编写便携式文件,而是使用便携式文件。)