9

我正在尝试为我的 Makefile 创建一个通用的构建模板,就像他们在eval 文档中讨论的那样。

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

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 bug 的解决方法

4

1 回答 1

11

当您使用eval. 在大多数情况下,唯一不需要双重转义的是函数参数(因为call函数将完全扩展它们)。在这种情况下,从技术上讲,您不需要双重转义joinSRC_DIR但如果您在使用eval.

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

您编写它的方式wildcard是在字符串文字上调用的$( test_SRC_DIR)*.cwildcard如果您愿意,您可以通过在您的版本中替换为自己来查看这一点,info然后看看会发生什么。

您需要推迟实际调用wildcard,直到第二次扩展,以便它的参数是扩展的结果 $(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)

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).

于 2010-03-11T01:45:14.670 回答