GNU make 手册介绍了仅订购先决条件:
target: prerequisite1 prerequisite2 | orderonlyprerequisite1 orderonlyprerequisite2
但是,虽然该手册页提供了示例并描述了仅订单先决条件的目的,但该手册页从未回答标题中的问题:什么是仅订单先决条件?
您能否给出仅订单先决条件的行为的精确定义?
首先,让我们回顾一下一般的先决条件是什么。
基本上,Makefile 中的先决条件有两个作用:
仅订单先决条件执行第 1 项,即强加构建顺序,但不执行第 2 项。
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
因为虽然为了生孩子你必须做爱,但不是每次你做爱时都必须生孩子。
正常的先决条件有两个声明:首先,它规定了调用配方的顺序:目标的所有先决条件的配方将在目标的配方运行之前完成。其次,它强加了依赖关系:如果任何先决条件比目标新,则目标被认为是过时的,必须重建。
然后它描述了仅订单先决条件的行为与此有何不同;它将:
对要调用的规则施加特定的顺序,
而不在执行这些规则之一时强制更新目标。
首先,
目录作为目标。您想要创建一个文件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
。