Dependencies GNU制造的先决条件将按什么顺序制造?

Dependencies GNU制造的先决条件将按什么顺序制造?,dependencies,makefile,gnu,Dependencies,Makefile,Gnu,假设我们有规则: a: b c d e 和b,c,d和e是相互独立的 制定b、c、d、e的顺序是否已定义?一般来说,它们的顺序是b,c,d,e,但有时可能会出现顺序不同的情况吗?当然,如果我使用make-ja,它们可能会同时生成(取决于b、c、d或e是否依次具有其他/相关的依赖项)。根据您提供的规则,顺序正确。对于您的特定示例,这可能意味着许多不同(4!=24,来自内存)顺序中的任何一个 所有make程序都可以自由选择它们喜欢的顺序,只要依赖关系得到尊重。如果在您的示例中有其他规则,比如c:b

假设我们有规则:

a: b c d e
b
c
d
e
是相互独立的


制定
b
c
d
e
的顺序是否已定义?一般来说,它们的顺序是
b
c
d
e
,但有时可能会出现顺序不同的情况吗?

当然,如果我使用
make-ja
,它们可能会同时生成(取决于
b
c
d
e
是否依次具有其他/相关的依赖项)。

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

所有
make
程序都可以自由选择它们喜欢的顺序,只要依赖关系得到尊重。如果在您的示例中有其他规则,比如
c:b
,那么
c
将在
b
之前生成(但您指出的情况并非如此)


如果您需要依赖特定的顺序,则需要更多的规则来强制执行。否则,
make
可以随心所欲。for GNU make只说明如何处理规则,而不是规则中依赖项的处理顺序。最符合逻辑的顺序(对我来说,无论如何)将是它们列出的顺序,但这不能保证。

不,顺序没有定义。这就是使用面向声明依赖性编程的要点:计算机可以选择最佳的求值顺序,或者实际上,甚至在同一时间对它们求值。

不,当存在n时,您不能指望排序o依赖关系

  • make需要这样做,因为依赖关系可能有额外的和多个关系。make所做的排序可能相当复杂,因为图中的节点可能在不同级别上多次相关
  • 一般来说,排序算法并不自然,即使对于简单的基于键的排序也是如此
GNU制造的先决条件将按什么顺序制造

这取决于先决条件的类型。根据第4.2节:

实际上有两种不同类型的先决条件 GNU make:正常的先决条件,如前一节所述 一个普通的先决条件是两个 声明:首先,它规定了食谱的顺序 调用:将调用目标的所有先决条件的配方 在运行目标配方之前完成。第二,它强制 依赖关系:如果任何先决条件比 目标,则该目标被认为已过时,必须重新生成

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

然而,有时候,您会遇到想要强制执行 在不强制 如果执行其中一个规则,则要更新的目标。在这种情况下, 您想定义仅限订单的先决条件。仅限订单 先决条件可以通过在中放置管道符号(|)来指定 先决条件列表:管道符号左侧的所有先决条件 正常;右侧的任何先决条件仅适用于订单:

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

考虑一个例子,将目标放在一个单独的位置 目录,并且在运行
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)
OBJDIR:=OBJDIR
OBJS:=$(addprefix$(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o:%.c
$(COMPILE.c)$(输出选项)$<
全部:$(OBJS)
$(OBJS):|$(OBJDIR)
$(OBJDIR):
mkdir$(OBJDIR)
现在,如果需要,将运行创建“objdir”目录的规则, 在生成任何“.o”之前,但不会生成“.o”,因为 “objdir”目录时间戳已更改


如果顺序很重要,您可以使用有选择地强制执行。例如,假设您不关心b和c的顺序,只要它们都是在d之前生成的,d是在e之前生成的。那么您可以将规则编写为:

a: b c
    $(MAKE) d
    $(MAKE) e
    # Additional steps to make a

请注意,根据d和e的复杂性,这种方法可能会影响构建时间:请参阅(PDF)对于反对这样做的论点。

我将添加这一点以供将来参考。虽然GNU Make在处理先决条件时可能没有定义特定的顺序,但POSIX Make要求按照指定的顺序处理先决条件,即从左到右。大多数实现都遵循这一规则。POSIX甚至给出了一个例子,说明不遵循此规则的重新生成实现可能会中断程序的生成过程:

foo: y.tab.o lex.o main.o
    $(CC) $(CFLAGS) -o $@ t.tab.o lex.o main.o
lex.o最终使用了一个不正确的y.tab.h。虽然这可以用GNU Make的方式重写,但我想我应该和大家分享一下关于prerequisit的一些小贴士