处理“--just-print”命令行选项的配方不一致

时间:2015-08-21 10:34:18

标签: makefile gnu-make

来自docs

  

-n-t-q选项不会影响配方行   以+字符开头或包含字符串$(MAKE)${MAKE}。   请注意,只有包含+字符或字符串的行   无论这些选项如何,都会运行$(MAKE)${MAKE}。其他线路   除非它们也以+开头或包含,否则不会运行同一规则   $(MAKE)${MAKE}



现在,给定一个makefile:

# 'test -f foo' is "false".
$(shell rm -rf foo)
# 'test -f bar' is "true".
$(shell rm -rf bar; touch bar)

# 'test -f bar' will be executed, even for -[tnq] command-line options. NOT SO, for 'test -f foo'.
define cmd
test -f 'foo'
+test -f 'bar'
endef


1 2 ::
    $(cmd)



正在运行,我们得到:

$ make --just-print 1
test -f 'foo'
test -f 'bar'

#####################

$ make --just-print 2
test -f 'foo'
test -f 'bar'

#####################

$ make --just-print 1 2
test -f 'foo'
test -f 'bar'
test -f 'foo'
makefile:14: recipe for target '2' failed
make: *** [2] Error 1

#####################

$ make --just-print 2 1
test -f 'foo'
test -f 'bar'
test -f 'foo'
makefile:14: recipe for target '1' failed
make: *** [1] Error 1



显然,我们有4个案例:

  1. make --just-print 1
    • test -f foo,显然是“假”命令,成功。这是因为--just-print命令行选项,所以Make并没有真正“运行”它。这只是一个 echo
    • test -f bar,由于+前缀,实际运行的命令。但鉴于这个配方是一个“真正的”命令,它成功并不奇怪。
  2. make --just-print 2
    • 完全案例1 。那么,配方执行 for 的目标在这里可能会有所不同(21),但执行的配方是100%相同< / strong>即可。这包括他们成功背后的“逻辑”,在case 1中解释。
  3. make --just-print 1 2
    • 这更复杂。它从case 1开始,出于同样的原因,两者都有:test -f footest -f bar成功。
    • 但是,当Make必须“重复”相同的“例程”时,通过执行2的配方,会发生致命错误。为什么?
  4. make --just-print 2 1
    • case 3相同,但21目标在这里扮演的是“相反”的角色。也就是说,2的执行成功(按照case 2),但在目标1上失败。


  5. 现在,毫无疑问,这里出了点问题。

    test -f foo模式下执行时,--just-print的Make永远不会失败。

    简单地说,因为不允许Make执行命令。它应该只是回应它!

    那么,这里有什么问题?

1 个答案:

答案 0 :(得分:0)

它与多行变量的扩展有关,其中包含+的内容在一行而不是其他行。如果使用普通内容而不是多行变量编写规则,则它适用于所有情况:

1 2 ::
        test -f 'foo'
        +test -f 'bar'

您应该提交有关此特殊情况的错误。包含多行的变量很棘手,因为它们在首次被make解析时只显示为一行,但在执行时会扩展为多行。