makefile - 为什么在使用 $$* 的二次扩展时 patsubst 停止工作?

标签 makefile gnu-make

这是来自 GNU Make manual section on Secondary Expansion 的示例(稍微简化):

foo_SRCS := bar.c baz.c

.SECONDEXPANSION:
# $$@ expands to the target ("foo" in this case)
foo: $$(patsubst %.c,%.o,$$($$@_SRCS))

这很好用;它构建 bar.obaz.o:

cc    -c -o bar.o bar.c
cc    -c -o baz.o baz.c

但是如果我稍微调整一下这个例子,patsubst就会停止工作:

all: foo.a

foo_SRCS := bar.c baz.c

.SECONDEXPANSION:
# $$* expands to the stem of the match ("foo" in this case).
%.a: $$(patsubst %.c,%.o,$$($$*_SRCS))
        ar rcs $@ $^

它不再构建 bar.obaz.o,而是直接使用 *.c 文件作为先决条件!

ar rcs foo.a bar.c baz.c

请注意,$$($$*_SRCS) 部分显然正在工作,它找到 foo_SRCS 并将其用作先决条件这一事实就证明了这一点。但由于某种原因,patsubst 部分已变成无操作!它没有将 %.c 替换为 %.o,而是直接使用 foo_SRCS

这是怎么回事?我怎样才能让我的例子工作?

编辑:我有一个理论,即 patsubst 中的 % 字符会使用词干匹配 (foo) 进行早期评估,因此 patsubst 本身看起来像是像这样的东西:

$(patsubst foo.c,foo.o,bar.c baz.c)

为了测试这个理论,我向 foo_SRCS 添加了一个名为 foo.c 的文件:

all: foo.a

foo_SRCS := foo.c bar.c baz.c

.SECONDEXPANSION:
# $$* expands to the stem of the match ("foo" in this case).
%.a: $$(patsubst %.c,%.o,$$($$*_SRCS))
        ar rcs $@ $^

这导致了更奇怪的事情:

make: *** No rule to make target `foo.a', needed by `all'.  Stop.

最佳答案

百分比字符被 make 读取为与词干中的通配符匹配,并被替换为词干匹配。如果您检查示例的 make -p 输出,您将看到解析的目标行如下所示:

%.a: $(patsubst %.c,%.o,$($*_SRCS))

就 make 而言,这只是一组非常奇怪的模式目标(或类似的东西)。

如果您以与从 make 评估中转义 $ 类似的方式从 make 解析中转义百分比字符,您可以获得您想要的结果:

pc := %
$$(patsubst $$(pc).c,$$(pc).o,$$($$*_SRCS))

了解更多信息 substitution references (即 $(foo_SRCS:.c=.o))可用于此类转换,以代替对 patsubst 的较长调用。然而,在这种情况下,虽然它在这种情况下使用类似的 : 转义(通过 c := :),但它似乎并不作为唯一的先决条件至少在 GNU Make 3.81 中,目标(make 给出 Makefile:23: *** 命令在第一个目标之前开始。停止。 错误,我不太明白)。

关于makefile - 为什么在使用 $$* 的二次扩展时 patsubst 停止工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25589586/

相关文章:

linux - 在 shell 脚本中使用 makefile 变量而不运行 make

检查 'make'包括哪些文件

c++ - 非常非常基本 : Why won't my makefile work

makefile - 无法覆盖特定于目标的变量

android - 如何使用 Gnu makefile 为库编写 Android.mk

gcc - make 删除依赖文件

具有不同源类型的 Makefile

makefile - 是否可以在 Makefile 的同一个目标中有多个先决条件模式?

windows - 在 jom/nmake 读取的 makefile 中设置环境变量

makefile - 如何匹配目标中的双词干,如 %/% 或其他方式?