Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Makefile 我可以改为引用$call by name的位置参数吗?_Makefile - Fatal编程技术网

Makefile 我可以改为引用$call by name的位置参数吗?

Makefile 我可以改为引用$call by name的位置参数吗?,makefile,Makefile,通过$(eval$(call))定义规则族非常有用,如下所示: define SIMPLE_TEMPLATE foo_$(1): echo foo $(1) endef $(foreach _,A B C,$(eval $(call SIMPLE_TEMPLATE,$_))) 这将创建目标foo_A、foo_B和foo_C。在一个更复杂的模板中,引用参数并用名称调用可能会更好;i、 e.$(消息)而不是$(1)。大概是这样的: define SIMPLE_TEMPLATE

通过$(eval$(call))定义规则族非常有用,如下所示:

define SIMPLE_TEMPLATE
  foo_$(1):
        echo foo $(1)
endef

$(foreach _,A B C,$(eval $(call SIMPLE_TEMPLATE,$_)))
这将创建目标
foo_A
foo_B
foo_C
。在一个更复杂的模板中,引用参数并用名称调用可能会更好;i、 e.
$(消息)
而不是
$(1)
。大概是这样的:

define SIMPLE_TEMPLATE
  MSG := $1
  foo_$(MSG):
        echo foo $(MSG)
endef

$(foreach _,A B C,$(eval $(call SIMPLE_TEMPLATE,$_)))

这几乎奏效了<代码>foo_A和
foo_B
按预期工作,但
foo_C
不工作。有趣的是,将
abc
更改为
abcd
会导致target
foo_C
开始工作。下面是我如何理解发生了什么:每次通过
eval
都会为
$(MSG)
分配一个值,但直到下一次
eval
调用时,才会感知到该分配。同样,如果在循环中附加额外的过程,这看起来确实有效。但感觉不对。有没有一种“正确”的方法可以做到这一点,而不必进行额外的密码破解?

根据定义方式(
a:=…
a=…
)和位置(在目标、先决条件、配方中…)在不同的可能时间进行递归扩展。简要说明这一点

我发现您的第二个Makefile存在两个不同的问题:

  • SIMPLE\u模板
    中的
    $(MSG)
    是在扩展
    $(foreach,A B C,…
    )的过程中展开的,而不是在将结果作为make语法进行正常解析的过程中展开的。让我们一步一步地看一下:

    • 扩展foreach的

      $(eval $(call SIMPLE_TEMPLATE,A)))
      $(eval $(call SIMPLE_TEMPLATE,B)))
      $(eval $(call SIMPLE_TEMPLATE,C)))
      
    • eval
      的扩展是特殊的,它扩展了其参数并将其实例化为make构造。因此,要理解,我们必须首先扩展
      调用
      。每个调用都替换
      简单模板定义中的
      $(1)
      。例如,传递给第一个
      eval
      的是:

      MSG := A
      foo_$(MSG):
          echo foo $(MSG)
      
    • 但是,
      eval
      参数的扩展将继续进行,直到没有可扩展的内容。对
      MSG
      的引用(尚未定义)将替换为空字符串,并且最终实例化的make构造为:

      MSG := A
      foo_:
          echo foo 
      
    有一个(看不见)
    echo foo
    末尾的空格。与任何make构造一样,它们会依次展开,但这不会改变任何内容,因为没有其他内容可展开。在第二个
    eval
    展开过程中,由于第一个
    MSG
    的值为
    A
    。因此,第二个
    eval
    收到:

        MSG := B
        foo_$(MSG)       
            echo foo $(MSG)
    
    调用
    ,将其展开为:

        MSG := B
        foo_A       
            echo foo A
    
    并将其实例化为make构造。这些make构造将再次展开(与任何其他make构造一样),但不会再更改任何内容。类似地,第三个
    eval
    实例化:

        MSG := C
        foo_B       
            echo foo B
    
    总之,将被实例化为make构造的是:

    MSG := A
    foo_:
        echo foo 
    
    MSG := B
    foo_A:
        echo foo A
    
    MSG := C
    foo_B:
        echo foo B
    
    您没有任何
    foo_C
    target(但您有一个不需要的
    foo_
    target…)

    要在扩展
    $(foreach…
    期间避免第一次过早扩展
    $(MSG)
    ,可以将
    $
    符号加倍:

    define SIMPLE_TEMPLATE
        MSG := $(1)
        foo_$$(MSG):
            echo foo $$(MSG)
    endef
    
    如果我们一步一步地运行此操作,第一个
    调用将通过:

    MSG := A
    foo_$$(MSG):
        echo foo $$(MSG)
    
    到第一个
    eval
    ,将其展开为:

    MSG := A
    foo_$(MSG):
        echo foo $(MSG)
    
    (每个
    $$
    吃一个
    $
    ),并将其实例化为make构造。这些新的make构造也将像任何其他make构造一样展开,将给出:

    MSG := A
    foo_A:
        echo foo $(MSG)
    
    (配方中的
    $(MSG)
    尚未展开,因为在配方中,展开延迟到第二阶段,并且仅在选择执行配方时发生)。在第一次展开
    $(foreach,A B C,…
    之后,您拥有的是:

    MSG := A
    foo_A:
        echo foo $(MSG)
    
    MSG := B
    foo_B:
        echo foo $(MSG)
    
    MSG := C
    foo_C:
        echo foo $(MSG)
    
    但在这里,您遇到了第二个问题:

  • 您的不同规则共享相同的
    MSG
    make变量。在第一阶段之后,它的值被解析为
    C
    ,并且您所拥有的等价于:

    MSG := C
    foo_A:
        echo foo $(MSG)
    foo_B:
        echo foo $(MSG)
    foo_C:
        echo foo $(MSG)
    
    结果将是:

    $ make foo_A foo_B foo_C
    echo foo C
    foo C
    echo foo C
    foo C
    echo foo C
    foo C
    
    可能不是您想要的。请注意,即使使用递归扩展的变量(
    MSG=…
    ),它也是一样的

  • 要解决第二个问题,可以对所有目标使用相同的make变量名,但为其指定特定于目标的值,如:

    define SIMPLE_TEMPLATE
        foo_$(1): MSG := $(1)
        foo_$(1):
            echo foo $$(MSG)
    endef
    
    (注意配方中的
    $
    ),其展开形式如下:

    foo_A: MSG := A
    foo_A:
        echo foo $(MSG)
    ...
    
    MSG_A := A
    foo_A:
        echo foo $(MSG_A)
    ...
    
    或者,可能使用不同的构造变量名:

    define SIMPLE_TEMPLATE
        MSG_$(1) := $(1)
        foo_$(1):
            echo foo $$(MSG_$(1))
    endef
    
    扩展为:

    foo_A: MSG := A
    foo_A:
        echo foo $(MSG)
    ...
    
    MSG_A := A
    foo_A:
        echo foo $(MSG_A)
    ...
    
    两者最终运行为:

    $ make foo_A foo_B foo_C
    echo foo A
    foo A
    echo foo B
    foo B
    echo foo C
    foo C
    
    可能更接近你的预期