GNU Make:如何在$(eval)中调用$(通配符)

ben*_*erd 8 makefile eval gnu-make

我正在尝试为我的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)
Run Code Online (Sandbox Code Playgroud)

当我用它运行make时,输出是

./src/test

[correct list of all .c files in ./src/test/]
Run Code Online (Sandbox Code Playgroud)

基本上,PROGRAM_template中的通配符调用没有像我预期的那样被评估.该调用导致一个空列表.
尽管如此,正在正确评估联接调用.

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

$$($(1)_SRC_DIR) 
Run Code Online (Sandbox Code Playgroud)

是不正确的,但我无法找到正确的方法.

编辑 一旦解决了这个问题,我花了很长时间才能用eval来解决另一个问题.我在GNU Make 3.80评估错误的解决方法中将其作为一个新问题发布

Dan*_*ing 10

使用时,您需要双重转义几乎所有的函数和变量eval.在大多数情况下,只表示事情并不需要是双重逸出是函数的参数(因为该call功能将全面展开它们).在这种情况下,从技术上讲,您不需要双重转义join或者SRC_DIR其中任何一个,但如果您在使用时总是双重转义所有变量和函数,它将简化您的生活eval.

您需要双重转义的原因是使用时扩展会发生两次eval.该eval功能本身执行扩展,然后扩展完成再次当块最终解析为生成文件的语法(即,当它实际评价).

编写它的方式wildcard是在字符串文字上调用的$( test_SRC_DIR)*.c.如果你愿意,你可以通过更换看到自己wildcardinfo你的版本,看看会发生什么.

你需要推迟实际调用,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)
Run Code Online (Sandbox Code Playgroud)

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