通过制造' $?'来实现不一致的扩张。变量

时间:2015-08-21 03:14:53

标签: makefile gnu-make

来自docs

  

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



所以,给定一个makefile:

# Force make to search for 'foo' in the VPATH directory
$(shell rm -rf foo)
# If 'D' is a "regular" file, we remove it first.
$(shell rm -rf D)
$(shell mkdir D)
# Suggest a VPATH-file, for Make to "associate" with 'foo'.
$(shell touch D/foo)
$(shell sleep 1)
# Target 'all' is newer than prerequisite 'D/foo'
$(shell touch all)

VPATH = D

all : foo phony
    echo '$?'

foo ::
    touch '$@'

.PHONY: phony

.PRECIOUS : D/foo



然后跑步,我得到:

$ make -r
touch 'D/foo'
echo 'D/foo phony'
D/foo phony

# Try again, but this time, with parallel-execution mode.
$ make -r -j
touch 'D/foo'
echo 'phony'
phony



在这里,我们有两个严重的问题:

  1. 鉴于"触摸"简单且明确的配方先决条件foo,明确执行 - 因此保证 foo将是"更新"比all - 仍然$?扩展为D/foo,至少在上面的第二种情况下(即 parallel - 执行(-j)模式)。为什么?
  2. 如果你想出上述解释,不应该解释,为什么在第一种情况下(非并行执行),$? - 确实 - 扩展到D/foo

    我想,我有一个假设, parallel 非并行不同,Make会在执行目标之前暂停 ,并且首先检查所有的先决条件是否已完成各自的版本。
  3. 那么,对于这两种情况,$?变量是否应该相同地扩展?

1 个答案:

答案 0 :(得分:0)

我认为这里有两个问题。

首先,双冒号规则似乎像虚假的目标,因为它们迫使make将目标视为“更新”而不管实际的修改时间。 (这就是非并行版本的行为方式。从foo ::更改为foo :并且foo输出中根本没有$?。 )

第二件事是,尽管如此,使用并行模式似乎迫使重新考虑其先决条件的修改时间(因此避免了先前的行为)。

这是猜想而不是决定因素,因为我没有挖掘代码来查看这是否真的发生了但是它解释了这里的结果(它也解释了另一个结果,几乎相同,问题here )。