Debugging 在make函数内部使用eval

Debugging 在make函数内部使用eval,debugging,makefile,gnu-make,Debugging,Makefile,Gnu Make,(注意——这与我之前的问题类似,但似乎有不同的原因,所以我在这里发布了一个新问题) 我正在调试一些makefiles,其中包含一些非常复杂的eval。我希望能够准确地转储eval扩展到的内容,然后调用eval。我需要这样做,以便可以轻松地打开/关闭调试,但我发现函数中的eval有一些奇怪的行为。我有: FOO := a:=foo $(eval $(FOO)) $(info a=$(a)) #a=foo -- OK define eval_dbg $(info eval_dbg: runni

(注意——这与我之前的问题类似,但似乎有不同的原因,所以我在这里发布了一个新问题)

我正在调试一些makefiles,其中包含一些非常复杂的eval。我希望能够准确地转储eval扩展到的内容,然后调用eval。我需要这样做,以便可以轻松地打开/关闭调试,但我发现函数中的
eval
有一些奇怪的行为。我有:

FOO := a:=foo
$(eval $(FOO))
$(info a=$(a))   #a=foo -- OK

define eval_dbg
$(info eval_dbg: running [$1]) # $1 is "a:=bar"
$(eval $(1))                   # fails - missing seperator...
endef

$(call eval_dbg,a:=bar)    #causes error...
$(info a=$a)
但是,我得到:

a=foo
eval_dbg: running [a:=bar]
test2.mk:17: *** missing separator.  Stop.
是否可以评估呼叫参数


**最小可复制示例:**

tmp> more test3.mk
FOO := a:=foo
$(eval $(FOO))
$(info a=$(a))

define eval_dbg
$(info eval_dbg: running [$1])
$(eval $(1))
endef

$(call eval_dbg,a:=bar)
$(info a=$a)

all:
        @echo running $@

tmp> make -f test3.mk
a=foo
eval_dbg: running [a:=bar]
test3.mk:10: *** missing separator.  Stop.

tmp> make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for x86_64-unknown-linux-gnu

问题是调用
eval(…)
的结果是空字符串,因此实际上您传递的是
call
一个参数——定义的函数
eval\u dbg
——它包含空格,
call
不喜欢空格

define func_1
$(info hello)
endef

$(call func_1) # this works                                                     

define func_2
$(info hello)

endef

$(call func_2) # this fails 

define func_3
$(info hello)
$(eval a:=b)
endef

$(call func_3) # this also fails
但是没有理由从函数内部调用
eval
。如图所示,您可以打印语句,然后对其调用
eval
。或者您可以将调用的结果传递给
call

define foo_double
$(1):=foo_$(1)$(1)
endef

$(info $(call foo_double,a))
$(eval $(call foo_double,a))

$(info a is $a)

该问题是由于“定义”中的注释引起的

基本上,“define”与变量赋值相同(除了换行符)。“调用”进行扩展,但不进行评估。因此,未经计算就进入流的注释-->发生错误

因此,道德:

  • 定义不是一个宏;这是一根绳子
  • 呼叫不是一种评估;这是一个扩展
  • 评论不是空白;对其进行评估
  • UPD。事实证明,另一个问题是旧版本。看起来v3.81不能像现代make版本那样简单地忽略空白

    另一个评估解决了此问题:

    $(eval $(call eval_dbg,a:=bar))
    

    call不喜欢空白
    call可以使用空白。它甚至保存了它(大部分)。这可能是呼叫方的问题,但不是呼叫的问题。您能扩展到
    呼叫不喜欢空白吗?根据我的理解,
    $(info)
    也会导致一个空字符串,那么为什么
    func_1
    工作,而不是
    func_2
    ?不幸的是,现实生活中的场景比我所发布的要复杂得多(这只是一个很小的例子),其中有58个eval,其中大多数在for循环中,并且大多数都有多行表达式。我真的希望有一个eval的替代品,它可以在计算表达式之前打印表达式(当然,如果调试打开了…。@user11809993
    func_1
    扩展为空字符串
    func_2
    扩展为一个新行。@user11809993这是因为
    define
    之后的一个新行和
    endef
    之前的另一个新行会被自动删除。我真的很希望eval的替代品能在计算表达式之前打印出来:最简单的方法是将
    eval
    替换为
    错误
    。参数将出现在stderr上,make将停止。我明白你的意思。不幸的是,如果我删除了评论,我仍然会得到一个错误。(事实上,评论中的错误与我描述的不同——我的坏朋友,我在写文章时添加了评论以保持清晰,没有意识到它们改变了行为)。@user11809993如果删除了评论,我没有错误。什么是?在我的问题中添加了MRE(原始输出、剪切和粘贴——为清晰起见,在命令之间添加了几行换行符)。我开始觉得你在运行不同版本的make。@Beta的
    func_1
    func_2
    对你的品牌有效吗?(
    func_2
    在我的上失败)@user11809993 3 3.81版严重过时。看起来它也想评估空白。这在现代的make版本中是没有遇到的。从技术上讲,Beta的答案是正确的,所以我认为他的答案是正确的。不幸的是,我没有足够的代表投票,所以我不能投票支持你的答案。不过我很感谢你抽出时间。你是如何坚持3.81的?也许我们可以帮上忙——我不知道为什么3.81仍然如此流行,它的不兼容性每隔3周左右就会出现一次。