这个 Makefile 语句的含义是什么?

What's the meaning of this Makefile statement?

${COMPILE_PATH}/%.c.d:%.cpp
$(CC) $(CFLAGS) ${CFLAGS_NDBG} -MM -E $^ > $@
@sed 's/.*\.o/$(subst /,\/, $(dir $@))&/g' $@ >$@.tmp
@mv $@.tmp $@

$(subst /,\/, $(dir $@)),这个说法我看不懂,subst的第二个参数是\/,为什么?将 / 更改为 \/?

因为它被用在 sed 命令中,其中 / 将被视为 s/// 命令的结尾。

也就是说,另一种解决方案(假设您可以保证目录名称中哪些字符是合法的)本来可以为 s/// 使用不同的分隔符,例如 ; (即 s;.*\.o;$(dir $@)&;g)或 !(即 s!.*\.o!$(dir $@)&!g

他们似乎正在将 / 更改为转义版本。

路径中的斜杠需要转义,因为 sed 脚本使用斜杠作为正则表达式分隔符。未转义的斜杠会过早地终止替换表达式。

但是,解决此问题的更好方法是使用备用分隔符——sed 允许您在此处使用任何标点符号;斜线只是一个常见的默认值。

临时文件也是一个很容易避免的缺点。

${COMPILE_PATH}/%.c.d:%.cpp
    $(CC) $(CFLAGS) ${CFLAGS_NDBG} -MM -E $^ \
    | sed 's|.*\.o|$(dir $@)/&|g' >$@

(我猜 g 标志在这里实际上也是完全多余的。)