4

我有一个生成文件规则来生成 antlr 解析器的输出文件:

XLexer.c XLexer.h XParser.c XParser.h X.tokens: X.g
    $(ANTLR) $(ANTLRFLAGS) X.g

正如预期的那样,当 Xg 更改时,这可以正常工作并重建所有生成的文件。但是当我使用 -j 标志运行并行 make 时,上述规则对每个文件运行一次,因此在这种情况下,antlr 调用并行运行 5 次。

有没有办法执行这种类型的规则但只运行一次命令?我知道 .NOPARALLEL: 规则,但这违背了目的。如果一个已经在运行但没有成功,我试图使用一个锁定文件来导致多个运行退出。

4

2 回答 2

4

除非所有的输出文件共享一个共同的词干(例如,“XLexer.c”和“XLexer.h”都有词干“XLexer”),否则在GNU make 中没有干净的方法可以做到这一点。有多种解决方法,例如使用哨兵文件:

XLexer.c XLexer.h XParser.c XParser.h X.tokens: dummy
    @

dummy: X.g
    $(ANTLR) $(ANTLRFLAGS) X.g && touch dummy

在 CMCrossroads 的 Mr. Make 专栏上的GNU Make 中的多输出规则一文中对选项进行了详尽的描述。

(“@”行是一个“no-op”命令,但它很重要:没有它,GNU make 会假设XLexer.c和朋友永远不会通过增量重建来更新,所以你必须运行 make 两次才能对 Xg 进行任何更改生效)

或者,您可以使用更智能的 make 版本,例如ElectricAccelerator,它会自动为您解决这个问题(免责声明:我是 ElectricAccelerator 的架构师)。

于 2012-04-26T16:59:22.773 回答
0

模式规则的行为与普通规则不同;手册说:

模式规则可能有多个目标。与普通规则不同,这不会像许多具有相同先决条件和配方的不同规则一样起作用。如果模式规则有多个目标,make则知道规则的配方负责生成所有目标。该配方仅执行一次以生成所有目标。

这将适用于您的情况,因为您有一个共同的词干 ( X):

all: XLexer.c XLexer.h XParser.c XParser.h X.tokens
# (or more realistically, several targets that depend on the above)

%Lexer.c %Lexer.h %Parser.c %Parser.h %.tokens: %.g
    $(ANTLR) $(ANTLRFLAGS) $<
于 2017-01-20T16:11:15.350 回答