变量“$?”的扩展错误在makefile中

时间:2015-08-20 09:37:51

标签: makefile gnu-make

来自docs

  

$?   
  
  比目标更新的所有先决条件的名称,   它们之间有空格。



现在,给定一个makefile:

# Create target 'all', that is created later than 'old', which was created after 'older'.
$(shell touch older)
$(shell sleep 1)
$(shell touch old)
$(shell sleep 1)
$(shell touch all)

all : old phony;
    @echo '"$$?" is: "$?"'

# A command to turn the file 'old' even "older", by acquiring the modification-time of 'older'.
old ::
    cp -p 'older' 'old'


.PHONY: phony



正在运行,我得到:

$ make
cp -p 'older' 'old'
"$?" is: "old phony"

# Trying again, but this time, with a *parallel-execution*.
$ make -j
cp -p 'older' 'old'
"$?" is: "phony"



*你能否看到,Make为并行执行$?)以不同于非并行的方式扩展-j的值-execution ?*

让我们首先分析第一种情况,即非并行执行。

allold的修改时间为:

  • 在构建之前 oldall“更早”。这是不言而喻的。正确?
  • 在完成构建先决条件 之后,即在Make“builds”old之后,old变得“更老”,可以这么说通过“获取”名为older的文件的修改时间。这基本上是shell命令的净结果:cp -p older old。现在,不难看出,older 方式“年龄大于”all

现在,由于其他先决条件,即:all,Make最终构建了目标phony

但是,根据文档,$?应仅扩展为“比目标更强更新的所有先决条件的名称”。这是一个完全引用。

我们是否同意,old 从不 较新而不是all。而且,如果不是phony,那么Make甚至不会重新构建all

那么,对于Make来说,将$?扩展为old phony会有多么错误。

phony我明白了。但old?真的吗?!



但是,我们现在将注意力转向并行执行,其中Make将$?扩展为phony

下面:

  1. 当然,可以说,扩展是正确的(与非并行执行中的扩展相比)。 原因是,只有phony 触发重新构建all的文件。如果没有它,Make就不会费心去重建all了。

  2. 然而,人们不禁要问,如何以这两种执行模式不同地扩展变量。 我甚至无法思考,这与$?的扩展有什么关系。

    总之,看起来“随机”更改(即执行模式的修改,从并行非并行)会影响看似无关的实体,这是自动变量的扩展。为什么呢?

2 个答案:

答案 0 :(得分:1)

make生成或更新的任何文件都已更新,因此它会隐式地假设它更新,即使您破解了使其更旧的命令。

理论上,Make应该处理文件的内容,而不是日期。如果内容不同,那么您应该运行依赖构建。鉴于我们没有文件系统提供简单的内容派生(哈希等),它使用最后修改日期来执行此操作。因为这也不是100%可靠 - 例如,参见那些日期不具备足够准确性的系统,或者将来只是的系统 - 它也会使用这是一个信息来源。如果它只是构建它,它必须被修改,因此它是正确的考虑它"更新"或者"重建"。

答案 1 :(得分:1)

使用规则构建old后,Make现在认为它是依赖关系图中的最新文件。 在完成之后不会检查old

对于虚假目标来说,这显然是正确的做法,对于文件目标来说通常也是正确的事情。