Makefile:什么是仅限订单的先决条件?

问题描述 投票:0回答:4

GNU make 手册介绍了仅订购先决条件

target: prerequisite1 prerequisite2 | orderonlyprerequisite1 orderonlyprerequisite2

但是,虽然该手册页提供了示例并描述了仅订单先决条件的目的,但该手册页从未回答标题中的问题:什么是仅订单先决条件?

您能否给出仅订单先决条件的行为的精确定义?

makefile
4个回答
52
投票

首先,让我们回顾一下一般的先决条件是什么。

基本上,Makefile 中的先决条件有两个作用:

  1. 对它们进行检查,如有必要,在目标之前构建它们
  2. 如果任何先决条件被重建(或者只是比目标新),那么目标也将被重建。
现在,

仅订单先决条件执行第 1 项,即强加构建顺序,但不执行第 2 项。


49
投票
假设你有一个像这样的Makefile

baby: love touch $@ love: touch $@
然后

make

说,

touch love touch baby
现在你

rm love

make

touch love touch baby
因为为了生孩子,你必须做爱,

并且每次你做爱时,你都必须生孩子。然而,假设您不想每次做爱时都生孩子。在这种情况下,您可以使用管道。

baby: | love touch $@
现在你

rm love

make
只说

touch love
因为虽然为了生孩子你必须做爱,但

不是每次你做爱时都必须生孩子。


3
投票

正常的先决条件有两个声明:首先,它规定了调用配方的顺序:目标的所有先决条件的配方将在目标的配方运行之前完成。其次,它强加了依赖关系:如果任何先决条件比目标新,则目标被认为是过时的,必须重建。

然后它描述了仅订单先决条件的行为与此有何不同;它将:

对要调用的规则施加特定的顺序,
而不

在执行这些规则之一时强制更新目标。


0
投票

首先,

目录作为目标。

您想要创建一个文件bin/package.jar,并且如果需要的话您想要创建

bin
。这个 Makefile 片段看起来不错:
bin/package.jar: bin
    jar cfm $@ manifest.txt $(CLASSES)

bin:
    mkdir $@

但它有一个潜在的缺陷。如果 
bin

bin/package.jar
更新,那么 make 将在不需要时重建
bin/package.jar
。然而,如果其中的任何文件发生更改,
bin
的修改时间也会改变!在较大的 Makefile 中,可能会由于意外原因而发生这种情况。手册对此进行了描述:

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

bin/package.jar: | bin jar cf $@ $(CLASSES) bin: mkdir $@
第二,
检查文件是否存在,但忽略其内容。

假设您要自动创建manifest.txt,检查Java源文件并将其名称放入

manifest.txt
中。再次强调,使用仅限订单的先决条件:
MAINCLASS=Coffee

manifest.txt: | $(MAINCLASS).java
    echo "Main-Class: $(MAINCLASS)" > $@

# Other targets may use $(MAINCLASS).java or $(MAINCLASS).class

manifest.txt

需要

$(MAINCLASS).java
存在。但是更改
$(MAINCLASS).java
的内容(这会更改其修改时间,这就是 make 所使用的)不应该重建
manifest.txt
    

© www.soinside.com 2019 - 2024. All rights reserved.