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

时间:2016-03-18 22:17:23

标签: gnu-make

所以,我有一个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),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))

在我添加$(if之前,$(1)完整地传递给LIBRARYBUILD_TEMPLATE,但是一旦我添加$(if$(1)就变成空字符串。

我尝试了$$ $(eval $$eval等的各种组合,但有些基本原理我只是不了解gmake解析此模板定义的方式。

我要做的是在此模板中使$(2)成为可选项,并在提供时使用它,或者如果没有提供,则构建32位和64位库。

如何最初解析模板定义,然后进行评估。

2 个答案:

答案 0 :(得分:0)

首先,函数$(if condition,then-part,else-part)ifeq等其他条件不同。只检查$(if)函数条件是否为空字符串(c.f. manual):

  

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

当谈到$(eval $(call ...)时,事情可能变得棘手,必须评估事物的顺序。我通常这样想:

  

如果操作的评估结果取决于参数(如$1),则操作需要延迟secondary expansion

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

.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

答案 1 :(得分:0)

让我们使用PRIVATE_LIBRARY_TEMPLATE

的定义
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))

显然,在展开$eval之前, make 必须首先展开$call

  • 1设置为privatelib1
  • 2设置为64
  • PRIVATE_LIBRARY_TEMPLATE现已扩展。

    • 首先,$(if …)需要扩展:

      • 制作查看$(if $(2)=='',$(call LIBRARYBUILD_TEMPLATE,$(1),32))中的条件,然后展开$(2)==''。您会注意到64==''不是空字符串,因此被视为 true 。要完成$(if …)的扩展, make 会选择真正的分支,然后继续展开$(call LIBRARYBUILD_TEMPLATE,$(1),32)

        • 1变为privatelib1
        • 2变为32
        • $(call LIBRARYBUILD_TEMPLATE,privatelib1,32)成为一些文字。不知道是什么,但由于它最终将传递给$eval,因此它必须是有效的 make 语法。我们假设它像LIB_privatelib1_32 := 1一样简单。
      • 同样扩展了第二个$(if …)

      • 同样扩展了第三个$(if …)

      • 为了论证,让我们说$(call PRIVATE_LIBRARY_TEMPLATE,…)的最终扩展是这样的文字: LIB_privatelib1_32 := 1 LIB_privatelib1_64 := 1 LIB_privatelib1_64 := 1

这三行传递给$eval

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

呼。

这里一个明显的错误是==无效 make 语法。 Truthyness仅仅是一个字符串是否包含字符。 你可能想要这样的东西:

$(if $2,$(eval $(call LIBRARYBUILD_TEMPLATE,$1,32)))
$(if $2,$(eval $(call LIBRARYBUILD_TEMPLATE,$1,64)))
$(if $2,,$(eval $(call LIBRARYBUILD_TEMPLATE,$1,$2)))

(查看最后一项否定。)