GNU Make:如何在 $(eval) 中调用 $(wildcard)

发布于 2024-08-24 20:36:56 字数 1047 浏览 4 评论 0原文

我正在尝试为我的 Makefile 创建一个通用构建模板,有点像他们在 评估文档

我似乎无法让通配符函数在评估中工作。我遇到问题的基本代码如下所示。

SRC_DIR = ./src/

PROG_NAME = test

define PROGRAM_template
  $(1)_SRC_DIR = $(join $(SRC_DIR), $(1)/)
  $(1)_SRC_FILES = $(wildcard $$($(1)_SRC_DIR)*.c)
endef

$(eval $(call PROGRAM_template, $(PROG_NAME)))

all:
    @echo $(test_SRC_DIR)
    @echo $(test_SRC_FILES)
    @echo $(wildcard $(wildcard $(test_SRC_DIR)*.c)

当我用它运行 make 时,输出

./src/test

[correct list of all .c files in ./src/test/]

基本上是,PROGRAM_template 中的通配符调用没有按照我的预期进行评估。调用结果为空列表。
不过,连接调用正在被正确评估。

那么,我做错了什么?我的猜测是这

$$($(1)_SRC_DIR) 

是不正确的,但我无法找出正确的方法。

编辑 一旦这个问题解决了,没过多久我就遇到了 eval 的另一个问题。 我将其作为新问题发布在 GNU Make 3.80 eval 错误的解决方法

I'm trying to create a generic build template for my Makefiles, kind of like they discuss in the eval documentation.

I can't seem to get the wildcard function to work within an eval. The basic code I'm having issues with looks like this.

SRC_DIR = ./src/

PROG_NAME = test

define PROGRAM_template
  $(1)_SRC_DIR = $(join $(SRC_DIR), $(1)/)
  $(1)_SRC_FILES = $(wildcard $($(1)_SRC_DIR)*.c)
endef

$(eval $(call PROGRAM_template, $(PROG_NAME)))

all:
    @echo $(test_SRC_DIR)
    @echo $(test_SRC_FILES)
    @echo $(wildcard $(wildcard $(test_SRC_DIR)*.c)

When I run make with this, the output is

./src/test

[correct list of all .c files in ./src/test/]

Basically, the wildcard call within PROGRAM_template is not being eval'd as I expect it. The call results in an empty list.
The join call is being eval'd correctly though.

So, what am I doing wrong? My guess is that

$($(1)_SRC_DIR) 

is not correct, but I can't figure out the right way to do it.

EDIT
Once this was solved, it didn't take long for me to hit another issue with eval.
I posted it as a new question at
Workaround for GNU Make 3.80 eval bug

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故笙诉离歌 2024-08-31 20:36:57

使用 eval 时,您几乎需要对所有函数和变量进行双重转义。在大多数情况下,唯一不需要需要双重转义的是函数参数(因为call函数将完全扩展它们)。在这种情况下,从技术上讲,您也不需要双重转义 joinSRC_DIR,但如果您始终对所有变量和函数进行双重转义,它将简化您的生活使用eval时。

您需要两次转义的原因是使用eval时会发生两次扩展。 eval 函数本身执行扩展,然后当该块最终被解析为 makefile 语法时(即实际评估时),再次执行扩展。

按照您编写的方式,在字符串文字 $( test_SRC_DIR)*.c 上调用 wildcard 。如果需要,您可以在您的版本中将 wildcard 替换为 info 来亲自查看,看看会发生什么。

您需要推迟实际调用通配符,直到第二次扩展,以便它的参数是扩展的结果 $(test_SRC_DIR)

试试这个:

SRC_DIR = ./src/

PROG_NAME = test

define PROGRAM_template
  $(1)_SRC_DIR = $(join $(SRC_DIR),$(1)/)
  $(1)_SRC_FILES = $(wildcard $($(1)_SRC_DIR)*.c)
endef

$(eval $(call PROGRAM_template,$(PROG_NAME)))

all:
    @echo $(test_SRC_DIR)
    @echo $(test_SRC_FILES)
    @echo $(wildcard $(test_SRC_DIR)*.c)

编辑:发布此内容后,我想我最好对其进行测试以确保它确实有效。在这样做的过程中,我发现了另一个问题。调用函数时应避免在逗号和参数之间添加空格。它会导致在传递给函数的参数前面添加一个文字空格字符,并导致意外的结果。我已经删除了我的版本中函数调用中逗号后面的空格(虽然这对于 join 的调用来说不是问题,但我也删除了那里的空格,因为这是一个好习惯进入)。

You need to double escape virtually all of the functions and variables when you use eval. In most cases, the only things that don't need to be double-escaped are function arguments (because the call function will fully expand them). In this case, you technically don't need to double-escape join or SRC_DIR either, but it will simplify your life if you just always double-escape all variables and functions when using eval.

The reason you need the double escapes is that expansion happens twice when using eval. The eval function itself performs expansion, and then expansion is done again when the block is finally parsed as makefile syntax (i.e. when it is actually evaluated).

The way you've got it written, wildcard is invoked on the string literal $( test_SRC_DIR)*.c. If you want, you can see this for yourself by replacing wildcard with info in your version and see what happens.

You need to hold off on actually invoking wildcard until the second expansion, so that it's argument is the result of the expansion of $(test_SRC_DIR).

Try this:

SRC_DIR = ./src/

PROG_NAME = test

define PROGRAM_template
  $(1)_SRC_DIR = $(join $(SRC_DIR),$(1)/)
  $(1)_SRC_FILES = $(wildcard $($(1)_SRC_DIR)*.c)
endef

$(eval $(call PROGRAM_template,$(PROG_NAME)))

all:
    @echo $(test_SRC_DIR)
    @echo $(test_SRC_FILES)
    @echo $(wildcard $(test_SRC_DIR)*.c)

EDIT: After posting this, I thought I'd better test it out to make sure it actually works. In doing so, I discovered another problem. You should avoid putting spaces between the comma and argument when calling functions. It causes a literal space character to be prepended to the argument that is passed to the function and leads to unintended results. I've removed the spaces after the commas in the function calls in my version (while this isn't a problem for the call to join, I removed the space there as well just because it's a good habit to get into).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文