2010-03-10 51 views
8

我正在尝试为我的Makefiles创建一个通用构建模板,有点像他们在eval documentation中讨论的那样。

我似乎无法得到通配符函数在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) 

当我运行与这,输出

./src/test 

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

基本上,内PROGRAM_template通配符通话不被我希望它eval'd。通话结果为空列表。
虽然正在评估联合调用。

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

$$($(1)_SRC_DIR) 

是不正确的,但我无法弄清楚正确的做法。

编辑 一旦解决了这个问题,我花了很长时间才用eval来打另一个问题。 我张贴它作为一个新的问题,在 Workaround for GNU Make 3.80 eval bug

回答

10

你需要加倍逃避几乎所有的函数和变量,当您使用eval。在大多数情况下,不必需要双重转义的函数参数(因为call函数将完全展开它们)。在这种情况下,您在技术上不需要双重转义joinSRC_DIR,但如果您在使用eval时总是双重转义所有变量和函数,它将简化您的生活。

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

你写的方式,wildcard被调用的字符串文字$(test_SRC_DIR)*.c。如果你愿意,你可以在你的版本中用info代替wildcard,看看会发生什么。

你需要暂缓实际调用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) 

编辑:张贴在此之后,我想我会更好地测试它,以确保它的实际工作。在这样做的时候,我发现了另一个问题。调用函数时,应避免在逗号和参数之间放置空格。它导致一个字面空格字符被前置到传递给该函数的参数,并导致意想不到的结果。我删除了我的版本中函数调用后的逗号(虽然这对调用join来说不是问题,但我只是因为这是一个很好的习惯才去掉了这个空间)。

+0

谢谢! 我正准备评论它没有用,然后我回来看到你的编辑。 看起来像 $(1)_SRC_DIR = $$(join $$(SRC_DIR),$(1)/) 也符合我的要求,但对于$(通配符)行,您需要$$。 – bengineerd 2010-03-11 02:20:27

+0

@bengineerd:是的,我已经澄清了我的答案。你不需要'join'和'SRC_DIR'上的双重转义,因为只需一次扩展就可以完全扩展。但是,就像我说的那样,只是总是使用双重转义,这会让生活更轻松。当他们不需要时,他们不会伤害任何东西。 – 2010-03-11 02:23:43