Makefile 是否在导出递归变量之前使其展开?

Makefile 是否在导出递归变量之前使其展开?,makefile,gnu-make,Makefile,Gnu Make,给定一个生成文件: ifeq“$(MAKELEVEL)”0 0 :: @$(制造) 其他的 1 :: @echo'foo is:“$(foo)”' 恩迪夫 然后执行,我们得到: $make foo='$@' make[1]:输入目录“/home/myname” 傅是:“1” make[1]:离开目录“/home/myname” $make foo='$@'--环境覆盖 make[1]:输入目录“/home/myname” 富是:“0” make[1]:离开目录“/home/myname”



给定一个生成文件:

ifeq“$(MAKELEVEL)”0
0 ::
@$(制造)
其他的
1 ::
@echo'foo is:“$(foo)”'
恩迪夫


然后执行,我们得到:

$make foo='$@'
make[1]:输入目录“/home/myname”
傅是:“1”
make[1]:离开目录“/home/myname”
$make foo='$@'--环境覆盖
make[1]:输入目录“/home/myname”
富是:“0”
make[1]:离开目录“/home/myname”


因此,我们这里有一个递归变量
foo
,其值为:
$@
,当然,它会扩展到目标的名称。现在,我们有两个选择:

  • 或者,Make首先展开变量,然后将变量导出到子Make。

    使用此“逻辑”,当Make运行第一个makefile(
    MAKELEVEL=0
    )时,它将构建目标0,因此:将变量
    foo
    (及其值:
    $@
    )展开为
    0
    ,然后将此已展开的值导出到子Make。

    这个结果是,当子make运行其makefile时,变量
    foo
    的值很简单:
    0


    事实上,当我们运行
    make--environment overrides
    时就是这种情况,正如您在上面示例中的makefile的第二次运行中所看到的那样。

  • 另一个“逻辑”是Make传递值“逐字”。这意味着,没有扩展


    因此,当传递给第二个Make时,所有递归变量都将保持不变。

    对于该逻辑,仅允许子make递归扩展其变量,因此:任何递归扩展都将在子make的上下文中完成。

    在上面的示例中,我们使用了
    foo
    及其值
    $@
    ,如果我们遵循此逻辑,Make将传递值
    $
    “verbatim”,而不进行任何扩展,因此子Make将有效地看到其
    foo
    变量的值
    $
    ,因此:当在目标的上下文中进行扩展时,恰好是1,它将递归地将
    foo
    (及其值:
    $@
    )扩展到1

    实际上,这是第一次运行makefile时明显的“正常”行为,如上面的示例所示

  • 因此,由于缺乏明确的方法,我们只能得出结论,扩展然后导出导出然后扩展的行为是不一致的

    也就是说,有时候Make会选择第一种方法,有时候Make会选择第二种方法

    在我们的示例中,它是一个命令行选项(
    --environment--overrides
    ),作为决定Make必须选择什么方法的因素

    但是,我们真的能证明这些看似不相关的特性(即导出/递归与环境覆盖)最终会对彼此产生如此巨大的影响吗




    (版本说明:4.0及更高版本)。
    make
    以扩展形式导出foo,如下所示:

    target:
        @echo "'$$foo'"
    
    输出:

    $make foo='$@'
    'target'
    
    $make foo='$@'
    ' -- foo=$$@'
    
    但是,要将其参数传递给sub make,它不直接使用环境——而是将所有内容填充到变量
    MAKEFLAGS
    中。在那里它通过了未展开的foo:

    target:
        @echo "'$$MAKEFLAGS'"
    
    输出:

    $make foo='$@'
    'target'
    
    $make foo='$@'
    ' -- foo=$$@'
    
    需要明确的是:子make确实从环境中导入
    foo
    ,但随后会被
    MAKEFLAGS
    中的设置覆盖


    指定
    --environment--overrides
    时,意味着环境变量优先于makefile中的设置。GNU make文档没有明确指定在存在
    --environment--overrides
    的情况下,通过
    MAKEFLAGS
    传入的变量会发生什么情况,但显然它们也被重写了。

    非常好的一点。谢谢我们仍然必须解决如何和为什么这样做的问题。也就是说,命令行变量的导出是如何受到命令行选项(如
    --environment overrides
    )的影响的。但更令人不安的是,原因何在。i、 e.为什么导出在命令行上定义的变量(仅在命令行上定义的变量)会受到看似不相关的命令行选项的影响,例如
    --环境覆盖
    。因为从语义上讲,它总是如此(即,无论是否使用
    --环境覆盖
    )一个命令行级别变量(当然,它比环境级别变量高一个级别,即使使用
    --环境覆盖
    )。因此,导出wize、Make应始终使用相同(或等效)机制来执行相同类型的导出(即,要么先展开,要么不展开)。