makefile中处理组件的顺序

makefile中处理组件的顺序,makefile,gnu-make,Makefile,Gnu Make,在makefile中,依赖项行的形式如下- abc: x y z 所有三个组件(x、y、z)本身都是makefile中更下面的依赖关系行中的目标 如果调用make abc,将以什么顺序执行三个目标x、y、z?默认情况下,执行顺序与先决条件列表中指定的顺序相同,除非这些先决条件之间定义了任何依赖关系 abc: x y z 顺序是xyz abc: x y z y : z 顺序是xzy 但理想情况下,您应该设计makefile,使其不依赖于先决条件的指定顺序。也就是说,如果y应该在z之后执行,那

在makefile中,依赖项行的形式如下-

abc: x y z
所有三个组件(x、y、z)本身都是makefile中更下面的依赖关系行中的目标


如果调用make abc,将以什么顺序执行三个目标x、y、z?

默认情况下,执行顺序与先决条件列表中指定的顺序相同,除非这些先决条件之间定义了任何依赖关系

abc: x y z
顺序是
xyz

abc: x y z
y : z
顺序是
xzy

但理想情况下,您应该设计makefile,使其不依赖于先决条件的指定顺序。也就是说,如果
y
应该在
z
之后执行,那么必须有
y:z
依赖关系


请记住,GNU Make可以并行执行某些配方,请参见。

您真的不应该依赖于它们的执行顺序-在所有其他条件相同的情况下,这些先决条件的所有三个配方都可以并行运行

唯一的硬规则是在运行目标配方之前必须满足所有先决条件

如果
x
y
z
之间没有依赖关系,并且没有并行执行,GNU make将按照您指定的顺序运行它们,但文档中不保证这一点

POSIX的描述包括一个基本原理,其中说明:

大多数历史实现中的
make
实用程序按从左到右的顺序处理目标的先决条件,makefile格式需要这样做。它支持许多生成
yacc
程序的makefile中使用的标准习惯用法;例如:

foo: y.tab.o lex.o main.o
     $(CC) $(CFLAGS) -o $@ t.tab.o lex.o main.o
在本例中,如果
make
选择了任意顺序,则
lex.o
可能无法使用正确的
y.tab.h
生成。虽然可能有更好的方式来表达这种关系,但它在历史上被广泛使用。如前所述,希望并行更新先决条件的实现应该需要对
make
进行显式扩展或使用makefile格式来完成

(我相信
$(CC)
行中的
t.tab.o
y.tab.o
的打字错误,但这就是基本原理实际所说的。)

因此,观察到的先决条件从左到右处理的行为在这里得到了验证,尽管它仅在基本原理部分,而不在主要描述中。基本原理还提到了平行
制造
等问题。

从中,您可以添加管道符号:

abc: | x y z
从make手册: 通过在“先决条件”列表中放置管道符号(|),可以指定“仅订购”先决条件:管道符号左侧的任何先决条件都是正常的;右侧的任何先决条件仅适用于以下顺序:

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


简短明了的回答。我现在不能
+1
,但我尽量不要忘记明天回来投票。另一种说法是:每当有订单依赖项时,将其明确表示为Makefile规则。“recipe”是用于表示依赖项行下的命令列表的术语?是的,这是一个术语(无论如何在GNU make文档中).@Shailesh,不客气。我添加了和UPD。发布主要答案后的第节。@EldarAbusalimov:不需要,有修订历史记录。只需将答案写成一篇连贯的散文。POSIX描述可能重复+1,以及关于并行
make
作业的重要警告。在国际海事组织,选择不允许对平行作业执行任何命令是一个错误。e、 g.我很高兴我的
.o
对象可以以任何顺序编译,但我需要在编译和链接之前和之后分别发生一系列其他事情,这比它应该发生的困难得多……我要指出的是,GNU make与POSIX make的差异非常大,并且,
.POSIX
特殊目标应该包含在makefile中,以表明它应该以兼容的方式运行。不,这不是只有顺序的先决条件所做的
foo:| bar baz
不强制执行
bar baz
,不强制执行管道字符。相反,管道粗略地说,“在订购foo、bar和baz时,bar和baz必须在foo之前,但对bar和baz的更新不足以导致foo被视为更新并需要运行”。文档处于且不是最清晰的。@PhilP我不是母语人士,但我建议您的意思是“考虑过时”(因此需要运行),不是吗?我无法对其进行编辑以修复,但您是对的。我想我重写了好几次,但还是丢失了一些东西。“被认为需要更新”也适用。非常感谢。