【发布时间】:2020-06-23 10:19:51
【问题描述】:
在我的工作目录中,有一个makefile、一个空的obj 文件夹和一个包含foo.c 的src 文件夹。我有一个简单的规则,它接受一个目标文件,用 src 替换第一个斜杠之前的所有内容,并用 .c 替换结尾的 .o。
示例: obj/foo.o --> src/foo.c
在 MadScientist 的帮助下(感谢他)我得到了下面的模式规则(请不要提出更简单的规则 --> 我知道它们的存在,但只有这条规则说明了我的问题):
OBJFILES=obj/foo.o
all: $(OBJFILES)
@echo "all executed"
Y = $(shell echo $1 | sed -e 's,^[^\/]*,src,' -e 's,\.o$$,.c,')
.SECONDEXPANSION:
%.o: $$(call Y,$$@)
@echo "OBJECTS executed for $@ - [$^]"
src/foo.c:
@echo "Congrats"
运行上面的 makefile 后,我得到一个循环依赖:
xxxx@null:~/Desktop/experiment$ make
make: Circular src.o <- src dependency dropped.
OBJECTS executed for obj/foo.o - [src/foo.c]
all executed
原因很快就找到了:Make 创建了隐式规则Makefile: Makefile.o,它触发了我的模式规则。由于Makefile.o 不包含斜线,因此sed 的计算结果为src。 Make 再次应用隐式规则 src:src.o 最终导致循环依赖。这可以在 make 输出中看到:
make --print-data-base | grep src
make: Circular src.o <- src dependency dropped.
OBJECTS executed for obj/foo.o - [src/foo.c]
Y = $(shell echo $1 | sed -e 's,^[^\/]*,src,' -e 's,\.o$$,.c,')
# src (device 64769, inode 14031369): No files, no impossibilities so far.
Makefile.o: src
src: src.o
# Implicit/static pattern stem: 'src'
src.o:
# Implicit/static pattern stem: 'src'
# @ := src.o
# * := src
# < := src.o
obj/foo.o: src/foo.c
# + := src/foo.c
# < := src/foo.c
# ^ := src/foo.c
# ? := src/foo.c
src/foo.c:
如果我们现在以这种方式重新定义Y:Y = $(patsubst obj/%.o,src/%.c,$1),则不会发生循环依赖,因为make 甚至不会尝试应用隐式规则Makefile:Makefile.o
make --print-data-base | grep src
OBJECTS executed for obj/foo.o - [src/foo.c]
Y = $(patsubst obj/%.o,src/%.c,$1)
# src (device 64769, inode 14031369): No files, no impossibilities so far.
obj/foo.o: src/foo.c
# + := src/foo.c
# < := src/foo.c
# ^ := src/foo.c
# ? := src/foo.c
src/foo.c:
make 何时创建隐式规则Makefile: Makefile.o? Y的两种不同定义有什么区别?
【问题讨论】: