假设有一个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
在这两种情况下,我们基本上拥有相同的配置:
- 一个模式/目标定义,它附加到先前的值。
- 该模式/目标定义适用于
所有
和x
目标。 - 我们有一个命令行定义,应该覆盖makefile级别的定义。
现在,解释或实现该覆盖,Make使用非常不同的方法,针对版本1(目标定义)和版本2(模式定义)。
让我们看看:
- 对于目标定义,Make 完全忽略任何在makefile中定义的值。因此,最终值为:
cmd
。 - 然而,对于模式定义,Make采用"调和"方法,试图满足两者,即makefile级别的定义和命令行定义,因此:
- 接受最终值为
cmd
,根据覆盖makefile定义的命令行。 - 但是,由于makefile暗示"模式"应该"附加"其他值——不要紧那些相同的值已被覆盖——Make仍将服从这些附加值,但它将使用不同的值(即"获胜"的命令行值),从而达成一种"妥协",使得makefile或命令行都不能单独控制变量的最终值。
- 接受最终值为
好吧,当我们期望它们非常不同的最终结果时,Make实施命令行覆盖所采取的不同方法(针对模式与特定目标变量)更加明显:
cmd
(针对特定目标)。cmd cmd cmd
(针对模式特定)。
这是否有道理?为什么?