Gnu make gmake如何解析和执行模板定义

Gnu make gmake如何解析和执行模板定义,gnu-make,Gnu Make,所以,我有一个制作模板。我这样说: $(eval $(call PRIVATE_LIBRARY_TEMPLATE,privatelib1,64)) 它的定义如下: define PRIVATE_LIBRARY_TEMPLATE # Evaluate the condition multiple times because of way make processes templates $(if $(2)=='',$(eval $(call LIBRARYBUILD_TEMPLATE,$(1)

所以,我有一个制作模板。我这样说:

$(eval $(call PRIVATE_LIBRARY_TEMPLATE,privatelib1,64))
它的定义如下:

define PRIVATE_LIBRARY_TEMPLATE

# Evaluate the condition multiple times because of way make processes templates
$(if $(2)=='',$(eval $(call LIBRARYBUILD_TEMPLATE,$(1),32)))
$(if $(2)=='',$(eval $(call LIBRARYBUILD_TEMPLATE,$(1),64)))
$(if $(2)!='',$(eval $(call LIBRARYBUILD_TEMPLATE,$(1),$(2))))

# More stuff that doesn't matter here
endef
或者说:

define PRIVATE_LIBRARY_TEMPLATE

# Evaluate the condition multiple times because of way make processes templates
$(if $(2)=='',$(call LIBRARYBUILD_TEMPLATE,$(1),32))
$(if $(2)=='',$(call LIBRARYBUILD_TEMPLATE,$(1),64))
$(if $(2)!='',$(call LIBRARYBUILD_TEMPLATE,$(1),$(2)))

# More stuff that doesn't matter here
endef
以前它被定义为:

define PRIVATE_LIBRARY_TEMPLATE

$$(eval $$(call LIBRARYBUILD_TEMPLATE,$(1),32))
$$(eval $$(call LIBRARYBUILD_TEMPLATE,$(1),64))
在我添加
$(如果
)之前,
$(1)
会完整地传递给LIBRARYBUILD\u模板,但一旦我添加
$(如果
$(1)
就会变成一个空字符串

我已经尝试了各种组合的
$
$(eval
$$eval
等,但有一点我只是不了解gmake解析这个模板定义的方式

我试图做的是在这个模板中使
$(2)
成为可选的,如果提供了,则使用它;如果没有提供,则使用它构建32位和64位库


模板定义最初是如何解析的,然后是如何计算的。

首先,函数
$(if条件,然后part,else部分)
与其他条件(如
ifeq
)不同。
$(if)
函数条件只需检查是否为空字符串():

如果它扩展到任何非空字符串,则该条件被视为true。如果它扩展到空字符串,则该条件被视为false

当涉及到
$(eval$(call…
)时,事情可能会变得棘手,必须按照什么顺序对事情进行评估。我通常这样想:

如果运算的计算结果取决于参数(如
$1
),则运算需要延迟

所以在你的情况下,我认为这就是你想要的:

.SECONDEXPANSION:
define LIBRARYBUILD_TEMPLATE
$$(info >>  LIBRARYBUILD_TEMPLATE: $1 $2)
endef

define PRIVATE_LIBRARY_TEMPLATE
  $$(info > PRIVATE_LIBRARY_TEMPLATE $1 $2)
  ifeq ($2,)
    $$(eval $$(call LIBRARYBUILD_TEMPLATE,$1,32))
    $$(eval $$(call LIBRARYBUILD_TEMPLATE,$1,64))
  else
    $$(eval $$(call LIBRARYBUILD_TEMPLATE,$1,$2))
  endif
endef


$(eval $(call PRIVATE_LIBRARY_TEMPLATE,privatelib1,64))
$(eval $(call PRIVATE_LIBRARY_TEMPLATE,privatelib2,))
它给出了输出:

> PRIVATE_LIBRARY_TEMPLATE privatelib1 64
>>  LIBRARYBUILD_TEMPLATE: privatelib1 64
> PRIVATE_LIBRARY_TEMPLATE privatelib2 
>>  LIBRARYBUILD_TEMPLATE: privatelib2 32
>>  LIBRARYBUILD_TEMPLATE: privatelib2 64

让我们使用
PRIVATE\u LIBRARY\u模板的定义

define PRIVATE_LIBRARY_TEMPLATE
# Evaluate the condition multiple times because of way make processes templates
$(if $(2)=='',$(eval $(call LIBRARYBUILD_TEMPLATE,$(1),32)))
$(if $(2)=='',$(eval $(call LIBRARYBUILD_TEMPLATE,$(1),64)))
$(if $(2)!='',$(eval $(call LIBRARYBUILD_TEMPLATE,$(1),$(2))))
endef
详细了解make在遇到问题时所做的事情是很有启发性的

$(eval $(call PRIVATE_LIBRARY_TEMPLATE,privatelib1,64))
显然,make必须先展开
$call
,然后才能展开
$eval

  • 1
    设置为
    privatelib1
  • 2
    设置为
    64
  • PRIVATE\u LIBRARY\u模板现在已展开

    • 首先,
      $(如果…
      需要扩展:

      • Make查看
        $(如果$(2)='',$(调用LIBRARYBUILD_模板,$(1),32))
        ,然后展开
        $(2)=''
        。您会注意到
        64=''
        不是空字符串,因此被认为是真的。要完成
        $的展开(如果…)
        ,make因此选择真正的分支并继续展开
        $(调用LIBRARYBUILD\u模板,$(1),32)

        • 1
          变为
          privatelib1
        • 2
          变为
          32
        • $(调用LIBRARYBUILD\u TEMPLATE,privatelib1,32)
          会变成一些文本。不知道是什么,但由于它最终会被传递给
          $eval
          ,所以它必须是有效的make语法。让我们假设它是类似
          LIB\u privatelib1\u 32:=1
          这样简单的东西
      • 第二个
        $(如果…
        )类似地展开

      • 第三个
        $(if…
        类似地展开

      • 为了便于讨论,让我们假设
        $(调用PRIVATE\u LIBRARY\u TEMPLATE,…)
        的最终扩展是以下文本:
        
        LIB_privatelib1_32:=1
        LIB_privatelib1_64:=1
        LIB_privatelib1_64:=1

这三行被传递到
$eval

  • 作为副作用,定义了三个新的简单变量
  • $(eval…
    的扩展名为空

这里一个明显的错误是,
==
的make语法无效。 真实性仅仅是字符串中是否包含字符。 您可能需要以下内容:

$(if $2,$(eval $(call LIBRARYBUILD_TEMPLATE,$1,32)))
$(if $2,$(eval $(call LIBRARYBUILD_TEMPLATE,$1,64)))
$(if $2,,$(eval $(call LIBRARYBUILD_TEMPLATE,$1,$2)))
(查看最后一个否定。)