GNU make将以什么顺序进行先决条件?

pep*_*er0 26 dependencies gnu makefile

假设我们有规则:

a: b c d e
Run Code Online (Sandbox Code Playgroud)

b,c,de相互独立的.

是作出该命令b,c,d,e界定?看来,他们一般会在顺序进行b,c,d,e,但可能它有时会发生,该命令会有所不同?

Jör*_*tag 25

不,订单没有定义.这是使用声明性依赖性编程的全部要点:计算机可以选择最佳评估顺序,或者实际上,甚至可以同时评估它们.


jww*_*jww 13

GNU make将以什么顺序进行先决条件?

这取决于先决条件的类型.根据GNU Make Manual,第4.2节:

实际上,GNU make理解了两种不同类型的先决条件:正常的先决条件,如上一节中所述,以及仅限订单的先决条件.正常的先决条件产生两个语句:首先,它强加了一个调用配方的顺序:目标的所有先决条件的配方将在目标的配方运行之前完成.其次,它强加了依赖关系:如果任何先决条件比目标更新,那么目标被认为是过时的,必须重建.

通常,这正是您想要的:如果更新目标的先决条件,则还应更新目标.

但是,有时您可能希望对要调用的规则强制执行特定排序,而不强制在执行其中一个规则时更新目标.在这种情况下,您希望定义仅订单的先决条件.可以通过在先决条件列表中放置管道符号(|)来指定仅订单的先决条件:管道符号左侧的任何先决条件都是正常的; 右边的任何先决条件都是仅限订单:

   targets: normal-prerequisites | order-only-prerequisites
Run Code Online (Sandbox Code Playgroud)

正常的先决条件部分当然可能是空的.此外,您仍然可以为同一目标声明多行先决条件:它们被适当地附加(正常先决条件附加到正常先决条件列表;仅订单先决条件附加到仅订单先决条件列表).请注意,如果将同一文件声明为普通文件和仅限订单的先决条件,则通常的先决条件优先(因为它们具有仅限订单先决条件的行为的严格超集).

考虑一个示例,其中您的目标将放置在单独的目录中,并且该目录在make运行之前可能不存在.在这种情况下,您希望在将任何目标放入其中之前创建目录,但是,因为无论何时添加,删除或重命名文件时目录上的时间戳都会更改,我们当然不希望重建所有目标.目录的时间戳更改.管理此问题的一种方法是使用仅限订单的先决条件:使目录成为所有目标的仅订单先决条件:

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)

$(OBJDIR)/%.o : %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

all: $(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
    mkdir $(OBJDIR)
Run Code Online (Sandbox Code Playgroud)

现在,在构建任何'.o'之前,如果需要,将运行创建'objdir'目录的规则,但是由于'objdir'目录时间戳已更改,因此不会构建'.o'.

  • 这并没有真正强加一个顺序,至少不是一个正常的先决条件.它只是说,对于仅订单的先决条件,gmake应该忽略时间戳.它是先决条件,因此必须在当前规则运行之前存在,但由于它是仅订单的先决条件,因此其时间戳/状态不会触发当前规则.(这不排除导致仅依赖顺序的依赖项执行其命令的其他依赖项.) (6认同)
  • 从上面的gnu make文档:`但是,有时您会想要对如何调用目标规则强制执行特定排序,而不强制执行其中一个规则时更新目标对于只有奥得河的先决条件,这似乎相当糟糕.根据我的理解,仅限订单的先决条件只是一个先决条件,如果它发生变化,它不会强制"make"重建目标. (5认同)

Car*_*rum 6

当然,如果我使用make -j a,他们可能都得到在同一时间建(取决于bcd,或者e反过来有其他/相互关联的依赖)。

  • 这并不能真正回答问题,所以我很惊讶它被接受了。 (5认同)
  • 我在这里读到的问题是:“通常看来,它们将按照顺序b,c,d,e来制造,但有时会发生,顺序会有所不同吗?”。我很确定我提供了一个反例。我想您的意见可能会有所不同。 (3认同)
  • @jww 不,仅订单先决条件不是按照特定顺序构建的,它们只是不会**“[..]在执行这些规则之一时强制更新目标[..]”**。 (3认同)

pax*_*blo 6

按照正确的顺序,根据您提供的规则.对于您的特定示例,这可能意味着许多不同的(4!= 24,来自内存)订单中的任何一个.

make只要依赖关系得到尊重,所有程序都可以自由选择他们喜欢的顺序.如果你的例子中有其他规则,比如说c: b,那么c之前就会做出来b(但事实并非如此,正如你所指出的那样).

如果您需要依赖特定订单,则需要更多规则来强制执行.否则make可以做它喜欢的事情.GNU Make 的文档仅说明如何处理规则,而不是规则中处理依赖关系的顺序.最合乎逻辑的顺序(对我来说,无论如何)将是它们被列出的顺序但是不能保证.