我遇到了仅限订单的先决条件问题。这些根本不会首先执行。我是否误解了仅限订单的先决条件的工作方式?
以下制作剧本:
.PHONY: mefirst mefirst2
mefirst:
@echo "I'm first!"
mefirst2:
@echo "I'm first too!"
normaltarget: normaltarget2 | mefirst2
@echo "normaltarget done"
normaltarget2: a b c
@echo "normaltarget2 done"
helloworld: normaltarget | mefirst
@echo "helloworld done"
.DEFAULT_GOAL := go
go: helloworld
@echo "go done"
a:
@echo a
b:
@echo b
c:
@echo c
...打印出以下内容:
a
b
c
normaltarget2 done
I'm first too!
normaltarget done
I'm first!
helloworld done
go done
...而不是我期望的那样:
I'm first!
I'm first too!
a
b
c
normaltarget2 done
normaltarget done
helloworld done
go done
我做错了什么?
答案 0 :(得分:39)
我是否误解了仅限订单的先决条件的工作方式?
是的,这就是它的样子。
名称“仅限订单”有些令人困惑。 |
背后的先决条件被称为“仅订单先决条件”,不是因为它们更改了单个目标的先决条件列表中的配方执行顺序,而是因为它们的唯一目的是在其他目标之前创建某些目标,像一个引导程序。正如下面的用户bobbogo准确解释的那样( - 感谢纠正):如果make
决定重建目标的先决条件,它将运行该先决条件的配方。现在,对于普通的先决条件,此更新意味着目标现在已过时,make
将必须运行目标的配方。另一方面,对于仅订购的先决条件,make
不会将目标标记为需要更新。
例如,请参阅Types of Prerequisites部分,了解在创建该目录中的对象之前应创建目录的用例。
举个例子makefile
:
a: b
touch a
b: c
touch b
c:
touch c
x: | y
touch x
y: | z
touch y
z:
touch z
如您所见,b
和c
是a
和b
的正常先决条件,而y
和z
是有序的 - 只有x
和y
的先决条件。从干净的石板开始,它们看起来一样:
:~$ make a
touch c
touch b
touch a
:~$ make x
touch z
touch y
touch x
:~$ make a
make: `a' is up to date.
:~$ make x
make: `x' is up to date.
但是,如果我们现在手动“更新”链末尾的先决条件(c
和z
),我们会看到差异:
:~$ touch c
:~$ make a
touch b
touch a
:~$ touch z
:~$ make x
make: `x' is up to date.
这显示了存在的仅限订单的先决条件如何不会使任何目标无效,而与其时间戳无关。删除仅订单目标确实会导致重建(但只重建该丢失的文件):
:~$ rm c
:~$ make a
touch c
touch b
touch a
:~$ rm z
:~$ make x
touch z
说到这里,更改配方运行顺序的正确方法是纠正目标之间的依赖关系。例如,如果您希望在mefirst
之前构建a
,那么您需要将mefirst
作为a
的先决条件,例如
a: mefirst
@echo a
由于您没有详细描述您希望食谱运行的顺序,因此无法为您的问题提供整个解决方案。
你的答案有一个捷径,不是解决方案,但仍然很有趣。虽然没有记录,但似乎单个目标的先决条件按它们出现的顺序进行处理。 |
符号不会改变这一点。在您的简单情况下,您可以利用它来实现您正在寻找的输出:
normaltarget: mefirst2 normaltarget2
@echo "normaltarget done"
和
helloworld: mefirst normaltarget
@echo "helloworld done"
但是,正如您自己所指出的,只要-j
标志用于并行运行配方,这个“解决方案”就会中断。另外,正如用户bobbogo指出的那样,依赖这种排序机制是不好的做法。引入新的依赖项可能会干扰排序。所以不要这样做: - )