Build 为Antlr解析器生成文件多次并行GNU Make运行命令

Build 为Antlr解析器生成文件多次并行GNU Make运行命令,build,makefile,parallel-processing,antlr,gnu,Build,Makefile,Parallel Processing,Antlr,Gnu,我有一个makefile规则来生成antlr解析器的输出文件: XLexer.c XLexer.h XParser.c XParser.h X.tokens: X.g $(ANTLR) $(ANTLRFLAGS) X.g 如预期的那样,当X.g发生更改时,这会正常工作并重建所有生成的文件。但是当我使用-j标志运行parallel make时,上面的规则对每个文件运行一次,因此在本例中,antlr调用并行运行5次 有没有办法执行这种类型的规则,但只运行一次命令?我知道这个规则。不平行:但

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

XLexer.c XLexer.h XParser.c XParser.h X.tokens: X.g
    $(ANTLR) $(ANTLRFLAGS) X.g
如预期的那样,当X.g发生更改时,这会正常工作并重建所有生成的文件。但是当我使用-j标志运行parallel make时,上面的规则对每个文件运行一次,因此在本例中,antlr调用并行运行5次


有没有办法执行这种类型的规则,但只运行一次命令?我知道这个规则。不平行:但那违背了目的。我试图使用一个锁定文件,在一个运行中退出多个运行,但没有成功。

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

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

dummy: X.g
    $(ANTLR) $(ANTLRFLAGS) X.g && touch dummy
在CMCrossroads的Mr.Make专栏上,有一篇关于选项的全面报道

(“@”行是一个“no op”命令,但它很重要:如果没有它,GNU make将假定
XLexer.c
和friends永远不会通过增量重建进行更新,因此您必须运行make两次才能使X.g中的任何更改生效)


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

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

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

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

all:XLexer.cxlexer.hxparser.cxparser.hx.tokens
#(或者更现实地说,取决于上述因素的几个目标)
%Lexer.c%Lexer.h%Parser.c%Parser.h%。令牌:%.g
$(ANTLR)$(ANTLR标志)$<

有什么原因使具有多个目标的模式规则不适用于此吗?@rakslice:只有当所有输出目标都有一个公共干时,模式规则才有效。在本例中,您可能可以通过将X作为词干来尝试,如
%Lexer.c%Lexer.h%Parser.c%Parser.h%.标记:%.g
。这有点不寻常,但取决于您的环境,这可能是可以接受的。在触摸虚拟文件之前,两个或多个make作业是否可能同时进入虚拟规则?对不起,如果这是一个愚蠢的问题。我是一个制造者noob@mercurytw:否,只有一个虚拟规则实例。
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) $<