如何在仅限订单的先决条件中调用函数



给定Makefile的这一位:

# for pattern matching
$(OBJDIR) := build
# just to see if a level of indirection will work
my_dir = $(dir $(1))
$(OBJECTS) : $(OBJDIR)/% : $(HEADERS) $(SRCDIR)/% | % $(dir %) $(call my_dir,%)
  @echo output-only = $|

这是一个静态模式规则,具有仅限顺序的先决条件。

考虑目标"build/putility/debug.js"。上面规则的输出是:

output-only = utility/debug.js ./
  • 第一个组件"utility/debug.js"是从stem(%)中正确复制的
  • 第二个组件"./"是调用先决条件列表中的dir函数的输出
  • 第三个组件是一个空字符串,它是调用先决条件列表中的my_dir函数的输出

如果我将my_dir更改为:

my_dir = $(1)

输出保持不变。如果我把它改成这个:

my_dir = "foo"

然后make抱怨没有规则生成"foo"(这是预期的)。那么,在对my_dir的调用中,$(1)似乎没有被绑定。

怎么回事?为什么我不能将词干传递给函数?我有一个使用二次扩展的解决方法,但我想知道为什么我不能用这种方式编写规则。

编辑:我是stackoverflow的新手,如果这里不是这样做的,请原谅我。

正如Alex所指出的,我想要$(1),因为我将词干作为参数传递给my_dir

我不知道为什么有人建议我要"$"。我不相信美元本身会在任何情况下扩展到任何东西。

我知道自动变量只在配方中可用。我没有在先决条件中使用自动变量-我使用的是词干:

每个目标都与目标模式相匹配,以提取目标名称的一部分,称为词干。这个词干被替换到每个prereq模式中,以形成先决条件名称(每个preeq模式中有一个)。-手动

这个例子证明了词干是可用的:当单独使用时,词干会扩展到正确的值,但当传递给函数时则不会。

正如GNU make手册的这一部分所示,在读入阶段,先决条件列表中的变量和函数引用会立即展开。这意味着,在进行任何模式匹配之前,%还没有特殊意义;它被解释为两个函数引用$(dir %)$(call my_dir,%)中的文字字符,这两个函数的结果都是./,它们被合并到配方中对$|的引用中。

除了您已经找到的解决方案,即二次扩展,我不知道还有其他解决方案。

注意$1不是一个特殊的变量,它可以扩展到与模式规则(或静态模式规则)相关的任何有趣的内容。$1变量仅在$(call ...)函数调用的用户定义宏的上下文中具有唯一行为。

您希望使用$*,而不是$1$*是一个自动变量,它扩展到规则目标的词干。

然而,在所有版本的make(包括make的POSIX标准定义)中,自动变量(包括$*$<$@$^等)仅在配方的上下文中可用。它们在目标或先决条件列表中不可用。有关更多详细信息,请参阅GNU make手册中关于自动变量的部分。

正如您所建议的,有一个GNU特定于make的功能是由.SECONDEXPANSION伪目标启用的,它提供了一种避免这种限制的方法。

最新更新