仅订单先决条件在GNU make中无法正常工作? [英] Order-only prerequisites not working correctly in GNU make?

查看:61
本文介绍了仅订单先决条件在GNU make中无法正常工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对仅订购的先决条件有疑问.这些根本不执行.我是否误解了仅订购先决条件的工作方式?

I have a problem with order-only prerequisites. These do not execute first at all. Am I mis-understanding the way order-only prerequisites work?

以下make脚本:

.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

...打印出以下内容:

...prints out the following:

a
b
c
normaltarget2 done
I'm first too!
normaltarget done
I'm first!
helloworld done
go done

...而不是我所期望的:

...instead of what I would expect:

I'm first!
I'm first too!
a
b
c
normaltarget2 done
normaltarget done
helloworld done
go done

我在做什么错了?

推荐答案

我是否误解了仅订购先决条件的工作方式?

Am I mis-understanding the way order-only prerequisites work?

是的,就是这样.

仅订购"这个名称有些令人困惑. |后面的先决条件称为仅订购先决条件",不是因为它们会更改单个目标的先决条件列表内配方执行的顺序,而是因为它们的唯一目的是先于其他目标创建某些目标,例如引导程序.正如下面的用户bobbogo准确解释的(-感谢您的纠正):如果make决定重建目标的先决条件,它将为该先决条件运行配方.现在,对于一般的先决条件,此更新意味着目标现在已过期,并且make将必须运行目标的配方.另一方面,对于仅订购的先决条件,make不会将目标标记为需要更新.

The name "order-only" is somewhat confusing. The prerequisites behind the | are called "order-only prerequisites" not because they change the order of recipe execution inside the list of prerequisites for a single target, but because their only purpose is to have certain targets created before others, like a bootstrap. As accurately explained by user bobbogo below ( -- thanks for correcting): if make decides to rebuild a prerequisite of a target, it will run the recipe for that prerequisite. Now, for an ordinary prerequisite this update implies that the target is now out-of-date, and make will have to run the target's recipe. For an order-only prerequisite on the other hand, make does not mark the target as needing an update.

例如,请参见前提类型用于在创建目录中的对象之前应先创建目录的用例.

For example see the section Types of Prerequisites for a use case where a directory should be created before the objects in that directory are created.

以这个例子makefile:

a: b
    touch a

b: c
    touch b

c:
    touch c

x: | y 
    touch x

y: | z 
    touch y

z:
    touch z

如您所见,bcab的常规先决条件,而yzxy的仅订购先决条件.从干净的石板开始,它们看起来是一样的:

As you can see, b and c are normal prerequisites of a and b, whereas y and z are order-only prerequisites of x and y. Starting from a clean slate, they look the same:

:~$ 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.

但是,如果我们现在手动更新"链末尾的先决条件(cz),我们将看到不同之处:

However, if we now manually "update" the prerequisites at the end of the chain (c and z), we see the difference:

:~$ touch c
:~$ make a
touch b
touch a
:~$ touch z
:~$ make x
make: `x' is up to date.

这表明存在的仅订购先决条件如何使任何目标独立于其时间戳而无效.删除仅订购目标确实会导致重建(但只会重建丢失的文件):

This shows how order-only prerequisites that exist do not invalidate any targets, independent of their time-stamp. Deleting the order-only target does result in rebuilding though (but only rebuilding of that missing file):

:~$ rm c
:~$ make a
touch c
touch b
touch a
:~$ rm z
:~$ make x
touch z

话虽如此,更改配方运行顺序的正确方法是纠正目标之间的依赖性.例如,如果要在a之前构建mefirst,则需要将mefirst作为a的先决条件,如

Having that said, the correct way to change the order in which your recipes are run is by correcting the dependencies between the targets. For example, if you want mefirst to be built before a, then you need to make mefirst a prerequisite for a, as in

a: mefirst
    @echo a

由于您没有详细描述期望配方以什么顺序运行,因此无法为您的问题提供完整的解决方案.

It is not possible to give the entire solution to your question since you did not describe in detail in which order you expect recipes to run.

您的答案有一个捷径,它不是解决方案,但仍然很有趣.尽管没有记录,但似乎单个目标的先决条件按照它们出现的顺序进行处理. |符号不会改变它.在简单的情况下,您可以利用它来实现所需的输出:

There is a shortcut to your answer which is not the solution but still interesting to know. Although not documented, it seems that the prerequisites of a single target are processed in the order that they appear. The | sign does not change that. In your simple case, you can take advantage of that to achieve the output that you are looking for:

normaltarget: mefirst2 normaltarget2
    @echo "normaltarget done"

helloworld: mefirst normaltarget
    @echo "helloworld done"

但是,正如您自己指出的那样,一旦使用-j标志并行运行配方,此解决方案"就会中断.而且,正如用户bobbogo所指出的那样,依靠这种排序机制是一种不好的做法.引入新的依赖项可能会干扰排序.所以不要这样做:-)

However, as pointed out by yourself, this "solution" breaks as soon as the -j flag is used to run recipes in parallel. Also, as pointed out by user bobbogo, relying on this ordering mechanism is bad practice. Introducing new dependencies can interfere with the ordering. So don't do this :-)

这篇关于仅订单先决条件在GNU make中无法正常工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆