我有一个包含这种形式的几个规则的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。)
答案 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:不要轻易编写便携式文件,而是使用便携式文件。)