GNU make 将按什么顺序满足先决条件?

发布于 2024-08-09 04:50:37 字数 309 浏览 4 评论 0 原文

假设我们有规则:

a: b c d e

并且 bcde 彼此独立。

bcde 的生成顺序是否已定义?看起来一般会按照bcde的顺序制作,但有时可能会这样发生这种情况,顺序会有所不同吗?

Assuming we have the rule:

a: b c d e

and b, c, d and e are independent of each other.

Is the order of making b, c, d, e defined? It seems that generally they will be made in order b, c, d, e, but may it sometimes happen, that the order will be different?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

梦醒灬来后我 2024-08-16 04:50:37

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

No, the order is not defined. That is the whole point in using declarative dependency-oriented programming: that the computer can pick the optimal evaluation order, or in fact, evaluate them even at the same time.

掀纱窥君容 2024-08-16 04:50:37

GNU make 将按什么顺序满足先决条件?

这取决于先决条件的类型。根据 GNU Make 手册,第 4.2 节:

实际上有两种不同类型的先决条件
GNU make:正常先决条件如前面所述
部分,以及仅订购的先决条件。一个正常的先决条件是两个
声明:首先,它规定了食谱的顺序
调用:目标的所有先决条件的配方将是
在目标的配方运行之前完成。其次,它强加
依赖关系:如果任何先决条件比
目标,则该目标被认为是过时的,必须重建。

通常,这正是您想要的:如果目标的先决条件是
更新了,那么目标也应该更新。

但是,有时您会遇到这样的情况:您想要强加一个
调用规则的特定顺序不强制
如果执行这些规则之一,则更新目标。在那种情况下,
您想要定义仅限订单先决条件。仅限订单
可以通过在中放置管道符号 (|) 来指定先决条件
先决条件列表:管道符号左侧的任何先决条件
是正常的;右侧的任何先决条件均仅限订购:

 目标:正常先决条件 |仅订购先决条件

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

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

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

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

全部:$(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
    mkdir $(OBJDIR)

现在,如果需要,将运行创建“objdir”目录的规则,
在构建任何“.o”之前,但不会构建“.o”,因为
“objdir”目录时间戳已更改。

In what order prerequisites will be made by the GNU make?

It depends on the type of the prerequisite. According tho the GNU Make Manual, Section 4.2:

There are actually two different types of prerequisites understood by
GNU make: normal prerequisites such as described in the previous
section, and order-only prerequisites. A normal prerequisite makes two
statements: first, it imposes an order in which recipes will be
invoked: the recipes for all prerequisites of a target will be
completed before the recipe for the target is run. Second, it imposes
a dependency relationship: if any prerequisite is newer than the
target, then the target is considered out-of-date and must be rebuilt.

Normally, this is exactly what you want: if a target’s prerequisite is
updated, then the target should also be updated.

Occasionally, however, you have a situation where you want to impose a
specific ordering on the rules to be invoked without forcing the
target to be updated if one of those rules is executed. In that case,
you want to define order-only prerequisites. Order-only
prerequisites can be specified by placing a pipe symbol (|) in the
prerequisites list: any prerequisites to the left of the pipe symbol
are normal; any prerequisites to the right are order-only:

   targets: normal-prerequisites | order-only-prerequisites

The normal prerequisites section may of course be empty. Also, you may
still declare multiple lines of prerequisites for the same target:
they are appended appropriately (normal prerequisites are appended to
the list of normal prerequisites; order-only prerequisites are
appended to the list of order-only prerequisites). Note that if you
declare the same file to be both a normal and an order-only
prerequisite, the normal prerequisite takes precedence (since they
have a strict superset of the behavior of an order-only prerequisite).

Consider an example where your targets are to be placed in a separate
directory, and that directory might not exist before make is run. In
this situation, you want the directory to be created before any
targets are placed into it but, because the timestamps on directories
change whenever a file is added, removed, or renamed, we certainly
don’t want to rebuild all the targets whenever the directory’s
timestamp changes. One way to manage this is with order-only
prerequisites: make the directory an order-only prerequisite on all
the targets:

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

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

all: $(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
    mkdir $(OBJDIR)

Now the rule to create the ‘objdir’ directory will be run, if needed,
before any ‘.o’ is built, but no ‘.o’ will be built because the
‘objdir’ directory timestamp changed.

甜宝宝 2024-08-16 04:50:37

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

只要遵守依赖关系,所有 make 程序都可以自由选择它们喜欢的顺序。如果您的示例中还有其他规则,例如 c: b,则 c 将在 b 之前制定(但事实并非如此) ,正如您所指出的)。

如果您需要依赖特定的命令,则需要更多规则来执行它。否则 make 可以做它想做的事。 GNU Make 的文档仅说明如何规则 的处理顺序,而不是规则内依赖项的处理顺序。最合乎逻辑的顺序(无论如何对我来说)是它们列出的顺序,但这并不能保证。

In the right order, based on the rules you provide. For your particular example, that could mean any one of a number of different (4! = 24, from memory) orders.

All make programs are free to choose the order they like as long as the dependencies are honored. If there were other rules in your example, say c: b, then c would be made before b (but that isn't the case, as you point out).

If you need to rely on a specific order, you'll need more rules to enforce it. Otherwise make can do what it pleases. The documentation for GNU Make only states how rules are processed, not the order in which dependencies within a rule are processed. The most logical order (to me, anyway) would be the order in which they're listed but that's not guaranteed.

靑春怀旧 2024-08-16 04:50:37

当然,如果我使用 make -j a,它们可能会同时构建(取决于是否 bc de 依次具有其他/相互关联的依赖关系)。

Sure, if I use make -j a, they might all get built at the same time (depending on whether b, c, d, or e in turn have other/interrelated dependencies).

花桑 2024-08-16 04:50:37

不,当没有依赖关系时,您不能依赖顺序。

  • make 需要做拓扑排序,因为依赖关系可能有额外的和多重的关系。 make 所做的排序可能相当复杂,因为图中的节点可能在不同级别上多次相关,
  • 而一般排序算法并不自然 稳定,即使对于简单的基于键的排序

No, you can't count on the ordering when there are no dependency relationships.

  • make needs to do a topological sort, because dependencies may have additional and multiple relationships. The sort that make does is potentially quite complex, as nodes in the graph may be related multiple times at different levels
  • in general sorting algorithms are not naturally stable, even for simple key-based sorts
半城柳色半声笛 2024-08-16 04:50:37

我将添加此内容以供将来参考。虽然 GNU Make 在处理先决条件时可能没有定义特定的顺序,但 POSIX make 要求按照指定的顺序处理它们,即从左到右。大多数实现都遵循此规则。 POSIX 甚至给出了一个示例,其中不遵循此规则的 make 实现可能会破坏程序的构建过程:

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 一起使用的方式重写,但我想我应该分享这个关于先决条件排序的花絮。

I'll just add this for future reference. While GNU Make may not define a specific order when it comes to processing prerequisites, POSIX make requires that they be handled in the order they've been specified, namely left-to-right. Most implementations follow this rule. POSIX even gives an example where a make implementation not following this rule could break the build process of a program:

foo: y.tab.o lex.o main.o
    $(CC) $(CFLAGS) -o $@ t.tab.o lex.o main.o

where lex.o ends up using an incorrect y.tab.h. While this can be rewritten in a way that works with GNU Make, I thought I'd share this tidbit about prerequisite ordering.

南渊 2024-08-16 04:50:37

如果顺序很重要,您可以使用 递归 make 有选择地强制执行它。例如,假设您不关心 b 和 c 的生成顺序,只要它们都在 d 之前生成,并且 d 在 e 之前生成即可。然后你可以将你的规则写为:

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

请注意,根据 d 和 e 的复杂性,这种方法可能会对你的构建时间产生负面影响:请参阅 递归使人认为有害 (PDF) 反对这样做的论点。

If order matters, you can selectively enforce it using recursive make. For example, suppose you don't care what order b and c are made in, as long as they're both made before d and d is made before e. Then you could write your rule as:

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

Be aware that depending on the complexity of d and e, this approach may do Bad Things to your build times: see Recursive Make Considered Harmful (PDF) for arguments against doing it this way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文