如何从命令行覆盖目标特定变量?

3

假设有一个Makefile文件,其中包含一个target-specific定义:

# A target-specific definition for both: 'all' and 'x'.
all : foo += target
x   : foo += target


all : x ;

x ::
    @echo '$(foo)'


运行,我得到:

# override Makefile-level variables, with a command-line definition.
$ make foo=cmd
cmd



现在,同样的makefile,与上面一样,但使用了模式特定定义:

# A pattern-specific definition that matches both targets: 'all' and 'x'.
% : foo += target


all : x ;

x ::
    @echo '$(foo)'


我遇到的问题是:

# override Makefile-level variables, with a command-line definition.
$ make foo=cmd
cmd cmd cmd

现在,这两个makefile几乎是相同的,除了:
  • 对于Makefile版本1:(具有目标特定定义),我们有:
    all:foo += target
    x:foo += target
  • 对于Makefile版本2:(具有模式特定定义),我们有:
    %:foo += target

在这两种情况下,我们基本上拥有相同的配置:

  1. 一个模式/目标定义,它附加到先前的值。
  2. 该模式/目标定义适用于所有x目标。
  3. 我们有一个命令行定义,应该覆盖makefile级别的定义。

现在,解释或实现该覆盖,Make使用非常不同的方法,针对版本1(目标定义)和版本2(模式定义)。

让我们看看:

  • 对于目标定义,Make 完全忽略任何在makefile中定义的值。因此,最终值为:cmd
  • 然而,对于模式定义,Make采用"调和"方法,试图满足两者,即makefile级别的定义和命令行定义,因此:
    1. 接受最终值为cmd,根据覆盖makefile定义的命令行。
    2. 但是,由于makefile暗示"模式"应该"附加"其他值——不要紧那些相同的值已被覆盖——Make仍将服从这些附加值,但它将使用不同的值(即"获胜"的命令行值),从而达成一种"妥协",使得makefile或命令行都不能单独控制变量的最终值。

好吧,当我们期望它们非常不同的最终结果时,Make实施命令行覆盖所采取的不同方法(针对模式与特定目标变量)更加明显:

  1. cmd(针对特定目标)。
  2. cmd cmd cmd(针对模式特定)。

这是否有道理?为什么?

1个回答

3
这似乎是一个最小完整示例:
%: foo += targ

x:
    @echo $(foo)

当使用GNUMake v3.81时,以make foo=cmd的方式调用,会产生以下结果:

cmd cmd

这看起来像是一个bug。根据手册的说法,命令行中提供的变量(如果有‘-e’选项,则还包括环境变量)将优先于目标特定变量。因此,+=语句不应该产生任何影响。但显然,如果赋值在模式规则中,命令行的值会取代规则尝试追加的,但不会取代追加操作本身,因此Make会将$(foo)追加到自身。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接