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)'
问题出在哪里会更加明显。
我正在尝试编写一个规则,将一组 .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
.
如果您的测试 makefile 是这样写的:
prints:
echo sources
echo '$(sources)'
echo objects
echo '$(objects)'
echo '$(objs)'
问题出在哪里会更加明显。