在 makefile 中使用 eval 函数时遇到问题

Trouble using eval function in makefile

提问人:NotYourFox 提问时间:11/14/2023 最后编辑:NotYourFox 更新时间:11/15/2023 访问量:24

问:

我正在尝试编写一个 makefile 函数,它将目录中的源添加到变量中并重新计算对象变量。

rwildcard = $(wildcard $(addprefix $1,$2)) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

define __add_sources
    SOURCES += $(call rwildcard,$(realpath $1)/,*.c *.S) 
    _SOURCES = $$(SOURCES:  %= %)
    OBJECTS = $$(addprefix $(OBJDIR)/,$$(addsuffix .o,$$(subst $(realpath $1)/,$2,$$(call rwildcard,$$(_SOURCES)))))
endef

当我打电话时

add_sources = $(info $(call __add_sources,$1,$2))
_ = $(call add_sources,src,)

它确实输出(对不起,为了隐私不得不省略一些路径输出,希望这无关紧要)

    SOURCES +=  <path>/<file>.S   <path>/<file>.c <path>/<file>.c <path>/<file>.S         <path>/<file>.c   <path>/<file>.c <path>/<file>.c           <path>/<file>.c   <path>/<file>.c <path>/<file>.c          
    _SOURCES = $(SOURCES:  %= %)
    OBJECTS = $(addprefix <objpath>/objects/,$(addsuffix .o,$(subst <srcpath>,,$(call rwildcard,$(_SOURCES)))))

这看起来不错,看起来像是我需要的东西,但是,当我在 add_sources 中用 eval 替换 info 时,期望 Makefile 将评估文字并处理赋值,但在输出时,我没有看到任何分配给 SOURCES 或 OBJECTS。

生成文件

评论


答:

1赞 MadScientist 11/15/2023 #1

哇,这是巧合的疯狂积累,以获得你所看到的结果。

我真的不明白为什么你有这么多层次的间接。但根本问题是,您实际上并没有调用这些函数中的任何一个。你有这个:

rwildcard = $(wildcard $(addprefix $1,$2)) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

define __add_sources
    SOURCES += $(call rwildcard,$(realpath $1)/,*.c *.S) 
    _SOURCES = $$(SOURCES:  %= %)
    OBJECTS = $$(addprefix $(OBJDIR)/,$$(addsuffix .o,$$(subst $(realpath $1)/,$2,$$(call rwildcard,$$(_SOURCES)))))
endef

add_sources = $(info $(call __add_sources,$1,$2))
_ = $(call add_sources,src,)

根据此代码,您定义了四个 make 变量:、、 和 。rwildcard__add_sourcesadd_sources_

但是你从来没有真正使用过这些变量中的任何一个,所以它们没有被扩展,它们也没有效果。您需要确保它们已扩展。例如,您可以添加如下行:

$(_)

全部由其本身进行,这将强制扩展变量。然后,您将看到 ._eval

那么,你可能会问,为什么在使用 时会看到输出,如果变量没有展开呢?这是下一个巧合。info

原因是你使用的是一个名为的变量,并且该变量对 shell 来说是特殊的,因此它将被添加到你的 shell 开始制作的环境中。当它启动 shell 脚本时,Make 将重新扩展它通过环境接收的任何变量。_

由于该变量是在 make 首次调用配方行时从环境中接收的,因此它将自动扩展该值,这就是可以看到 的输出的地方。但是,对任何变量(例如)所做的任何更改都不会保留,因为我们正在扩展要添加到子 shell 环境中的变量,而不是用于 make。_infoSOURCES

如果将该“临时”变量重命名为其他变量(例如或类似变量),则该变量不是从环境中继承的变量,那么您将看到上面显示的 makefile 的任何内容都不会打印出任何输出,因为该变量永远不会扩展。_dummy

评论

0赞 NotYourFox 11/15/2023
哦。。。我已将该行更改为 just (我也尝试过这样做,然后,我的 SOURCES var 在这两种情况下都发生了变化,但 OBJECTS 变量仍然是空的。所以在我看来,我的“var += literal”表达式被评估了,但其他动态表达式没有被评估。我是否必须以某种方式再次告诉 Makefile 才能这样做?据我从 GNU 文档中了解到,eval 应该扩展源代码并将其作为 Makefile 命令进行第二次处理$(call add_sources,src,)dummy = $(call...)$(dummy)
0赞 MadScientist 11/15/2023
我不知道该说什么,我以上面的例子为例,从那一行中删除了 只是调用 ,它起作用了:我曾经打印过 的值 ,和 ,它们都按预期设置。你一定做了一些不同的事情,而这些事情没有反映在你的问题中。_ =call$(info ...)SOURCES_SOURCESOBJECTS