makefile 中的 patsubst 不会扩展变量

variable doesn't get exanded for patsubst in makefile

我正在尝试编写一个规则,将一组 .c 文件替换为一个变量的 .o 文件。

为确保它有效,我赞同他们的价值观。 .c 文件是通过 shell 通配符

从当前工作目录获取的
sources := *.c

但是,.o 文件没有打印出任何内容,因为 'sources' 似乎没有为此进行扩展,无论我是使用 patsubst 还是更方便的 $(src:%.c= %.o).

另一方面,如果我设置 'manually' 的值,一切都会按预期工作,例如

sources := source1.c source2.c source3.c

生成文件:

sources := *.c
srcs = one.c two.c
objects := $(sources:.c=.o)
objs := $(patsubst %.c, %.o, $(srcs))

prints:
    @echo sources
    @echo $(sources)
    @echo objects
    @echo $(objects)
    @echo $(objs)

输出:

sources
source1.c source2.c source3.c source4.c
objects
*.o
one.o two.o

如您所见,'objects'(基于使用通配符 'sources')是不行的,但是 'objs'(基于手动设置的 'srcs' 按预期工作)。

我错过了什么。我知道这一定与扩张发生的时间或方式有关。

Make 不是shell。这一行:

sources := *.c

将 make 变量 sources 设置为文字字符串 *.c。然后这一行:

objects := $(sources:.c=.o)

objects 设置为文字字符串 *.o

然后这一行:

@echo $(sources)

echo *.c 发送到 shell,SHELL 将 *.c 扩展到与该 glob 匹配的文件列表。

然后这一行:

@echo $(objects)

echo *.o 发送到 shell,并且由于没有文件匹配 *.o glob,它只打印 glob 本身 *.o.

如果你想在 make 中获得文件列表 你必须使用 wildcard 函数:

sources := $(wildcard *.c)

此外,您还遇到了人们在尝试调试 makefile 时犯的两种不同的常见错误:

首先,你不应该,永远在你的配方行中使用@来隐藏命令。这就像试图在蒙上眼睛的情况下调试您的 makefile。查看 make 发送到 shell 的内容可为您提供有关此处发生的事情的绝对重要信息。我个人不使用 @ 即使在我的 makefile 工作之后,除了一些琐碎的操作,我绝对不会在尝试调试时使用它。

其次,如果您想在食谱中查看 make 变量的内容,您应该 始终 在它们周围使用单引号。如果您将它们不加引号或使用双引号,那么 shell 将会出现并弄乱这些值(取决于值是什么)并且您将无法看到它们的真实含义。要么在它们周围使用 '',要么使用像 $(info ...) 这样的 make 函数来查看它们的值,而不是像 echo.

这样的 shell 程序

如果您的测试 makefile 是这样写的:

prints:
        echo sources
        echo '$(sources)'
        echo objects
        echo '$(objects)'
        echo '$(objs)'

问题出在哪里会更加明显。